diff --git a/DEPS b/DEPS
index e0accf5..39f6eede7 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '3692957d2864e013fb324de5d652fe4bdcbd71b9',
+  'v8_revision': '908a6304467d88447cf9e497581f4c970c09e750',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -64,7 +64,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '26cb2fa42b1a90146f9ab5c0b83ee8b48703baf4',
+  'pdfium_revision': '5be0b291bce26e1a12c9a7becb7c9a9e7857a456',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -96,7 +96,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'e6ad06342efb08256f35c2605ac9c3be87a3e770',
+  'catapult_revision': 'de3ade508f3ff869e7bc63bd6b9a6765afb74774',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 0a9282f..2752765 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -191,26 +191,22 @@
     (
       'ScopedAllowIO',
       (
-       'New code should not use ScopedAllowIO. Post a task to the blocking',
-       'pool or the FILE thread instead.',
+       'New production code should not use ScopedAllowIO (using it in',
+       'browser tests is fine). Post a task to the blocking pool or the',
+       'FILE thread instead.',
       ),
       True,
       (
+        r"^.*browser(|_)test[a-z_]*\.cc$",
         r"^base[\\\/]memory[\\\/]shared_memory_posix\.cc$",
         r"^base[\\\/]process[\\\/]internal_aix\.cc$",
         r"^base[\\\/]process[\\\/]process_linux\.cc$",
         r"^base[\\\/]process[\\\/]process_metrics_linux\.cc$",
         r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]boot_times_recorder\.cc$",
         r"^chrome[\\\/]browser[\\\/]lifetime[\\\/]application_lifetime\.cc$",
-        r"^chrome[\\\/]browser[\\\/]chromeos[\\\/]"
-            "customization_document_browsertest\.cc$",
-        r"^chrome[\\\/]test[\\\/]media_router[\\\/]" +
-            r"media_router_integration_browsertest\.cc$",
-        r"^chrome[\\\/]test[\\\/]ppapi[\\\/]ppapi_filechooser_browsertest\.cc$",
         r"^components[\\\/]crash[\\\/]app[\\\/]breakpad_mac\.mm$",
         r"^content[\\\/]shell[\\\/]browser[\\\/]layout_test[\\\/]" +
             r"test_info_extractor\.cc$",
-        r"^content[\\\/].*browser(|_)test[a-zA-Z_]*\.cc$",
         r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
         r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
         r"^content[\\\/]test[\\\/]ppapi[\\\/]ppapi_test\.cc$",
diff --git a/chrome/browser/chrome_quota_permission_context.cc b/chrome/browser/chrome_quota_permission_context.cc
index 59718057..b4921431 100644
--- a/chrome/browser/chrome_quota_permission_context.cc
+++ b/chrome/browser/chrome_quota_permission_context.cc
@@ -36,11 +36,9 @@
 
 namespace {
 
-#if defined(OS_ANDROID)
-// If the site requested larger quota than this threshold, show a different
-// message to the user.
+// On Android, if the site requested larger quota than this threshold, show a
+// different message to the user.
 const int64_t kRequestLargeQuotaThreshold = 5 * 1024 * 1024;
-#endif
 
 // QuotaPermissionRequest ---------------------------------------------
 
@@ -49,6 +47,7 @@
   QuotaPermissionRequest(
       ChromeQuotaPermissionContext* context,
       const GURL& origin_url,
+      bool is_large_quota_request_,
       const content::QuotaPermissionContext::PermissionCallback& callback);
 
   ~QuotaPermissionRequest() override;
@@ -56,6 +55,9 @@
  private:
   // PermissionRequest:
   IconId GetIconId() const override;
+#if defined(OS_ANDROID)
+  base::string16 GetMessageText() const override;
+#endif
   base::string16 GetMessageTextFragment() const override;
   GURL GetOrigin() const override;
   void PermissionGranted() override;
@@ -64,8 +66,9 @@
   void RequestFinished() override;
   PermissionRequestType GetPermissionRequestType() const override;
 
-  scoped_refptr<ChromeQuotaPermissionContext> context_;
-  GURL origin_url_;
+  const scoped_refptr<ChromeQuotaPermissionContext> context_;
+  const GURL origin_url_;
+  const bool is_large_quota_request_;
   content::QuotaPermissionContext::PermissionCallback callback_;
 
   DISALLOW_COPY_AND_ASSIGN(QuotaPermissionRequest);
@@ -74,10 +77,15 @@
 QuotaPermissionRequest::QuotaPermissionRequest(
     ChromeQuotaPermissionContext* context,
     const GURL& origin_url,
+    bool is_large_quota_request,
     const content::QuotaPermissionContext::PermissionCallback& callback)
     : context_(context),
       origin_url_(origin_url),
-      callback_(callback) {}
+      is_large_quota_request_(is_large_quota_request),
+      callback_(callback) {
+  // Suppress unused private field warning on desktop
+  (void)is_large_quota_request_;
+}
 
 QuotaPermissionRequest::~QuotaPermissionRequest() {}
 
@@ -90,6 +98,17 @@
 #endif
 }
 
+#if defined(OS_ANDROID)
+base::string16 QuotaPermissionRequest::GetMessageText() const {
+  // If the site requested larger quota than this threshold, show a different
+  // message to the user.
+  return l10n_util::GetStringFUTF16(
+      (is_large_quota_request_ ? IDS_REQUEST_LARGE_QUOTA_INFOBAR_QUESTION
+                               : IDS_REQUEST_QUOTA_INFOBAR_QUESTION),
+      url_formatter::FormatUrlForSecurityDisplay(origin_url_));
+}
+#endif
+
 base::string16 QuotaPermissionRequest::GetMessageTextFragment() const {
   return l10n_util::GetStringUTF16(IDS_REQUEST_QUOTA_PERMISSION_FRAGMENT);
 }
@@ -267,8 +286,10 @@
     PermissionRequestManager* permission_request_manager =
         PermissionRequestManager::FromWebContents(web_contents);
     if (permission_request_manager) {
-      permission_request_manager->AddRequest(
-          new QuotaPermissionRequest(this, params.origin_url, callback));
+      bool is_large_quota_request =
+          params.requested_size > kRequestLargeQuotaThreshold;
+      permission_request_manager->AddRequest(new QuotaPermissionRequest(
+          this, params.origin_url, is_large_quota_request, callback));
       return;
     }
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
index 1c0ffcd..5fd289d 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
@@ -28,6 +28,7 @@
 #include "extensions/common/permissions/permissions_data.h"
 #include "extensions/test/extension_test_message_listener.h"
 #include "extensions/test/result_catcher.h"
+#include "ui/base/ui_features.h"
 
 #if defined(OS_WIN)
 #include "ui/views/win/hwnd_util.h"
@@ -44,6 +45,12 @@
   BrowserActionInteractiveTest() {}
   ~BrowserActionInteractiveTest() override {}
 
+  // BrowserTestBase:
+  void SetUpOnMainThread() override {
+    ExtensionApiTest::SetUpOnMainThread();
+    EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+  }
+
  protected:
   // Function to control whether to run popup tests for the current platform.
   // These tests require RunExtensionSubtest to work as expected and the browser
@@ -53,17 +60,20 @@
     // TODO(justinlin): http://crbug.com/177163
 #if defined(OS_WIN) && !defined(NDEBUG)
     return false;
-#elif defined(OS_MACOSX)
-    // TODO(justinlin): Browser window do not become active on Mac even when
-    // Activate() is called on them. Enable when/if it's possible to fix.
-    return false;
 #else
     return true;
 #endif
   }
 
+  void EnsurePopupActive() {
+    BrowserActionTestUtil test_util(browser());
+    EXPECT_TRUE(test_util.HasPopup());
+    EXPECT_TRUE(test_util.WaitForPopup());
+    EXPECT_TRUE(test_util.HasPopup());
+  }
+
   // Open an extension popup via the chrome.browserAction.openPopup API.
-  void OpenExtensionPopupViaAPI() {
+  void OpenPopupViaAPI() {
     // Setup the notification observer to wait for the popup to finish loading.
     content::WindowedNotificationObserver frame_observer(
         content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
@@ -72,7 +82,46 @@
     ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
                                     "open_popup_succeeds.html")) << message_;
     frame_observer.Wait();
+    EnsurePopupActive();
+  }
+
+  // Open an extension popup by clicking the browser action button.
+  void OpenPopupViaToolbar() {
+    content::WindowedNotificationObserver frame_observer(
+        content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
+        content::NotificationService::AllSources());
+    BrowserActionTestUtil(browser()).Press(0);
+    frame_observer.Wait();
+    EnsurePopupActive();
+  }
+
+  // Trigger a focus loss to close the popup.
+  void ClosePopupViaFocusLoss() {
     EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
+    content::WindowedNotificationObserver observer(
+        extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
+        content::NotificationService::AllSources());
+
+#if defined(OS_MACOSX)
+    // ClickOnView() in an inactive window is not robust on Mac. The click does
+    // not guarantee window activation on trybots. So activate the browser
+    // explicitly, thus causing the bubble to lose focus and dismiss itself.
+    // This works because bubbles on Mac are always toplevel.
+    EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
+#else
+    // Elsewhere, click on the omnibox. Note that with aura, the browser may be
+    // "active" the entire time when the popup is not a toplevel window. It's
+    // aura::Window::Focus() that determines where key events go in this case.
+    ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX);
+#endif
+
+    // The window disappears immediately.
+    EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
+
+    // Wait for the notification to achieve a consistent state and verify that
+    // the popup was properly torn down.
+    observer.Wait();
+    base::RunLoop().RunUntilIdle();
   }
 };
 
@@ -87,7 +136,7 @@
   // Setup extension message listener to wait for javascript to finish running.
   ExtensionTestMessageListener listener("ready", true);
   {
-    OpenExtensionPopupViaAPI();
+    OpenPopupViaAPI();
     EXPECT_TRUE(browserActionBar.HasPopup());
     browserActionBar.HidePopup();
   }
@@ -205,15 +254,7 @@
   ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
                                   "open_popup_fails.html")) << message_;
   EXPECT_TRUE(listener.WaitUntilSatisfied());
-
-  content::WindowedNotificationObserver frame_observer(
-      content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
-      content::NotificationService::AllSources());
-  // Open popup in the first extension.
-  BrowserActionTestUtil(browser()).Press(0);
-  frame_observer.Wait();
-  EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
-
+  OpenPopupViaToolbar();
   ResultCatcher catcher;
   // Return control to javascript to validate that opening a popup fails now.
   listener.Reply("show another");
@@ -227,7 +268,7 @@
   if (!ShouldRunPopupTest())
     return;
 
-  OpenExtensionPopupViaAPI();
+  OpenPopupViaAPI();
   ExtensionService* service = extensions::ExtensionSystem::Get(
       browser()->profile())->extension_service();
   ASSERT_FALSE(
@@ -239,34 +280,23 @@
               APIPermission::kTab));
 }
 
-// Test that the extension popup is closed when the browser window is clicked.
-IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, BrowserClickClosesPopup1) {
+// Test that the extension popup is closed when the browser window is focused.
+IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, FocusLossClosesPopup1) {
   if (!ShouldRunPopupTest())
     return;
-
-  // Open an extension popup via the chrome.browserAction.openPopup API.
-  content::WindowedNotificationObserver frame_observer(
-      content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
-      content::NotificationService::AllSources());
-  ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
-                                  "open_popup_succeeds.html")) << message_;
-  frame_observer.Wait();
-  EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
-
-  // Click on the omnibox to close the extension popup.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX);
-  EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
+  OpenPopupViaAPI();
+  ClosePopupViaFocusLoss();
 }
 
-// Test that the extension popup is closed when the browser window is clicked.
+// Test that the extension popup is closed when the browser window is focused.
 #if defined(OS_WIN)
 // Flaky on Windows: http://crbug.com/639130
-#define MAYBE_BrowserClickClosesPopup2 DISABLED_BrowserClickClosesPopup2
+#define MAYBE_FocusLossClosesPopup2 DISABLED_FocusLossClosesPopup2
 #else
-#define MAYBE_BrowserClickClosesPopup2 BrowserClickClosesPopup2
+#define MAYBE_FocusLossClosesPopup2 FocusLossClosesPopup2
 #endif
 IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
-                       MAYBE_BrowserClickClosesPopup2) {
+                       MAYBE_FocusLossClosesPopup2) {
   if (!ShouldRunPopupTest())
     return;
 
@@ -275,18 +305,8 @@
       "browser_action/popup")));
   const Extension* extension = GetSingleLoadedExtension();
   ASSERT_TRUE(extension) << message_;
-
-  // Open an extension popup by clicking the browser action button.
-  content::WindowedNotificationObserver frame_observer(
-      content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
-      content::NotificationService::AllSources());
-  BrowserActionTestUtil(browser()).Press(0);
-  frame_observer.Wait();
-  EXPECT_TRUE(BrowserActionTestUtil(browser()).HasPopup());
-
-  // Click on the omnibox to close the extension popup.
-  ui_test_utils::ClickOnView(browser(), VIEW_ID_OMNIBOX);
-  EXPECT_FALSE(BrowserActionTestUtil(browser()).HasPopup());
+  OpenPopupViaToolbar();
+  ClosePopupViaFocusLoss();
 }
 
 // Test that the extension popup is closed on browser tab switches.
@@ -299,7 +319,7 @@
   ASSERT_EQ(2, browser()->tab_strip_model()->count());
   EXPECT_EQ(browser()->tab_strip_model()->GetWebContentsAt(1),
             browser()->tab_strip_model()->GetActiveWebContents());
-  OpenExtensionPopupViaAPI();
+  OpenPopupViaAPI();
 
   content::WindowedNotificationObserver observer(
       extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
@@ -317,7 +337,7 @@
     return;
 
   // First, we open a popup.
-  OpenExtensionPopupViaAPI();
+  OpenPopupViaAPI();
   BrowserActionTestUtil browser_action_test_util(browser());
   EXPECT_TRUE(browser_action_test_util.HasPopup());
 
@@ -336,9 +356,15 @@
   EXPECT_FALSE(browser_action_test_util.HasPopup());
 }
 
-#if defined(TOOLKIT_VIEWS)
+// BrowserActionTestUtil::InspectPopup() is not implemented for a Cocoa browser.
+#if !defined(OS_MACOSX) || BUILDFLAG(MAC_VIEWS_BROWSER)
+#define MAYBE_CloseBrowserWithDevTools CloseBrowserWithDevTools
+#else
+#define MAYBE_CloseBrowserWithDevTools DISABLED_CloseBrowserWithDevTools
+#endif
 // Test closing the browser while inspecting an extension popup with dev tools.
-IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, CloseBrowserWithDevTools) {
+IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
+                       MAYBE_CloseBrowserWithDevTools) {
   if (!ShouldRunPopupTest())
     return;
 
@@ -359,7 +385,6 @@
   // Close the browser window, this should not cause a crash.
   chrome::CloseWindow(browser());
 }
-#endif  // TOOLKIT_VIEWS
 
 #if defined(OS_WIN)
 // Test that forcibly closing the browser and popup HWND does not cause a crash.
@@ -369,7 +394,7 @@
   if (!ShouldRunPopupTest())
     return;
 
-  OpenExtensionPopupViaAPI();
+  OpenPopupViaAPI();
   BrowserActionTestUtil test_util(browser());
   const gfx::NativeView view = test_util.GetPopupNativeView();
   EXPECT_NE(static_cast<gfx::NativeView>(NULL), view);
diff --git a/chrome/browser/extensions/browser_action_test_util.h b/chrome/browser/extensions/browser_action_test_util.h
index 4bdeedf..cf90784 100644
--- a/chrome/browser/extensions/browser_action_test_util.h
+++ b/chrome/browser/extensions/browser_action_test_util.h
@@ -69,6 +69,10 @@
 
   gfx::NativeView GetPopupNativeView();
 
+  // Spins a RunLoop until the NativeWindow hosting |GetPopupNativeView()| is
+  // reported as active by the OS. Returns true if successful.
+  bool WaitForPopup();
+
   // Returns whether a browser action popup is being shown currently.
   bool HasPopup();
 
diff --git a/chrome/browser/media/midi_permission_context.cc b/chrome/browser/media/midi_permission_context.cc
index f137ee5..126506a 100644
--- a/chrome/browser/media/midi_permission_context.cc
+++ b/chrome/browser/media/midi_permission_context.cc
@@ -20,5 +20,5 @@
 }
 
 bool MidiPermissionContext::IsRestrictedToSecureOrigins() const {
-  return true;
+  return false;
 }
diff --git a/chrome/browser/media/midi_permission_context_unittest.cc b/chrome/browser/media/midi_permission_context_unittest.cc
new file mode 100644
index 0000000..2f215c1
--- /dev/null
+++ b/chrome/browser/media/midi_permission_context_unittest.cc
@@ -0,0 +1,47 @@
+// Copyright 2017 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 "chrome/browser/media/midi_permission_context.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/content_settings/core/common/content_settings.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class MidiPermissionContextTests : public testing::Test {
+ public:
+  TestingProfile* profile() { return &profile_; }
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
+  TestingProfile profile_;
+};
+
+// Web MIDI permission status should be allowed for all origins.
+TEST_F(MidiPermissionContextTests, TestNoSysexAllowedAllOrigins) {
+  MidiPermissionContext permission_context(profile());
+  GURL insecure_url("http://www.example.com");
+  GURL secure_url("https://www.example.com");
+
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            permission_context
+                .GetPermissionStatus(nullptr /* render_frame_host */,
+                                     insecure_url, insecure_url)
+                .content_setting);
+
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            permission_context
+                .GetPermissionStatus(nullptr /* render_frame_host */,
+                                     insecure_url, secure_url)
+                .content_setting);
+
+  EXPECT_EQ(CONTENT_SETTING_ALLOW,
+            permission_context
+                .GetPermissionStatus(nullptr /* render_frame_host */,
+                                     secure_url, secure_url)
+                .content_setting);
+}
+
+}  // namespace
diff --git a/chrome/browser/media/midi_sysex_permission_context_unittest.cc b/chrome/browser/media/midi_sysex_permission_context_unittest.cc
index 72e3c1b..0ddf724 100644
--- a/chrome/browser/media/midi_sysex_permission_context_unittest.cc
+++ b/chrome/browser/media/midi_sysex_permission_context_unittest.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/media/midi_sysex_permission_context.h"
 #include "base/bind.h"
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/media/midi_permission_context.h"
 #include "chrome/browser/permissions/permission_request_id.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
@@ -26,10 +26,10 @@
 
 namespace {
 
-class TestPermissionContext : public MidiPermissionContext {
+class TestPermissionContext : public MidiSysexPermissionContext {
  public:
   explicit TestPermissionContext(Profile* profile)
-      : MidiPermissionContext(profile),
+      : MidiSysexPermissionContext(profile),
         permission_set_(false),
         permission_granted_(false),
         tab_context_updated_(false) {}
@@ -62,9 +62,9 @@
 
 }  // anonymous namespace
 
-class MidiPermissionContextTests : public ChromeRenderViewHostTestHarness {
+class MidiSysexPermissionContextTests : public ChromeRenderViewHostTestHarness {
  protected:
-  MidiPermissionContextTests() = default;
+  MidiSysexPermissionContextTests() = default;
 
  private:
   // ChromeRenderViewHostTestHarness:
@@ -77,11 +77,11 @@
 #endif
   }
 
-  DISALLOW_COPY_AND_ASSIGN(MidiPermissionContextTests);
+  DISALLOW_COPY_AND_ASSIGN(MidiSysexPermissionContextTests);
 };
 
-// Web MIDI permission should be denied for insecure origin.
-TEST_F(MidiPermissionContextTests, TestInsecureRequestingUrl) {
+// Web MIDI sysex permission should be denied for insecure origin.
+TEST_F(MidiSysexPermissionContextTests, TestInsecureRequestingUrl) {
   TestPermissionContext permission_context(profile());
   GURL url("http://www.example.com");
   content::WebContentsTester::For(web_contents())->NavigateAndCommit(url);
@@ -105,8 +105,8 @@
   EXPECT_EQ(CONTENT_SETTING_ASK, setting);
 }
 
-// Web MIDI permission status should be denied for insecure origin.
-TEST_F(MidiPermissionContextTests, TestInsecureQueryingUrl) {
+// Web MIDI sysex permission status should be denied for insecure origin.
+TEST_F(MidiSysexPermissionContextTests, TestInsecureQueryingUrl) {
   TestPermissionContext permission_context(profile());
   GURL insecure_url("http://www.example.com");
   GURL secure_url("https://www.example.com");
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller.cc b/chrome/browser/media/webrtc/media_stream_devices_controller.cc
index 2ee1bf2..ba0bd3d 100644
--- a/chrome/browser/media/webrtc/media_stream_devices_controller.cc
+++ b/chrome/browser/media/webrtc/media_stream_devices_controller.cc
@@ -220,6 +220,17 @@
   return is_asking_for_video_;
 }
 
+PermissionRequest::IconId MediaStreamDevicesController::Request::GetIconId()
+    const {
+#if defined(OS_ANDROID)
+  return IsAskingForVideo() ? IDR_INFOBAR_MEDIA_STREAM_CAMERA
+                            : IDR_INFOBAR_MEDIA_STREAM_MIC;
+#else
+  return IsAskingForVideo() ? ui::kVideocamIcon : ui::kMicrophoneIcon;
+#endif
+}
+
+#if defined(OS_ANDROID)
 base::string16 MediaStreamDevicesController::Request::GetMessageText() const {
   int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO;
   if (!IsAskingForAudio())
@@ -231,16 +242,7 @@
       url_formatter::FormatUrlForSecurityDisplay(
           GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
 }
-
-PermissionRequest::IconId MediaStreamDevicesController::Request::GetIconId()
-    const {
-#if defined(OS_ANDROID)
-  return IsAskingForVideo() ? IDR_INFOBAR_MEDIA_STREAM_CAMERA
-                            : IDR_INFOBAR_MEDIA_STREAM_MIC;
-#else
-  return IsAskingForVideo() ? ui::kVideocamIcon : ui::kMicrophoneIcon;
 #endif
-}
 
 base::string16 MediaStreamDevicesController::Request::GetMessageTextFragment()
     const {
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller.h b/chrome/browser/media/webrtc/media_stream_devices_controller.h
index a8348c1..74013cb 100644
--- a/chrome/browser/media/webrtc/media_stream_devices_controller.h
+++ b/chrome/browser/media/webrtc/media_stream_devices_controller.h
@@ -52,10 +52,12 @@
 
     bool IsAskingForAudio() const;
     bool IsAskingForVideo() const;
-    base::string16 GetMessageText() const;
 
     // PermissionRequest:
     IconId GetIconId() const override;
+#if defined(OS_ANDROID)
+    base::string16 GetMessageText() const override;
+#endif
     base::string16 GetMessageTextFragment() const override;
     GURL GetOrigin() const override;
     void PermissionGranted() override;
diff --git a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
index e06d4a9..a13b2c3 100644
--- a/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
+++ b/chrome/browser/net/nqe/ui_network_quality_estimator_service.cc
@@ -188,7 +188,7 @@
     (void)deleted;
   }
   if (prefs_manager_) {
-    prefs_manager_->ShutdownOnPrefThread();
+    prefs_manager_->ShutdownOnPrefSequence();
     bool deleted = content::BrowserThread::DeleteSoon(
         content::BrowserThread::IO, FROM_HERE, prefs_manager_.release());
     DCHECK(deleted);
diff --git a/chrome/browser/permissions/permission_dialog_delegate.cc b/chrome/browser/permissions/permission_dialog_delegate.cc
index a71d49d..2b03e02 100644
--- a/chrome/browser/permissions/permission_dialog_delegate.cc
+++ b/chrome/browser/permissions/permission_dialog_delegate.cc
@@ -159,9 +159,7 @@
       base::android::ToJavaIntArray(env, content_settings_types).obj(),
       ResourceMapper::MapFromChromiumId(
           permission_prompt_->GetIconIdForPermission(0)),
-      // TODO(timloh): This is the wrong string.
-      ConvertUTF16ToJavaString(env,
-                               permission_prompt_->GetMessageTextFragment(0)),
+      ConvertUTF16ToJavaString(env, permission_prompt_->GetMessageText(0)),
       // TODO(timloh): Pass the actual link text for EME.
       ConvertUTF16ToJavaString(env, base::string16()), primaryButtonText,
       secondaryButtonText,
diff --git a/chrome/browser/permissions/permission_prompt_android.cc b/chrome/browser/permissions/permission_prompt_android.cc
index ffef04a0..dc12132 100644
--- a/chrome/browser/permissions/permission_prompt_android.cc
+++ b/chrome/browser/permissions/permission_prompt_android.cc
@@ -103,6 +103,12 @@
   return requests[position]->GetIconId();
 }
 
+base::string16 PermissionPromptAndroid::GetMessageText(size_t position) const {
+  const std::vector<PermissionRequest*>& requests = delegate_->Requests();
+  DCHECK_LT(position, requests.size());
+  return requests[position]->GetMessageText();
+}
+
 base::string16 PermissionPromptAndroid::GetMessageTextFragment(
     size_t position) const {
   const std::vector<PermissionRequest*>& requests = delegate_->Requests();
diff --git a/chrome/browser/permissions/permission_prompt_android.h b/chrome/browser/permissions/permission_prompt_android.h
index ab47330e..8884806 100644
--- a/chrome/browser/permissions/permission_prompt_android.h
+++ b/chrome/browser/permissions/permission_prompt_android.h
@@ -37,6 +37,7 @@
   size_t PermissionCount() const;
   ContentSettingsType GetContentSettingType(size_t position) const;
   int GetIconIdForPermission(size_t position) const;
+  base::string16 GetMessageText(size_t position) const;
   base::string16 GetMessageTextFragment(size_t position) const;
 
  private:
diff --git a/chrome/browser/permissions/permission_request.h b/chrome/browser/permissions/permission_request.h
index 748313e..add86321 100644
--- a/chrome/browser/permissions/permission_request.h
+++ b/chrome/browser/permissions/permission_request.h
@@ -76,6 +76,12 @@
   // The icon to use next to the message text fragment in the permission bubble.
   virtual IconId GetIconId() const = 0;
 
+#if defined(OS_ANDROID)
+  // Returns the full prompt text for this permission. This is currently only
+  // used on Android.
+  virtual base::string16 GetMessageText() const = 0;
+#endif
+
   // Returns the shortened prompt text for this permission.  Must be phrased
   // as a heading, e.g. "Location", or "Camera". The permission bubble may
   // coalesce different requests, and if it does, this text will be displayed
diff --git a/chrome/browser/permissions/permission_request_impl.cc b/chrome/browser/permissions/permission_request_impl.cc
index 9d252f2..cc87658 100644
--- a/chrome/browser/permissions/permission_request_impl.cc
+++ b/chrome/browser/permissions/permission_request_impl.cc
@@ -100,6 +100,41 @@
 #endif
 }
 
+#if defined(OS_ANDROID)
+base::string16 PermissionRequestImpl::GetMessageText() const {
+  // This is currently only used for modal dialogs on Android.
+  int message_id;
+  switch (content_settings_type_) {
+    case CONTENT_SETTINGS_TYPE_GEOLOCATION:
+      message_id = IDS_GEOLOCATION_INFOBAR_QUESTION;
+      break;
+    case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
+    case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING:
+      message_id = IDS_NOTIFICATION_PERMISSIONS;
+      break;
+    case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
+      message_id = IDS_MIDI_SYSEX_INFOBAR_QUESTION;
+      break;
+    case CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER:
+      message_id = IDS_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_QUESTION;
+      break;
+    case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
+      message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY;
+      break;
+    case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
+      message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY;
+      break;
+    default:
+      NOTREACHED();
+      return base::string16();
+  }
+  return l10n_util::GetStringFUTF16(
+      message_id,
+      url_formatter::FormatUrlForSecurityDisplay(
+          GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
+}
+#endif
+
 base::string16 PermissionRequestImpl::GetMessageTextFragment() const {
   int message_id;
   switch (content_settings_type_) {
diff --git a/chrome/browser/permissions/permission_request_impl.h b/chrome/browser/permissions/permission_request_impl.h
index 035a5b6f..28f8a4f 100644
--- a/chrome/browser/permissions/permission_request_impl.h
+++ b/chrome/browser/permissions/permission_request_impl.h
@@ -38,6 +38,9 @@
  private:
   // PermissionRequest:
   IconId GetIconId() const override;
+#if defined(OS_ANDROID)
+  base::string16 GetMessageText() const override;
+#endif
   base::string16 GetMessageTextFragment() const override;
   GURL GetOrigin() const override;
   // Remember to call RegisterActionTaken for these methods if you are
diff --git a/chrome/browser/permissions/permission_request_manager.cc b/chrome/browser/permissions/permission_request_manager.cc
index 51fe1ba..61346ec 100644
--- a/chrome/browser/permissions/permission_request_manager.cc
+++ b/chrome/browser/permissions/permission_request_manager.cc
@@ -26,11 +26,18 @@
  public:
   explicit CancelledRequest(PermissionRequest* cancelled)
       : icon_(cancelled->GetIconId()),
+#if defined(OS_ANDROID)
+        message_(cancelled->GetMessageText()),
+#endif
         message_fragment_(cancelled->GetMessageTextFragment()),
-        origin_(cancelled->GetOrigin()) {}
+        origin_(cancelled->GetOrigin()) {
+  }
   ~CancelledRequest() override {}
 
   IconId GetIconId() const override { return icon_; }
+#if defined(OS_ANDROID)
+  base::string16 GetMessageText() const override { return message_; }
+#endif
   base::string16 GetMessageTextFragment() const override {
     return message_fragment_;
   }
@@ -45,6 +52,9 @@
 
  private:
   IconId icon_;
+#if defined(OS_ANDROID)
+  base::string16 message_;
+#endif
   base::string16 message_fragment_;
   GURL origin_;
 };
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index a6eebb3fa..4e01782b 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -131,7 +131,7 @@
   }
 
   if (io_data_->http_server_properties_manager_)
-    io_data_->http_server_properties_manager_->ShutdownOnPrefThread();
+    io_data_->http_server_properties_manager_->ShutdownOnPrefSequence();
 
   // io_data_->data_reduction_proxy_io_data() might be NULL if Init() was
   // never called.
@@ -472,7 +472,7 @@
   ApplyProfileParamsToContext(main_context);
 
   if (lazy_params_->http_server_properties_manager) {
-    lazy_params_->http_server_properties_manager->InitializeOnNetworkThread();
+    lazy_params_->http_server_properties_manager->InitializeOnNetworkSequence();
     main_context_storage->set_http_server_properties(
         std::move(lazy_params_->http_server_properties_manager));
   }
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 8654a8c..56b832f 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -3582,6 +3582,7 @@
         "cocoa/extensions/browser_action_test_util_mac.mm",
         "cocoa/find_bar/find_bar_host_unittest_util_cocoa.mm",
       ]
+      deps += [ "//ui/base:test_support" ]
     }
   }
 
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_test_util_mac.mm b/chrome/browser/ui/cocoa/extensions/browser_action_test_util_mac.mm
index 2c97e95f..ca79282 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_action_test_util_mac.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_action_test_util_mac.mm
@@ -26,6 +26,7 @@
 #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
 #include "chrome/common/chrome_constants.h"
+#import "ui/base/test/windowed_nsnotification_observer.h"
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
@@ -158,6 +159,23 @@
   return popup_owner ? popup_owner->GetPopupNativeView() : nil;
 }
 
+bool BrowserActionTestUtil::WaitForPopup() {
+  NSWindow* window = [GetPopupNativeView() window];
+  if (!window)
+    return false;
+
+  if ([window isKeyWindow])
+    return true;
+
+  base::scoped_nsobject<WindowedNSNotificationObserver> waiter(
+      [[WindowedNSNotificationObserver alloc]
+          initForNotification:NSWindowDidBecomeKeyNotification
+                       object:window]);
+
+  BOOL notification_observed = [waiter wait];
+  return notification_observed && [window isKeyWindow];
+}
+
 bool BrowserActionTestUtil::HasPopup() {
   return GetPopupNativeView() != nil;
 }
diff --git a/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
index 78e6cfe8..0a5f6c0 100644
--- a/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
+++ b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
@@ -167,6 +167,12 @@
   return popup_owner ? popup_owner->GetPopupNativeView() : nullptr;
 }
 
+bool BrowserActionTestUtil::WaitForPopup() {
+  // TODO(tapted): Implement this for MacViews.
+  NOTIMPLEMENTED();
+  return HasPopup();
+}
+
 bool BrowserActionTestUtil::HasPopup() {
   return GetPopupNativeView() != nullptr;
 }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index c9df284..8fa665c0 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -3090,6 +3090,7 @@
     "../browser/media/android/router/media_router_android_unittest.cc",
     "../browser/media/cast_remoting_connector_unittest.cc",
     "../browser/media/media_engagement_contents_observer_unittest.cc",
+    "../browser/media/midi_permission_context_unittest.cc",
     "../browser/media/midi_sysex_permission_context_unittest.cc",
     "../browser/media/router/browser_presentation_connection_proxy_unittest.cc",
     "../browser/media/router/create_presentation_connection_request_unittest.cc",
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index 43e9261..46dcdd48 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -149,7 +149,6 @@
   }
   if (enable_print_preview) {
     sources += [
-      "print_preview/print_preview.js",
       "print_preview/print_preview_destination_search_test.js",
       "print_preview/print_preview_ui_browsertest.js",
     ]
diff --git a/chrome/test/data/webui/print_preview/print_preview.js b/chrome/test/data/webui/print_preview/print_preview.js
deleted file mode 100644
index 8c16737..0000000
--- a/chrome/test/data/webui/print_preview/print_preview.js
+++ /dev/null
@@ -1,736 +0,0 @@
-// 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.
-
-var ROOT_PATH = '../../../../../';
-
-/**
- * Test fixture for print preview WebUI testing.
- * @constructor
- * @extends {testing.Test}
- */
-function PrintPreviewWebUITest() {
-  testing.Test.call(this);
-  this.printPreview_ = null;
-  this.nativeLayer_ = null;
-  this.initialSettings_ = null;
-  this.localDestinationInfos_ = null;
-  this.previewArea_ = null;
-}
-
-PrintPreviewWebUITest.prototype = {
-  __proto__: testing.Test.prototype,
-
-  /**
-   * Browse to the sample page, cause print preview & call preLoad().
-   * @type {string}
-   * @override
-   */
-  browsePrintPreload: 'print_preview/print_preview_hello_world_test.html',
-
-  /** @override */
-  runAccessibilityChecks: true,
-
-  /** @override */
-  accessibilityIssuesAreErrors: true,
-
-  /** @override */
-  isAsync: true,
-
-  /**
-   * Stub out low-level functionality like the NativeLayer and
-   * CloudPrintInterface.
-   * @this {PrintPreviewWebUITest}
-   * @override
-   */
-  preLoad: function() {
-    window.isTest = true;
-    window.addEventListener('DOMContentLoaded', function() {
-      function CloudPrintInterfaceStub() {
-        cr.EventTarget.call(this);
-      }
-      CloudPrintInterfaceStub.prototype = {
-        __proto__: cr.EventTarget.prototype,
-        search: function(isRecent) {}
-      };
-      var oldCpInterfaceEventType = cloudprint.CloudPrintInterfaceEventType;
-      cloudprint.CloudPrintInterface = CloudPrintInterfaceStub;
-      cloudprint.CloudPrintInterfaceEventType = oldCpInterfaceEventType;
-
-      print_preview.PreviewArea.prototype.checkPluginCompatibility_ =
-          function() {
-        return false;
-      };
-    }.bind(this));
-  },
-
-  extraLibraries: [
-    ROOT_PATH + 'ui/webui/resources/js/cr.js',
-    ROOT_PATH + 'ui/webui/resources/js/promise_resolver.js',
-    ROOT_PATH + 'ui/webui/resources/js/util.js',
-    ROOT_PATH + 'chrome/test/data/webui/settings/test_browser_proxy.js',
-    'native_layer_stub.js',
-  ],
-
-  /**
-   * Creates an instance of print_preview.PrintPreview and initializes the
-   * |nativeLayer_| and |previewArea_|.
-   */
-  createPrintPreview: function() {
-    this.nativeLayer_ = new print_preview.NativeLayerStub();
-    print_preview.NativeLayer.setInstance(this.nativeLayer_);
-    this.printPreview_ = new print_preview.PrintPreview();
-    this.previewArea_ = this.printPreview_.getPreviewArea();
-  },
-
-  /**
-   * Initialize print preview with the initial settings currently stored in
-   * |this.initialSettings_|. Creates |this.printPreview_| if it does not
-   * already exist.
-   */
-  setInitialSettings: function() {
-    if (!this.printPreview_)
-      this.createPrintPreview();
-    this.nativeLayer_.setInitialSettings(this.initialSettings_);
-    this.printPreview_.initialize();
-    testing.Test.disableAnimationsAndTransitions();
-    // Enable when failure is resolved.
-    // AX_TEXT_03: http://crbug.com/559209
-    this.accessibilityAuditConfig.ignoreSelectors(
-        'multipleLabelableElementsPerLabel',
-        '#page-settings > .right-column > *');
-  },
-
-  /**
-   * Dispatch the LOCAL_DESTINATIONS_SET event. This call is NOT async and will
-   * happen in the same thread.
-   */
-  setLocalDestinations: function() {
-    var localDestsSetEvent =
-        new Event(print_preview.NativeLayer.EventType.LOCAL_DESTINATIONS_SET);
-    localDestsSetEvent.destinationInfos = this.localDestinationInfos_;
-    this.nativeLayer_.getEventTarget().dispatchEvent(localDestsSetEvent);
-  },
-
-  /**
-   * Dispatch the CAPABILITIES_SET event. This call is NOT async and will
-   * happen in the same thread.
-   * @device - The device whose capabilities should be dispatched.
-   */
-  setCapabilities: function(device) {
-    var capsSetEvent =
-        new Event(print_preview.NativeLayer.EventType.CAPABILITIES_SET);
-    capsSetEvent.settingsInfo = device;
-    this.nativeLayer_.getEventTarget().dispatchEvent(capsSetEvent);
-  },
-
-  /**
-   * Dispatch the PREVIEW_GENERATION_DONE event. This call is NOT async and
-   * will happen in the same thread.
-   */
-  dispatchPreviewDone: function() {
-    var previewDoneEvent =
-        new Event(print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE);
-    this.previewArea_.dispatchEvent(previewDoneEvent);
-  },
-
-  /**
-   * Dispatch the SETTINGS_INVALID event. This call is NOT async and will
-   * happen in the same thread.
-   */
-  dispatchInvalidSettings: function() {
-    var invalidSettingsEvent =
-        new Event(print_preview.NativeLayer.EventType.SETTINGS_INVALID);
-    this.nativeLayer_.getEventTarget().dispatchEvent(invalidSettingsEvent);
-  },
-
-  /**
-   * @return {boolean} Whether the UI has "printed" or not. (called startPrint
-   *     on the native layer)
-   */
-  hasPrinted: function() {
-    return this.nativeLayer_.isPrintStarted();
-  },
-
-  /**
-   * @return {boolean} Whether the UI is "generating draft" in the most recent
-   *     preview. (checking the result of the startGetPreview call in the native
-   *     layer)
-   */
-  generateDraft: function() {
-    return this.nativeLayer_.generateDraft();
-  },
-
-  /**
-   * Even though animation duration and delay is set to zero, it is necessary to
-   * wait until the animation has finished.
-   */
-  waitForAnimationToEnd: function(elementId) {
-    // add a listener for the animation end event
-    document.addEventListener('animationend', function f(e) {
-      if (e.target.id == elementId) {
-        document.removeEventListener(f, 'animationend');
-        testDone();
-      }
-    });
-  },
-
-  /**
-   * Expand the 'More Settings' div to expose all options.
-   */
-  expandMoreSettings: function() {
-    var moreSettings = $('more-settings');
-    checkSectionVisible(moreSettings, true);
-    moreSettings.click();
-  },
-
-  /**
-   * Repeated setup steps for the advanced settings tests.
-   * Disables accessiblity errors, sets initial settings, and verifies
-   * advanced options section is visible after expanding more settings.
-   */
-  setupAdvancedSettingsTest: function(device) {
-    // Need to disable this since overlay animation will not fully complete.
-    this.setLocalDestinations();
-    this.setCapabilities(device);
-    this.expandMoreSettings();
-
-    // Check that the advanced options settings section is visible.
-    checkSectionVisible($('advanced-options-settings'), true);
-  },
-
-  /**
-   * @this {PrintPreviewWebUITest}
-   * @override
-   */
-  setUp: function() {
-    testing.Test.prototype.setUp.call(this);
-    Mock4JS.clearMocksToVerify();
-
-    this.initialSettings_ = new print_preview.NativeInitialSettings(
-      false /*isInKioskAutoPrintMode*/,
-      false /*isInAppKioskMode*/,
-      ',' /*thousandsDelimeter*/,
-      '.' /*decimalDelimeter*/,
-      1 /*unitType*/,
-      true /*isDocumentModifiable*/,
-      'title' /*documentTitle*/,
-      true /*documentHasSelection*/,
-      false /*selectionOnly*/,
-      'FooDevice' /*systemDefaultDestinationId*/,
-      null /*serializedAppStateStr*/,
-      null /*serializedDefaultDestinationSelectionRulesStr*/);
-    this.localDestinationInfos_ = [
-      { printerName: 'FooName', deviceName: 'FooDevice' },
-      { printerName: 'BarName', deviceName: 'BarDevice' }
-    ];
-  },
-};
-
-
-/**
- * Verify that |section| visibility matches |visible|.
- * @param {HTMLDivElement} section The section to check.
- * @param {boolean} visible The expected state of visibility.
- */
-function checkSectionVisible(section, visible) {
-  assertNotEquals(null, section);
-  expectEquals(
-      visible, section.classList.contains('visible'), 'section=' + section.id);
-}
-
-function checkElementDisplayed(el, isDisplayed) {
-  assertNotEquals(null, el);
-  expectEquals(isDisplayed,
-               !el.hidden,
-               'element="' + el.id + '" of class "' + el.classList + '"');
-}
-
-function getCddTemplate(printerId) {
-  return {
-    printerId: printerId,
-    capabilities: {
-      version: '1.0',
-      printer: {
-        supported_content_type: [{content_type: 'application/pdf'}],
-        collate: {},
-        color: {
-          option: [
-            {type: 'STANDARD_COLOR', is_default: true},
-            {type: 'STANDARD_MONOCHROME'}
-          ]
-        },
-        copies: {},
-        duplex: {
-          option: [
-            {type: 'NO_DUPLEX', is_default: true},
-            {type: 'LONG_EDGE'},
-            {type: 'SHORT_EDGE'}
-          ]
-        },
-        page_orientation: {
-          option: [
-            {type: 'PORTRAIT', is_default: true},
-            {type: 'LANDSCAPE'},
-            {type: 'AUTO'}
-          ]
-        },
-        media_size: {
-          option: [
-            { name: 'NA_LETTER',
-              width_microns: 215900,
-              height_microns: 279400,
-              is_default: true
-            }
-          ]
-        }
-      }
-    }
-  };
-}
-
-function isPrintAsImageEnabled() {
-  // Should be enabled by default on non Windows/Mac
-  return (!cr.isWindows && !cr.isMac &&
-          loadTimeData.getBoolean('printPdfAsImageEnabled'));
-}
-
-// Test to verify that duplex settings are set according to the printer
-// capabilities.
-TEST_F('PrintPreviewWebUITest', 'TestDuplexSettingsTrue', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-        this.setCapabilities(getCddTemplate("FooDevice"));
-
-        var otherOptions = $('other-options-settings');
-        checkSectionVisible(otherOptions, true);
-        duplexContainer = otherOptions.querySelector('#duplex-container');
-        expectFalse(duplexContainer.hidden);
-        expectFalse(duplexContainer.querySelector('.checkbox').checked);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test to verify that duplex settings are set according to the printer
-// capabilities.
-TEST_F('PrintPreviewWebUITest', 'TestDuplexSettingsFalse', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-        var device = getCddTemplate("FooDevice");
-        delete device.capabilities.printer.duplex;
-        this.setCapabilities(device);
-
-        // Check that it is collapsed.
-        var otherOptions = $('other-options-settings');
-        checkSectionVisible(otherOptions, false);
-
-        this.expandMoreSettings();
-
-        // Now it should be visible.
-        checkSectionVisible(otherOptions, true);
-        expectTrue(otherOptions.querySelector('#duplex-container').hidden);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that changing the selected printer updates the preview.
-TEST_F('PrintPreviewWebUITest', 'TestPrinterChangeUpdatesPreview', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-        this.setCapabilities(getCddTemplate("FooDevice"));
-
-        var previewGenerator = mock(print_preview.PreviewGenerator);
-        this.previewArea_.previewGenerator_ =
-            previewGenerator.proxy();
-
-        // The number of settings that can change due to a change in the
-        // destination that will therefore dispatch ticket item change events.
-        previewGenerator.expects(exactly(9)).requestPreview();
-
-        var barDestination =
-            this.printPreview_.destinationStore_.destinations().find(
-                function(d) {
-                  return d.id == 'BarDevice';
-                });
-
-        this.printPreview_.destinationStore_.selectDestination(barDestination);
-
-        var device = getCddTemplate("BarDevice");
-        device.capabilities.printer.color = {
-          "option": [
-            {"is_default": true, "type": "STANDARD_MONOCHROME"}
-          ]
-        };
-        this.setCapabilities(device);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that error message is displayed when plugin doesn't exist.
-TEST_F('PrintPreviewWebUITest', 'TestNoPDFPluginErrorMessage', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        var previewAreaEl = $('preview-area');
-
-        var loadingMessageEl =
-            previewAreaEl.
-            getElementsByClassName('preview-area-loading-message')[0];
-        expectTrue(loadingMessageEl.hidden);
-
-        var previewFailedMessageEl = previewAreaEl.getElementsByClassName(
-            'preview-area-preview-failed-message')[0];
-        expectTrue(previewFailedMessageEl.hidden);
-
-        var printFailedMessageEl =
-            previewAreaEl.
-            getElementsByClassName('preview-area-print-failed')[0];
-        expectTrue(printFailedMessageEl.hidden);
-
-        var customMessageEl =
-            previewAreaEl.
-            getElementsByClassName('preview-area-custom-message')[0];
-        expectFalse(customMessageEl.hidden);
-
-        testDone();
-      });
-});
-
-// Test custom localized paper names.
-TEST_F('PrintPreviewWebUITest', 'TestCustomPaperNames', function() {
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-
-        var customLocalizedMediaName = 'Vendor defined localized media name';
-        var customMediaName = 'Vendor defined media name';
-
-        var device = getCddTemplate("FooDevice");
-        device.capabilities.printer.media_size = {
-          option: [
-            { name: 'CUSTOM',
-              width_microns: 15900,
-              height_microns: 79400,
-              is_default: true,
-              custom_display_name_localized: [
-                { locale: navigator.language,
-                  value: customLocalizedMediaName
-                }
-              ]
-            },
-            { name: 'CUSTOM',
-              width_microns: 15900,
-              height_microns: 79400,
-              custom_display_name: customMediaName
-            }
-          ]
-        };
-
-        this.setCapabilities(device);
-
-        this.expandMoreSettings();
-
-        checkSectionVisible($('media-size-settings'), true);
-        var mediaSelect =
-            $('media-size-settings').querySelector('.settings-select');
-        // Check the default media item.
-        expectEquals(
-            customLocalizedMediaName,
-            mediaSelect.options[mediaSelect.selectedIndex].text);
-        // Check the other media item.
-        expectEquals(
-            customMediaName,
-            mediaSelect.options[mediaSelect.selectedIndex == 0 ? 1 : 0].text);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-function getCddTemplateWithAdvancedSettings(printerId) {
-  return {
-    printerId: printerId,
-    capabilities: {
-      version: '1.0',
-      printer: {
-        supported_content_type: [{content_type: 'application/pdf'}],
-        vendor_capability:
-        [
-          {display_name: 'Print Area',
-            id: 'Print Area',
-            type: 'SELECT',
-            select_cap: {
-              option: [
-                {display_name: 'A4', value: 4, is_default: true},
-                {display_name: 'A6', value: 6},
-                {display_name: 'A7', value: 7}
-              ]
-            }
-          }
-        ],
-        collate: {},
-        color: {
-          option: [
-            {type: 'STANDARD_COLOR', is_default: true},
-            {type: 'STANDARD_MONOCHROME'}
-          ]
-        },
-        copies: {},
-        duplex: {
-          option: [
-            {type: 'NO_DUPLEX', is_default: true},
-            {type: 'LONG_EDGE'},
-            {type: 'SHORT_EDGE'}
-          ]
-        },
-        page_orientation: {
-          option: [
-            {type: 'PORTRAIT', is_default: true},
-            {type: 'LANDSCAPE'},
-            {type: 'AUTO'}
-          ]
-        },
-        media_size: {
-          option: [
-            { name: 'NA_LETTER',
-              width_microns: 215900,
-              height_microns: 279400,
-              is_default: true
-            }
-          ]
-        },
-      }
-    }
-  };
-}
-
-// Simulates a click of the advanced options settings button to bring up the
-// advanced settings overlay.
-function openAdvancedSettings() {
-  // Check for button and click to view advanced settings section.
-  var advancedOptionsSettingsButton =
-      $('advanced-options-settings').
-      querySelector('.advanced-options-settings-button');
-  checkElementDisplayed(advancedOptionsSettingsButton, true);
-  // Button is disabled during testing due to test version of
-  // testPluginCompatibility() being set to always return false. Enable button
-  // to send click event.
-  advancedOptionsSettingsButton.disabled = false;
-  advancedOptionsSettingsButton.click();
-}
-
-// Test advanced settings with 1 capability (should not display settings search
-// box).
-TEST_F('PrintPreviewWebUITest', 'TestAdvancedSettings1Option', function() {
-  var device = getCddTemplateWithAdvancedSettings("FooDevice");
-  this.accessibilityIssuesAreErrors = false;
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setupAdvancedSettingsTest(device);
-
-        // Open the advanced settings overlay.
-        openAdvancedSettings();
-
-        // Check that advanced settings close button is now visible,
-        // but not the search box (only 1 capability).
-        var advancedSettingsCloseButton = $('advanced-settings').
-              querySelector('.close-button');
-        checkElementDisplayed(advancedSettingsCloseButton, true);
-        checkElementDisplayed($('advanced-settings').
-             querySelector('.search-box-area'), false);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-
-// Test advanced settings with 2 capabilities (should have settings search box).
-TEST_F('PrintPreviewWebUITest', 'TestAdvancedSettings2Options', function() {
-  var device = getCddTemplateWithAdvancedSettings("FooDevice");
-   // Add new capability.
-  device.capabilities.printer.vendor_capability.push({
-      display_name: 'Paper Type',
-      id: 'Paper Type',
-      type: 'SELECT',
-      select_cap: {
-          option: [
-              {display_name: 'Standard', value: 0, is_default: true},
-              {display_name: 'Recycled', value: 1},
-              {display_name: 'Special', value: 2}
-          ]
-      }
-  });
-  this.accessibilityIssuesAreErrors = false;
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setupAdvancedSettingsTest(device);
-
-        // Open the advanced settings overlay.
-        openAdvancedSettings();
-
-        // Check advanced settings is visible and that the search box now
-        // appears.
-        var advancedSettingsCloseButton = $('advanced-settings').
-            querySelector('.close-button');
-        checkElementDisplayed(advancedSettingsCloseButton, true);
-        checkElementDisplayed($('advanced-settings').
-            querySelector('.search-box-area'), true);
-
-        this.waitForAnimationToEnd('more-settings');
-      }.bind(this));
-});
-
-// Test that initialization with saved destination only issues one call
-// to startPreview.
-TEST_F('PrintPreviewWebUITest', 'TestInitIssuesOneRequest', function() {
-  this.createPrintPreview();
-  // Load in a bunch of recent destinations with non null capabilities.
-  var origin = cr.isChromeOS ? 'chrome_os' : 'local';
-  var initSettings = {
-    version: 2,
-    recentDestinations: [1, 2, 3].map(function(i) {
-      return {
-        id: 'ID' + i, origin: origin, account: '',
-        capabilities: getCddTemplate('ID' + i), name: '',
-        extensionId: '', extensionName: ''
-      };
-    }),
-  };
-  this.initialSettings_.serializedAppStateStr_ = JSON.stringify(initSettings);
-  this.setCapabilities(getCddTemplate('ID1'));
-  this.setCapabilities(getCddTemplate('ID2'));
-  this.setCapabilities(getCddTemplate('ID3'));
-
-  // Use a real preview generator.
-  this.previewArea_.previewGenerator_ =
-      new print_preview.PreviewGenerator(this.printPreview_.destinationStore_,
-        this.printPreview_.printTicketStore_, this.nativeLayer_,
-        this.printPreview_.documentInfo_);
-
-  // Preview generator starts out with inFlightRequestId_ == -1. The id
-  // increments by 1 for each startGetPreview call it makes. It should only
-  // make one such call during initialization or there will be a race; see
-  // crbug.com/666595
-  expectEquals(
-      -1,
-      this.previewArea_.previewGenerator_.inFlightRequestId_);
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        expectEquals(
-            0,
-            this.previewArea_.previewGenerator_.
-                inFlightRequestId_);
-        testDone();
-      }.bind(this));
-});
-
-// Test that invalid settings errors disable the print preview and display
-// an error and that the preview dialog can be recovered by selecting a
-// new destination.
-TEST_F('PrintPreviewWebUITest', 'TestInvalidSettingsError', function() {
-  // Setup
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-        this.setCapabilities(getCddTemplate("FooDevice"));
-
-        // Manually enable the print header. This is needed since there is no
-        // plugin during test, so it will be set as disabled normally.
-        this.printPreview_.printHeader_.isEnabled = true;
-
-        // There will be an error message in the preview area since the plugin
-        // is not running. However, it should not be the invalid settings error.
-        var previewAreaEl = $('preview-area');
-        var customMessageEl =
-            previewAreaEl.
-            getElementsByClassName('preview-area-custom-message')[0];
-        expectFalse(customMessageEl.hidden);
-        var expectedMessageStart = 'The selected printer is not available or '
-            + 'not installed correctly.'
-        expectFalse(customMessageEl.textContent.includes(expectedMessageStart));
-
-        // Verify that the print button is enabled.
-        var printHeader = $('print-header');
-        var printButton = printHeader.querySelector('button.print');
-        checkElementDisplayed(printButton, true);
-        expectFalse(printButton.disabled);
-
-        // Report invalid settings error.
-        this.dispatchInvalidSettings();
-
-        // Should be in an error state, print button disabled, invalid custom
-        // error message shown.
-        expectFalse(customMessageEl.hidden);
-        expectTrue(customMessageEl.textContent.includes(expectedMessageStart));
-        expectTrue(printButton.disabled);
-
-        // Select a new destination
-        var barDestination =
-            this.printPreview_.destinationStore_.destinations().find(
-                function(d) {
-                  return d.id == 'BarDevice';
-                });
-
-        this.printPreview_.destinationStore_.selectDestination(barDestination);
-
-        // Dispatch events indicating capabilities were fetched and new preview
-        // has loaded.
-        this.setCapabilities(getCddTemplate("BarDevice"));
-        this.dispatchPreviewDone();
-
-        // Has active print button and successfully "prints", indicating
-        // recovery from error state.
-        expectFalse(printButton.disabled);
-        expectFalse(this.hasPrinted());
-        printButton.click();
-        expectTrue(this.hasPrinted());
-        testDone();
-      }.bind(this));
-});
-
-// Test the preview generator to make sure the generate draft parameter is set
-// correctly. It should be false if the only change is the page range.
-TEST_F('PrintPreviewWebUITest', 'TestGenerateDraft', function() {
-  this.createPrintPreview();
-
-  // Use a real preview generator.
-  this.previewArea_.previewGenerator_ =
-      new print_preview.PreviewGenerator(this.printPreview_.destinationStore_,
-          this.printPreview_.printTicketStore_, this.nativeLayer_,
-          this.printPreview_.documentInfo_);
-
-  this.setInitialSettings();
-  this.nativeLayer_.whenCalled('getInitialSettings').then(
-      function() {
-        this.setLocalDestinations();
-        this.setCapabilities(getCddTemplate("FooDevice"));
-
-        // The first request should generate draft because there was no
-        // previous print preview draft.
-        expectTrue(this.generateDraft());
-
-        // Change the page range - no new draft needed.
-        this.printPreview_.printTicketStore_.pageRange.updateValue("2");
-        expectFalse(this.generateDraft());
-
-        // Change the margin type - need to regenerate again.
-        this.printPreview_.printTicketStore_.marginsType.updateValue(
-            print_preview.ticket_items.MarginsTypeValue.NO_MARGINS);
-        expectTrue(this.generateDraft());
-
-        testDone();
-      }.bind(this));
-});
diff --git a/chrome/test/data/webui/print_preview/print_preview_tests.js b/chrome/test/data/webui/print_preview/print_preview_tests.js
index 8610103..c7277f5 100644
--- a/chrome/test/data/webui/print_preview/print_preview_tests.js
+++ b/chrome/test/data/webui/print_preview/print_preview_tests.js
@@ -134,6 +134,27 @@
   }
 
   /**
+   * @param {string} printerId
+   * @return {!Object}
+   */
+  function getCddTemplateWithAdvancedSettings(printerId) {
+    var template = getCddTemplate(printerId);
+    template.capabilities.printer.vendor_capability = [{
+      display_name: 'Print Area',
+      id: 'Print Area',
+      type: 'SELECT',
+      select_cap: {
+        option: [
+          {display_name: 'A4', value: 4, is_default: true},
+          {display_name: 'A6', value: 6},
+          {display_name: 'A7', value: 7},
+        ],
+      },
+    }];
+    return template;
+  }
+
+  /**
    * Even though animation duration and delay is set to zero, it is necessary to
    * wait until the animation has finished.
    * @return {!Promise} A promise firing when the animation is done.
@@ -158,6 +179,35 @@
     moreSettings.click();
   }
 
+  // Simulates a click of the advanced options settings button to bring up the
+  // advanced settings overlay.
+  function openAdvancedSettings() {
+    // Check for button and click to view advanced settings section.
+    var advancedOptionsSettingsButton =
+        $('advanced-options-settings').
+        querySelector('.advanced-options-settings-button');
+    checkElementDisplayed(advancedOptionsSettingsButton, true);
+    // Button is disabled during testing due to test version of
+    // testPluginCompatibility() being set to always return false. Enable button
+    // to send click event.
+    advancedOptionsSettingsButton.disabled = false;
+    advancedOptionsSettingsButton.click();
+  }
+
+  /**
+   * Repeated setup steps for the advanced settings tests.
+   * Sets initial settings, and verifies advanced options section is visible
+   * after expanding more settings.
+   */
+  function setupAdvancedSettingsTest(device) {
+    setLocalDestinations();
+    setCapabilities(device);
+    expandMoreSettings();
+
+    // Check that the advanced options settings section is visible.
+    checkSectionVisible($('advanced-options-settings'), true);
+  }
+
   /** @return {boolean} */
   function isPrintAsImageEnabled() {
     // Should be enabled by default on non Windows/Mac.
@@ -536,7 +586,7 @@
       });
     });
 
-    // When the source is "PDF", depending on the selected destination printer,
+    // When the source is 'PDF', depending on the selected destination printer,
     // we show/hide the fit to page option and hide media size selection.
     test('SourceIsPDFCapabilities', function() {
       initialSettings.isDocumentModifiable_ = false;
@@ -575,7 +625,7 @@
           });
     });
 
-    // When the source is "PDF", depending on the selected destination printer,
+    // When the source is 'PDF', depending on the selected destination printer,
     // we show/hide the fit to page option and hide media size selection.
     test('ScalingUnchecksFitToPage', function() {
       initialSettings.isDocumentModifiable_ = false;
@@ -657,7 +707,7 @@
             setLocalDestinations();
             setCapabilities(getCddTemplate('FooDevice'));
 
-            // Indicate that the duplex print preset is set to "long edge" for
+            // Indicate that the duplex print preset is set to 'long edge' for
             // source PDF.
             var printPresetOptions = {
               duplex: 1
@@ -875,7 +925,7 @@
     });
 
     // Test that the color settings, one option, standard monochrome.
-    test('TestColorSettingsMonochrome', function() {
+    test('ColorSettingsMonochrome', function() {
       setInitialSettings();
       return nativeLayer.whenCalled('getInitialSettings').then(function() {
         setLocalDestinations();
@@ -896,7 +946,7 @@
     });
 
     // Test that the color settings, one option, custom monochrome.
-    test('TestColorSettingsCustomMonochrome', function() {
+    test('ColorSettingsCustomMonochrome', function() {
       setInitialSettings();
       return nativeLayer.whenCalled('getInitialSettings').then(function() {
         setLocalDestinations();
@@ -918,7 +968,7 @@
     });
 
     // Test that the color settings, one option, standard color.
-    test('TestColorSettingsColor', function() {
+    test('ColorSettingsColor', function() {
       setInitialSettings();
       return nativeLayer.whenCalled('getInitialSettings').then(function() {
         setLocalDestinations();
@@ -938,7 +988,7 @@
     });
 
     // Test that the color settings, one option, custom color.
-    test('TestColorSettingsCustomColor', function() {
+    test('ColorSettingsCustomColor', function() {
       setInitialSettings();
       return nativeLayer.whenCalled('getInitialSettings').then(function() {
         setLocalDestinations();
@@ -959,7 +1009,7 @@
 
     // Test that the color settings, two options, both standard, defaults to
     // color.
-    test('TestColorSettingsBothStandardDefaultColor', function() {
+    test('ColorSettingsBothStandardDefaultColor', function() {
       setInitialSettings();
       return nativeLayer.whenCalled('getInitialSettings').then(function() {
         setLocalDestinations();
@@ -984,7 +1034,7 @@
 
     // Test that the color settings, two options, both standard, defaults to
     // monochrome.
-    test('TestColorSettingsBothStandardDefaultMonochrome', function() {
+    test('ColorSettingsBothStandardDefaultMonochrome', function() {
       setInitialSettings();
       return nativeLayer.whenCalled('getInitialSettings').then(function() {
         setLocalDestinations();
@@ -1009,30 +1059,373 @@
 
     // Test that the color settings, two options, both custom, defaults to
     // color.
-    test('TestColorSettingsBothCustomDefaultColor', function() {
+    test('ColorSettingsBothCustomDefaultColor', function() {
       setInitialSettings();
-      return nativeLayer.whenCalled('getInitialSettings').then(
-          function() {
-            setLocalDestinations();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
 
-            var device = getCddTemplate('FooDevice');
-            device.capabilities.printer.color = {
-              'option': [
-                {'type': 'CUSTOM_MONOCHROME', 'vendor_id': '42'},
-                {'is_default': true, 'type': 'CUSTOM_COLOR', 'vendor_id': '43'}
+        var device = getCddTemplate('FooDevice');
+        device.capabilities.printer.color = {
+          'option': [
+            {'type': 'CUSTOM_MONOCHROME', 'vendor_id': '42'},
+            {'is_default': true, 'type': 'CUSTOM_COLOR', 'vendor_id': '43'}
+          ]
+        };
+        setCapabilities(device);
+
+        checkSectionVisible($('color-settings'), true);
+        expectEquals(
+            'color',
+            $('color-settings').querySelector(
+                '.color-settings-select').value);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test to verify that duplex settings are set according to the printer
+    // capabilities.
+    test('DuplexSettingsTrue', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+        setCapabilities(getCddTemplate('FooDevice'));
+
+        var otherOptions = $('other-options-settings');
+        checkSectionVisible(otherOptions, true);
+        duplexContainer = otherOptions.querySelector('#duplex-container');
+        expectFalse(duplexContainer.hidden);
+        expectFalse(duplexContainer.querySelector('.checkbox').checked);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test to verify that duplex settings are set according to the printer
+    // capabilities.
+    test('DuplexSettingsFalse', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+        var device = getCddTemplate('FooDevice');
+        delete device.capabilities.printer.duplex;
+        setCapabilities(device);
+
+        // Check that it is collapsed.
+        var otherOptions = $('other-options-settings');
+        checkSectionVisible(otherOptions, false);
+
+        expandMoreSettings();
+
+        // Now it should be visible.
+        checkSectionVisible(otherOptions, true);
+        expectTrue(otherOptions.querySelector('#duplex-container').hidden);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that changing the selected printer updates the preview.
+    test('PrinterChangeUpdatesPreview', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+        setCapabilities(getCddTemplate('FooDevice'));
+
+        var previewGenerator = mock(print_preview.PreviewGenerator);
+        previewArea.previewGenerator_ = previewGenerator.proxy();
+
+        // The number of settings that can change due to a change in the
+        // destination that will therefore dispatch ticket item change events.
+        previewGenerator.expects(exactly(9)).requestPreview();
+
+        var barDestination =
+            printPreview.destinationStore_.destinations().find(
+                function(d) {
+                  return d.id == 'BarDevice';
+                });
+
+        printPreview.destinationStore_.selectDestination(barDestination);
+
+        var device = getCddTemplate('BarDevice');
+        device.capabilities.printer.color = {
+          'option': [
+            {'is_default': true, 'type': 'STANDARD_MONOCHROME'}
+          ]
+        };
+        setCapabilities(device);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that error message is displayed when plugin doesn't exist.
+    test('NoPDFPluginErrorMessage', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        var previewAreaEl = $('preview-area');
+
+        var loadingMessageEl =
+            previewAreaEl.
+            getElementsByClassName('preview-area-loading-message')[0];
+        expectTrue(loadingMessageEl.hidden);
+
+        var previewFailedMessageEl = previewAreaEl.getElementsByClassName(
+            'preview-area-preview-failed-message')[0];
+        expectTrue(previewFailedMessageEl.hidden);
+
+        var printFailedMessageEl =
+            previewAreaEl.
+            getElementsByClassName('preview-area-print-failed')[0];
+        expectTrue(printFailedMessageEl.hidden);
+
+        var customMessageEl =
+            previewAreaEl.
+            getElementsByClassName('preview-area-custom-message')[0];
+        expectFalse(customMessageEl.hidden);
+      });
+    });
+
+    // Test custom localized paper names.
+    test('CustomPaperNames', function() {
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+
+        var customLocalizedMediaName = 'Vendor defined localized media name';
+        var customMediaName = 'Vendor defined media name';
+
+        var device = getCddTemplate('FooDevice');
+        device.capabilities.printer.media_size = {
+          option: [
+            { name: 'CUSTOM',
+              width_microns: 15900,
+              height_microns: 79400,
+              is_default: true,
+              custom_display_name_localized: [
+                { locale: navigator.language,
+                  value: customLocalizedMediaName
+                }
               ]
-            };
-            setCapabilities(device);
+            },
+            { name: 'CUSTOM',
+              width_microns: 15900,
+              height_microns: 79400,
+              custom_display_name: customMediaName
+            }
+          ]
+        };
 
-            checkSectionVisible($('color-settings'), true);
-            expectEquals(
-                'color',
-                $('color-settings').querySelector(
-                    '.color-settings-select').value);
+        setCapabilities(device);
 
-            return whenAnimationDone('more-settings');
-          });
-        });
+        expandMoreSettings();
 
+        checkSectionVisible($('media-size-settings'), true);
+        var mediaSelect =
+            $('media-size-settings').querySelector('.settings-select');
+        // Check the default media item.
+        expectEquals(
+            customLocalizedMediaName,
+            mediaSelect.options[mediaSelect.selectedIndex].text);
+        // Check the other media item.
+        expectEquals(
+            customMediaName,
+            mediaSelect.options[mediaSelect.selectedIndex == 0 ? 1 : 0].text);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test advanced settings with 1 capability (should not display settings
+    // search box).
+    test('AdvancedSettings1Option', function() {
+      var device = getCddTemplateWithAdvancedSettings('FooDevice');
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setupAdvancedSettingsTest(device);
+
+        // Open the advanced settings overlay.
+        openAdvancedSettings();
+
+        // Check that advanced settings close button is now visible,
+        // but not the search box (only 1 capability).
+        var advancedSettingsCloseButton = $('advanced-settings').
+              querySelector('.close-button');
+        checkElementDisplayed(advancedSettingsCloseButton, true);
+        checkElementDisplayed($('advanced-settings').
+             querySelector('.search-box-area'), false);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+
+    // Test advanced settings with 2 capabilities (should have settings search
+    // box).
+    test('AdvancedSettings2Options', function() {
+      var device = getCddTemplateWithAdvancedSettings('FooDevice');
+       // Add new capability.
+      device.capabilities.printer.vendor_capability.push({
+          display_name: 'Paper Type',
+          id: 'Paper Type',
+          type: 'SELECT',
+          select_cap: {
+              option: [
+                  {display_name: 'Standard', value: 0, is_default: true},
+                  {display_name: 'Recycled', value: 1},
+                  {display_name: 'Special', value: 2}
+              ]
+          }
+      });
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setupAdvancedSettingsTest(device);
+
+        // Open the advanced settings overlay.
+        openAdvancedSettings();
+
+        // Check advanced settings is visible and that the search box now
+        // appears.
+        var advancedSettingsCloseButton = $('advanced-settings').
+            querySelector('.close-button');
+        checkElementDisplayed(advancedSettingsCloseButton, true);
+        checkElementDisplayed($('advanced-settings').
+            querySelector('.search-box-area'), true);
+
+        return whenAnimationDone('more-settings');
+      });
+    });
+
+    // Test that initialization with saved destination only issues one call
+    // to startPreview.
+    test('InitIssuesOneRequest', function() {
+      // Load in a bunch of recent destinations with non null capabilities.
+      var origin = cr.isChromeOS ? 'chrome_os' : 'local';
+      initialSettings.serializedAppStateStr_ = JSON.stringify({
+        version: 2,
+        recentDestinations: [1, 2, 3].map(function(i) {
+          return {
+            id: 'ID' + i, origin: origin, account: '',
+            capabilities: getCddTemplate('ID' + i), name: '',
+            extensionId: '', extensionName: ''
+          };
+        }),
+      });
+      setCapabilities(getCddTemplate('ID1'));
+      setCapabilities(getCddTemplate('ID2'));
+      setCapabilities(getCddTemplate('ID3'));
+
+      // Use a real preview generator.
+      previewArea.previewGenerator_ =
+          new print_preview.PreviewGenerator(printPreview.destinationStore_,
+            printPreview.printTicketStore_, nativeLayer,
+            printPreview.documentInfo_);
+
+      // Preview generator starts out with inFlightRequestId_ == -1. The id
+      // increments by 1 for each startGetPreview call it makes. It should only
+      // make one such call during initialization or there will be a race; see
+      // crbug.com/666595
+      expectEquals(-1, previewArea.previewGenerator_.inFlightRequestId_);
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        expectEquals(0, previewArea.previewGenerator_.inFlightRequestId_);
+      });
+    });
+
+    // Test that invalid settings errors disable the print preview and display
+    // an error and that the preview dialog can be recovered by selecting a
+    // new destination.
+    test('InvalidSettingsError', function() {
+      // Setup
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+        setCapabilities(getCddTemplate('FooDevice'));
+
+        // Manually enable the print header. This is needed since there is no
+        // plugin during test, so it will be set as disabled normally.
+        printPreview.printHeader_.isEnabled = true;
+
+        // There will be an error message in the preview area since the plugin
+        // is not running. However, it should not be the invalid settings error.
+        var previewAreaEl = $('preview-area');
+        var customMessageEl =
+            previewAreaEl.
+            getElementsByClassName('preview-area-custom-message')[0];
+        expectFalse(customMessageEl.hidden);
+        var expectedMessageStart = 'The selected printer is not available or '
+            + 'not installed correctly.'
+        expectFalse(customMessageEl.textContent.includes(expectedMessageStart));
+
+        // Verify that the print button is enabled.
+        var printHeader = $('print-header');
+        var printButton = printHeader.querySelector('button.print');
+        checkElementDisplayed(printButton, true);
+        expectFalse(printButton.disabled);
+
+        // Report invalid settings error.
+        var invalidSettingsEvent =
+            new Event(print_preview.NativeLayer.EventType.SETTINGS_INVALID);
+        nativeLayer.getEventTarget().dispatchEvent(invalidSettingsEvent);
+
+        // Should be in an error state, print button disabled, invalid custom
+        // error message shown.
+        expectFalse(customMessageEl.hidden);
+        expectTrue(customMessageEl.textContent.includes(expectedMessageStart));
+        expectTrue(printButton.disabled);
+
+        // Select a new destination
+        var barDestination =
+            printPreview.destinationStore_.destinations().find(
+                function(d) {
+                  return d.id == 'BarDevice';
+                });
+
+        printPreview.destinationStore_.selectDestination(barDestination);
+
+        // Dispatch events indicating capabilities were fetched and new preview
+        // has loaded.
+        setCapabilities(getCddTemplate('BarDevice'));
+        var previewDoneEvent = new Event(
+            print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE);
+        previewArea.dispatchEvent(previewDoneEvent);
+
+        // Has active print button and successfully 'prints', indicating
+        // recovery from error state.
+        expectFalse(printButton.disabled);
+        expectFalse(nativeLayer.isPrintStarted());
+        printButton.click();
+        expectTrue(nativeLayer.isPrintStarted());
+      });
+    });
+
+    // Test the preview generator to make sure the generate draft parameter is
+    // set correctly. It should be false if the only change is the page range.
+    test('GenerateDraft', function() {
+      // Use a real preview generator.
+      previewArea.previewGenerator_ =
+          new print_preview.PreviewGenerator(printPreview.destinationStore_,
+              printPreview.printTicketStore_, nativeLayer,
+              printPreview.documentInfo_);
+
+      setInitialSettings();
+      return nativeLayer.whenCalled('getInitialSettings').then(function() {
+        setLocalDestinations();
+        setCapabilities(getCddTemplate('FooDevice'));
+
+        // The first request should generate draft because there was no
+        // previous print preview draft.
+        expectTrue(nativeLayer.generateDraft());
+
+        // Change the page range - no new draft needed.
+        printPreview.printTicketStore_.pageRange.updateValue('2');
+        expectFalse(nativeLayer.generateDraft());
+
+        // Change the margin type - need to regenerate again.
+        printPreview.printTicketStore_.marginsType.updateValue(
+            print_preview.ticket_items.MarginsTypeValue.NO_MARGINS);
+        expectTrue(nativeLayer.generateDraft());
+      });
+    });
   });
 });
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
index 740c11a..ef6c932 100644
--- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
+++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -25,7 +25,7 @@
   runAccessibilityChecks: true,
 
   /** @override */
-  accessibilityIssuesAreErrors: false,
+  accessibilityIssuesAreErrors: true,
 
   /** @override */
   isAsync: true,
@@ -82,15 +82,35 @@
   'ZeroTopAndBottomMarginsHideHeaderFooter',
   'ZeroTopAndNonZeroBottomMarginShowHeaderFooter',
   'SmallPaperSizeHeaderFooter',
-  'TestColorSettingsMonochrome',
-  'TestColorSettingsCustomMonochrome',
-  'TestColorSettingsColor',
-  'TestColorSettingsCustomColor',
-  'TestColorSettingsBothStandardDefaultColor',
-  'TestColorSettingsBothStandardDefaultMonochrome',
-  'TestColorSettingsBothCustomDefaultColor',
+  'ColorSettingsMonochrome',
+  'ColorSettingsCustomMonochrome',
+  'ColorSettingsColor',
+  'ColorSettingsCustomColor',
+  'ColorSettingsBothStandardDefaultColor',
+  'ColorSettingsBothStandardDefaultMonochrome',
+  'ColorSettingsBothCustomDefaultColor',
+  'DuplexSettingsTrue',
+  'DuplexSettingsFalse',
+  'PrinterChangeUpdatesPreview',
+  'NoPDFPluginErrorMessage',
+  'CustomPaperNames',
+  'InitIssuesOneRequest',
+  'InvalidSettingsError',
+  'GenerateDraft',
 ].forEach(function(testName) {
   TEST_F('PrintPreviewUIBrowserTest', testName, function() {
     mocha.grep(new RegExp(testName + '\\b')).run();
   });
 });
+
+
+// Disable accessibility errors for some tests.
+[
+  'AdvancedSettings1Option',
+  'AdvancedSettings2Options',
+].forEach(function(testName) {
+  TEST_F('PrintPreviewUIBrowserTest', testName, function() {
+    this.accessibilityIssuesAreErrors = false;
+    mocha.grep(new RegExp(testName + '\\b')).run();
+  });
+});
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index d2d87d33..fd9368a 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -87,8 +87,8 @@
 #else
 
 #define MAYBE_PPAPI_NACL(test_name) test_name
-#if defined (OS_WIN) || defined(ADDRESS_SANITIZER)
-// http://crbug.com/633067
+#if defined(OS_WIN) || defined(OS_LINUX) || defined(ADDRESS_SANITIZER)
+// http://crbug.com/633067, http://crbug.com/727989
 #define MAYBE_PPAPI_PNACL(test_name) DISABLED_##test_name
 #else
 #define MAYBE_PPAPI_PNACL(test_name) test_name
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc
index 10c1361..e042a2a 100644
--- a/components/cronet/android/cronet_url_request_context_adapter.cc
+++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -490,9 +490,9 @@
   DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread());
 
   if (http_server_properties_manager_)
-    http_server_properties_manager_->ShutdownOnPrefThread();
+    http_server_properties_manager_->ShutdownOnPrefSequence();
   if (network_qualities_prefs_manager_)
-    network_qualities_prefs_manager_->ShutdownOnPrefThread();
+    network_qualities_prefs_manager_->ShutdownOnPrefSequence();
   if (pref_service_)
     pref_service_->CommitPendingWrite();
   if (network_quality_estimator_) {
@@ -660,7 +660,7 @@
         http_server_properties_manager(new net::HttpServerPropertiesManager(
             new PrefServiceAdapter(pref_service_.get()),
             base::ThreadTaskRunnerHandle::Get(), GetNetworkTaskRunner()));
-    http_server_properties_manager->InitializeOnNetworkThread();
+    http_server_properties_manager->InitializeOnNetworkSequence();
     http_server_properties_manager_ = http_server_properties_manager.get();
     context_builder.SetHttpServerProperties(
         std::move(http_server_properties_manager));
diff --git a/components/nacl/loader/nacl_ipc_adapter.cc b/components/nacl/loader/nacl_ipc_adapter.cc
index dc521ba..03d41fae 100644
--- a/components/nacl/loader/nacl_ipc_adapter.cc
+++ b/components/nacl/loader/nacl_ipc_adapter.cc
@@ -67,7 +67,12 @@
   explicit DescThunker(NaClIPCAdapter* adapter_arg)
       : adapter(adapter_arg) {
   }
+
+  ~DescThunker() { adapter->CloseChannel(); }
+
   scoped_refptr<NaClIPCAdapter> adapter;
+
+  DISALLOW_COPY_AND_ASSIGN(DescThunker);
 };
 
 NaClIPCAdapter* ToAdapter(void* handle) {
diff --git a/components/translate/core/browser/BUILD.gn b/components/translate/core/browser/BUILD.gn
index 45e0c2b..f7ad715 100644
--- a/components/translate/core/browser/BUILD.gn
+++ b/components/translate/core/browser/BUILD.gn
@@ -94,6 +94,8 @@
   sources = [
     "language_model_unittest.cc",
     "language_state_unittest.cc",
+    "mock_translate_client.cc",
+    "mock_translate_client.h",
     "mock_translate_driver.cc",
     "mock_translate_driver.h",
     "mock_translate_ranker.cc",
diff --git a/components/translate/core/browser/mock_translate_client.cc b/components/translate/core/browser/mock_translate_client.cc
new file mode 100644
index 0000000..f517155
--- /dev/null
+++ b/components/translate/core/browser/mock_translate_client.cc
@@ -0,0 +1,41 @@
+// Copyright 2017 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 <memory>
+
+#include "components/translate/core/browser/mock_translate_client.h"
+#include "components/translate/core/browser/translate_prefs.h"
+
+namespace translate {
+
+namespace testing {
+
+#if defined(OS_CHROMEOS)
+const char* preferred_languages_prefs = "settings.language.preferred_languages";
+#else
+const char* preferred_languages_prefs = nullptr;
+#endif
+const char* accept_languages_prefs = "intl.accept_languages";
+
+MockTranslateClient::MockTranslateClient(TranslateDriver* driver,
+                                         PrefService* prefs)
+    : driver_(driver), prefs_(prefs) {}
+
+MockTranslateClient::~MockTranslateClient() {}
+
+TranslateDriver* MockTranslateClient::GetTranslateDriver() {
+  return driver_;
+}
+
+PrefService* MockTranslateClient::GetPrefs() {
+  return prefs_;
+}
+
+std::unique_ptr<TranslatePrefs> MockTranslateClient::GetTranslatePrefs() {
+  return base::MakeUnique<TranslatePrefs>(prefs_, accept_languages_prefs,
+                                          preferred_languages_prefs);
+}
+
+}  // namespace testing
+}  // namespace translate
diff --git a/components/translate/core/browser/mock_translate_client.h b/components/translate/core/browser/mock_translate_client.h
new file mode 100644
index 0000000..bf972ebb
--- /dev/null
+++ b/components/translate/core/browser/mock_translate_client.h
@@ -0,0 +1,67 @@
+// Copyright 2017 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 COMPONENTS_TRANSLATE_CORE_BROWSER_MOCK_TRANSLATE_CLIENT_H_
+#define COMPONENTS_TRANSLATE_CORE_BROWSER_MOCK_TRANSLATE_CLIENT_H_
+
+#include <memory>
+#include <string>
+
+#include "base/memory/ptr_util.h"
+#include "components/infobars/core/infobar.h"
+#include "components/translate/core/browser/translate_client.h"
+#include "components/translate/core/browser/translate_driver.h"
+#include "components/translate/core/browser/translate_prefs.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace translate {
+
+namespace testing {
+
+extern const char* preferred_languages_prefs;
+extern const char* accept_languages_prefs;
+
+class MockTranslateClient : public TranslateClient {
+ public:
+  MockTranslateClient(TranslateDriver* driver, PrefService* prefs);
+
+  ~MockTranslateClient() override;
+
+  TranslateDriver* GetTranslateDriver() override;
+
+  PrefService* GetPrefs() override;
+
+  std::unique_ptr<TranslatePrefs> GetTranslatePrefs() override;
+
+  MOCK_METHOD0(GetTranslateAcceptLanguages, TranslateAcceptLanguages*());
+  MOCK_CONST_METHOD0(GetInfobarIconID, int());
+
+#if !defined(USE_AURA)
+  MOCK_CONST_METHOD1(CreateInfoBarMock,
+                     infobars::InfoBar*(TranslateInfoBarDelegate*));
+  std::unique_ptr<infobars::InfoBar> CreateInfoBar(
+      std::unique_ptr<TranslateInfoBarDelegate> delegate) const {
+    return base::WrapUnique(CreateInfoBarMock(delegate.get()));
+  }
+#endif
+
+  MOCK_METHOD5(ShowTranslateUI,
+               void(translate::TranslateStep,
+                    const std::string&,
+                    const std::string&,
+                    TranslateErrors::Type,
+                    bool));
+  MOCK_METHOD1(IsTranslatableURL, bool(const GURL&));
+  MOCK_METHOD1(ShowReportLanguageDetectionErrorUI, void(const GURL&));
+
+ private:
+  TranslateDriver* driver_;
+  PrefService* prefs_;
+};
+
+}  // namespace testing
+
+}  // namespace translate
+
+#endif  // COMPONENTS_TRANSLATE_CORE_BROWSER_MOCK_TRANSLATE_CLIENT_H_
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc
index 043e036..5e6537f1 100644
--- a/components/translate/core/browser/translate_manager_unittest.cc
+++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -16,6 +16,7 @@
 #include "components/metrics/proto/translate_event.pb.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "components/translate/core/browser/mock_translate_client.h"
 #include "components/translate/core/browser/mock_translate_driver.h"
 #include "components/translate/core/browser/mock_translate_ranker.h"
 #include "components/translate/core/browser/translate_browser_metrics.h"
@@ -39,14 +40,6 @@
 
 const char kTrialName[] = "MyTrial";
 
-#if defined(OS_CHROMEOS)
-const char kLanguagePreferredLanguages[] =
-    "settings.language.preferred_languages";
-#else
-const char* kLanguagePreferredLanguages = nullptr;
-#endif
-const char kAcceptLanguages[] = "intl.accept_languages";
-
 // Overrides NetworkChangeNotifier, simulating connection type changes
 // for tests.
 // TODO(groby): Combine with similar code in ResourceRequestAllowedNotifierTest.
@@ -87,50 +80,6 @@
   DISALLOW_COPY_AND_ASSIGN(TestNetworkChangeNotifier);
 };
 
-// TODO(groby): Combine with MockTranslateClient in TranslateUiDelegateTest.
-class MockTranslateClient : public TranslateClient {
- public:
-  MockTranslateClient(TranslateDriver* driver, PrefService* prefs)
-      : driver_(driver), prefs_(prefs) {}
-
-  // TODO(groby): Does TranslateClient need a virtual dtor?
-  virtual ~MockTranslateClient() {}
-
-  TranslateDriver* GetTranslateDriver() { return driver_; }
-  PrefService* GetPrefs() { return prefs_; }
-
-  std::unique_ptr<TranslatePrefs> GetTranslatePrefs() {
-    return base::MakeUnique<TranslatePrefs>(prefs_, kAcceptLanguages,
-                                            kLanguagePreferredLanguages);
-  }
-  MOCK_METHOD0(GetTranslateAcceptLanguages, TranslateAcceptLanguages*());
-  MOCK_CONST_METHOD0(GetInfobarIconID, int());
-
-#if !defined(USE_AURA)
-  MOCK_CONST_METHOD1(CreateInfoBarMock,
-                     infobars::InfoBar*(TranslateInfoBarDelegate*));
-  std::unique_ptr<infobars::InfoBar> CreateInfoBar(
-      std::unique_ptr<TranslateInfoBarDelegate> delegate) const {
-    return base::WrapUnique(CreateInfoBarMock(std::move(delegate).get()));
-  }
-#endif
-
-  MOCK_METHOD5(ShowTranslateUI,
-               void(translate::TranslateStep,
-                    const std::string&,
-                    const std::string&,
-                    TranslateErrors::Type,
-                    bool));
-
-  MOCK_METHOD1(IsTranslatableURL, bool(const GURL&));
-  MOCK_METHOD1(ShowReportLanguageDetectionErrorUI,
-               void(const GURL& report_url));
-
- private:
-  TranslateDriver* driver_;
-  PrefService* prefs_;
-};
-
 // Compares TranslateEventProto on a restricted set of fields.
 MATCHER_P(EqualsTranslateEventProto, translate_event, "") {
   const metrics::TranslateEventProto& tep(translate_event);
@@ -147,8 +96,8 @@
  protected:
   TranslateManagerTest()
       : translate_prefs_(&prefs_,
-                         kAcceptLanguages,
-                         kLanguagePreferredLanguages),
+                         accept_languages_prefs,
+                         preferred_languages_prefs),
         manager_(TranslateDownloadManager::GetInstance()),
         mock_translate_client_(&driver_, &prefs_),
         field_trial_list_(new base::FieldTrialList(nullptr)) {}
@@ -156,9 +105,10 @@
   void SetUp() override {
     // Ensure we're not requesting a server-side translate language list.
     TranslateLanguageList::DisableUpdate();
-    prefs_.registry()->RegisterStringPref(kAcceptLanguages, std::string());
+    prefs_.registry()->RegisterStringPref(accept_languages_prefs,
+                                          std::string());
 #if defined(OS_CHROMEOS)
-    prefs_.registry()->RegisterStringPref(kLanguagePreferredLanguages,
+    prefs_.registry()->RegisterStringPref(preferred_languages_prefs,
                                           std::string());
 #endif
     TranslatePrefs::RegisterProfilePrefs(prefs_.registry());
@@ -178,7 +128,8 @@
   void PrepareTranslateManager() {
     TranslateManager::SetIgnoreMissingKeyForTesting(true);
     translate_manager_.reset(new translate::TranslateManager(
-        &mock_translate_client_, &mock_translate_ranker_, kAcceptLanguages));
+        &mock_translate_client_, &mock_translate_ranker_,
+        accept_languages_prefs));
   }
 
   // Prepare the test for ULP related tests.
@@ -275,7 +226,8 @@
   TestNetworkChangeNotifier network_notifier_;
   translate::testing::MockTranslateDriver driver_;
   translate::testing::MockTranslateRanker mock_translate_ranker_;
-  ::testing::NiceMock<MockTranslateClient> mock_translate_client_;
+  ::testing::NiceMock<translate::testing::MockTranslateClient>
+      mock_translate_client_;
   std::unique_ptr<TranslateManager> translate_manager_;
   std::unique_ptr<base::FieldTrialList> field_trial_list_;
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -342,7 +294,8 @@
 TEST_F(TranslateManagerTest, DontTranslateOffline) {
   TranslateManager::SetIgnoreMissingKeyForTesting(true);
   translate_manager_.reset(new translate::TranslateManager(
-      &mock_translate_client_, &mock_translate_ranker_, kAcceptLanguages));
+      &mock_translate_client_, &mock_translate_ranker_,
+      accept_languages_prefs));
 
   // The test measures that the "Translate was disabled" exit can only be
   // reached after the early-out tests including IsOffline() passed.
diff --git a/components/translate/core/browser/translate_ui_delegate_unittest.cc b/components/translate/core/browser/translate_ui_delegate_unittest.cc
index eb15170..2f33464 100644
--- a/components/translate/core/browser/translate_ui_delegate_unittest.cc
+++ b/components/translate/core/browser/translate_ui_delegate_unittest.cc
@@ -13,6 +13,7 @@
 #include "components/infobars/core/infobar.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "components/translate/core/browser/mock_translate_client.h"
 #include "components/translate/core/browser/mock_translate_driver.h"
 #include "components/translate/core/browser/mock_translate_ranker.h"
 #include "components/translate/core/browser/translate_client.h"
@@ -26,54 +27,12 @@
 
 using testing::Return;
 using testing::Test;
+using translate::testing::MockTranslateClient;
 using translate::testing::MockTranslateDriver;
 using translate::testing::MockTranslateRanker;
 
 namespace translate {
 
-#if defined(OS_CHROMEOS)
-const char* preferred_languages_prefs = "settings.language.preferred_languages";
-#else
-const char* preferred_languages_prefs = NULL;
-#endif
-
-class MockTranslateClient : public TranslateClient {
- public:
-  MockTranslateClient(TranslateDriver* driver, PrefService* prefs)
-      : driver_(driver), prefs_(prefs) {}
-
-  TranslateDriver* GetTranslateDriver() { return driver_; }
-  PrefService* GetPrefs() { return prefs_; }
-
-  std::unique_ptr<TranslatePrefs> GetTranslatePrefs() {
-    return base::MakeUnique<TranslatePrefs>(prefs_, "intl.accept_languages",
-                                            preferred_languages_prefs);
-  }
-
-  MOCK_METHOD0(GetTranslateAcceptLanguages, TranslateAcceptLanguages*());
-  MOCK_CONST_METHOD0(GetInfobarIconID, int());
-
-  MOCK_CONST_METHOD1(CreateInfoBarMock,
-                     infobars::InfoBar*(TranslateInfoBarDelegate*));
-  std::unique_ptr<infobars::InfoBar> CreateInfoBar(
-      std::unique_ptr<TranslateInfoBarDelegate> delegate) const {
-    return base::WrapUnique(CreateInfoBarMock(std::move(delegate).get()));
-  }
-
-  MOCK_METHOD5(ShowTranslateUI,
-               void(translate::TranslateStep,
-                    const std::string&,
-                    const std::string&,
-                    TranslateErrors::Type,
-                    bool));
-  MOCK_METHOD1(IsTranslatableURL, bool(const GURL&));
-  MOCK_METHOD1(ShowReportLanguageDetectionErrorUI, void(const GURL&));
-
- private:
-  TranslateDriver* driver_;
-  PrefService* prefs_;
-};
-
 class TranslateUIDelegateTest : public ::testing::Test {
  public:
   TranslateUIDelegateTest() : ::testing::Test() {}
diff --git a/content/browser/loader/reload_cache_control_browsertest.cc b/content/browser/loader/reload_cache_control_browsertest.cc
index 148436d..5951cd3d 100644
--- a/content/browser/loader/reload_cache_control_browsertest.cc
+++ b/content/browser/loader/reload_cache_control_browsertest.cc
@@ -28,8 +28,6 @@
 using net::test_server::HttpResponse;
 
 const char kReloadTestPath[] = "/loader/reload_test.html";
-const char kReloadFramePath[] = "/loader/simple_frame.html";
-const char kReloadImagePath[] = "/loader/empty16x16.png";
 // The test page should request resources as the content structure is described
 // below. Reload and the same page navigation will affect only the top frame
 // resource, reload_test.html. But bypassing reload will affect all resources.
@@ -47,6 +45,18 @@
   std::string cache_control;
 };
 
+struct ExpectedCacheControl {
+  const char* top_main;
+  const char* others;
+};
+
+const ExpectedCacheControl kExpectedCacheControlForNormalLoad = {
+    kNoCacheControl, kNoCacheControl};
+const ExpectedCacheControl kExpectedCacheControlForReload = {
+    kMaxAgeCacheControl, kNoCacheControl};
+const ExpectedCacheControl kExpectedCacheControlForBypassingReload = {
+    kNoCacheCacheControl, kNoCacheCacheControl};
+
 // Tests end to end behaviors between Blink and content around reload variants.
 class ReloadCacheControlBrowserTest : public ContentBrowserTest {
  protected:
@@ -70,6 +80,18 @@
   }
 
  protected:
+  void CheckCacheControl(const ExpectedCacheControl& expectation) {
+    base::AutoLock lock(request_log_lock_);
+    EXPECT_EQ(4u, request_log_.size());
+    for (const auto& log : request_log_) {
+      if (log.relative_url == kReloadTestPath)
+        EXPECT_EQ(expectation.top_main, log.cache_control);
+      else
+        EXPECT_EQ(expectation.others, log.cache_control);
+    }
+    request_log_.clear();
+  }
+
   std::vector<RequestLog> request_log_;
   base::Lock request_log_lock_;
 
@@ -93,139 +115,37 @@
   GURL url(embedded_test_server()->GetURL(kReloadTestPath));
 
   EXPECT_TRUE(NavigateToURL(shell(), url));
+  CheckCacheControl(kExpectedCacheControlForNormalLoad);
+
   ReloadBlockUntilNavigationsComplete(shell(), 1);
-
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(8UL, request_log_.size());
-    EXPECT_EQ(kReloadTestPath, request_log_[0].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[0].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[1].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[1].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[2].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[2].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[3].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[3].cache_control);
-
-    // Only the top main resource should be requested with kMaxAgeCacheControl.
-    EXPECT_EQ(kReloadTestPath, request_log_[4].relative_url);
-    EXPECT_EQ(kMaxAgeCacheControl, request_log_[4].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[5].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[5].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[6].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[6].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[7].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[7].cache_control);
-  }
+  CheckCacheControl(kExpectedCacheControlForReload);
 
   shell()->ShowDevTools();
   ReloadBlockUntilNavigationsComplete(shell(), 1);
-
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(12UL, request_log_.size());
-
-    // Only the top main resource should be requested with kMaxAgeCacheControl.
-    EXPECT_EQ(kReloadTestPath, request_log_[8].relative_url);
-    EXPECT_EQ(kMaxAgeCacheControl, request_log_[8].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[9].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[9].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[10].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[10].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[11].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[11].cache_control);
-  }
+  CheckCacheControl(kExpectedCacheControlForReload);
 
   shell()->CloseDevTools();
   ReloadBlockUntilNavigationsComplete(shell(), 1);
-
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(16UL, request_log_.size());
-
-    // Only the top main resource should be requested with kMaxAgeCacheControl.
-    EXPECT_EQ(kReloadTestPath, request_log_[12].relative_url);
-    EXPECT_EQ(kMaxAgeCacheControl, request_log_[12].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[13].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[13].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[14].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[14].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[15].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[15].cache_control);
-  }
+  CheckCacheControl(kExpectedCacheControlForReload);
 }
 
 // Test if bypassing reload issues requests with proper cache control flags.
 IN_PROC_BROWSER_TEST_F(ReloadCacheControlBrowserTest, BypassingReload) {
-
   GURL url(embedded_test_server()->GetURL(kReloadTestPath));
 
   NavigateToURLBlockUntilNavigationsComplete(shell(), url, 1);
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(4UL, request_log_.size());
-
-    EXPECT_EQ(kReloadTestPath, request_log_[0].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[0].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[1].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[1].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[2].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[2].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[3].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[3].cache_control);
-  }
+  CheckCacheControl(kExpectedCacheControlForNormalLoad);
 
   ReloadBypassingCacheBlockUntilNavigationsComplete(shell(), 1);
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(8UL, request_log_.size());
-
-    // Only the top main resource should be requested with kNoCacheCacheControl.
-    EXPECT_EQ(kReloadTestPath, request_log_[4].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[4].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[5].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[5].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[6].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[6].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[7].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[7].cache_control);
-  }
+  CheckCacheControl(kExpectedCacheControlForBypassingReload);
 
   shell()->ShowDevTools();
   ReloadBypassingCacheBlockUntilNavigationsComplete(shell(), 1);
-
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(12UL, request_log_.size());
-
-    // All resources should be requested with kNoCacheCacheControl.
-    EXPECT_EQ(kReloadTestPath, request_log_[8].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[8].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[9].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[9].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[10].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[10].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[11].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[11].cache_control);
-  }
+  CheckCacheControl(kExpectedCacheControlForBypassingReload);
 
   shell()->CloseDevTools();
   ReloadBypassingCacheBlockUntilNavigationsComplete(shell(), 1);
-
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(16UL, request_log_.size());
-
-    // All resources should be requested with kNoCacheCacheControl.
-    EXPECT_EQ(kReloadTestPath, request_log_[12].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[12].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[13].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[13].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[14].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[14].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[15].relative_url);
-    EXPECT_EQ(kNoCacheCacheControl, request_log_[15].cache_control);
-  }
+  CheckCacheControl(kExpectedCacheControlForBypassingReload);
 }
 
 // Test if the same page navigation issues requests with proper cache control
@@ -233,75 +153,23 @@
 IN_PROC_BROWSER_TEST_F(ReloadCacheControlBrowserTest, NavigateToSame) {
   GURL url(embedded_test_server()->GetURL(kReloadTestPath));
 
-  EXPECT_TRUE(NavigateToURL(shell(), url));
-  EXPECT_TRUE(NavigateToURL(shell(), url));
-
   // The first navigation is just a normal load.
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(8UL, request_log_.size());
-    EXPECT_EQ(kReloadTestPath, request_log_[0].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[0].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[1].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[1].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[2].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[3].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[3].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[3].cache_control);
-  }
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+  CheckCacheControl(kExpectedCacheControlForNormalLoad);
 
   // The second navigation is the same page navigation. This should be handled
   // as a reload, revalidating the main resource, but following cache protocols
   // for others.
-  {
-    base::AutoLock lock(request_log_lock_);
-
-    // Only the top main resource should be requested with kMaxAgeCacheControl.
-    EXPECT_EQ(kReloadTestPath, request_log_[4].relative_url);
-    EXPECT_EQ(kMaxAgeCacheControl, request_log_[4].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[5].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[5].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[6].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[6].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[7].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[7].cache_control);
-  }
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+  CheckCacheControl(kExpectedCacheControlForReload);
 
   shell()->ShowDevTools();
   EXPECT_TRUE(NavigateToURL(shell(), url));
-
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(12UL, request_log_.size());
-
-    // Only the top main resource should be requested with kMaxAgeCacheControl.
-    EXPECT_EQ(kReloadTestPath, request_log_[8].relative_url);
-    EXPECT_EQ(kMaxAgeCacheControl, request_log_[8].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[9].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[9].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[10].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[10].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[11].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[11].cache_control);
-  }
+  CheckCacheControl(kExpectedCacheControlForReload);
 
   shell()->CloseDevTools();
   EXPECT_TRUE(NavigateToURL(shell(), url));
-
-  {
-    base::AutoLock lock(request_log_lock_);
-    ASSERT_EQ(16UL, request_log_.size());
-
-    // Only the top main resource should be requested with kMaxAgeCacheControl.
-    EXPECT_EQ(kReloadTestPath, request_log_[12].relative_url);
-    EXPECT_EQ(kMaxAgeCacheControl, request_log_[12].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[13].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[13].cache_control);
-    EXPECT_EQ(kReloadFramePath, request_log_[14].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[14].cache_control);
-    EXPECT_EQ(kReloadImagePath, request_log_[15].relative_url);
-    EXPECT_EQ(kNoCacheControl, request_log_[15].cache_control);
-  }
+  CheckCacheControl(kExpectedCacheControlForReload);
 }
 
 }  // namespace
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
index feea79b..9e894e8e 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
@@ -58,7 +58,7 @@
 ChromeBrowserStateImplIOData::Handle::~Handle() {
   DCHECK_CURRENTLY_ON(web::WebThread::UI);
   if (io_data_->http_server_properties_manager_)
-    io_data_->http_server_properties_manager_->ShutdownOnPrefThread();
+    io_data_->http_server_properties_manager_->ShutdownOnPrefSequence();
 
   io_data_->ShutdownOnUIThread(GetAllContextGetters());
 }
@@ -215,7 +215,7 @@
   ApplyProfileParamsToContext(main_context);
 
   if (http_server_properties_manager_)
-    http_server_properties_manager_->InitializeOnNetworkThread();
+    http_server_properties_manager_->InitializeOnNetworkSequence();
 
   main_context->set_transport_security_state(transport_security_state());
 
diff --git a/media/base/key_systems.cc b/media/base/key_systems.cc
index d210b8a..773cc62 100644
--- a/media/base/key_systems.cc
+++ b/media/base/key_systems.cc
@@ -440,7 +440,7 @@
 #endif  // defined(OS_ANDROID)
 
     DVLOG(1) << __func__
-             << " Adding key system:" << properties->GetKeySystemName();
+             << ": Adding key system:" << properties->GetKeySystemName();
     key_system_properties_map_[properties->GetKeySystemName()] =
         std::move(properties);
   }
@@ -510,7 +510,7 @@
   KeySystemPropertiesMap::const_iterator key_system_iter =
       key_system_properties_map_.find(key_system);
   if (key_system_iter == key_system_properties_map_.end()) {
-    DLOG(ERROR) << key_system << " is not a known system";
+    DLOG(ERROR) << key_system << " is not a known key system";
     return false;
   }
   return key_system_iter->second->UseAesDecryptor();
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc
index 6ed4047..aa5bea1 100644
--- a/media/base/mime_util_internal.cc
+++ b/media/base/mime_util_internal.cc
@@ -225,7 +225,7 @@
         mime_type_lower_case, parsed_codec.codec, video_profile, video_level,
         parsed_codec.video_color_space, is_encrypted);
     if (result == IsNotSupported) {
-      DVLOG(2) << __func__ << " Codec " << parsed_codec.codec
+      DVLOG(2) << __func__ << ": Codec " << parsed_codec.codec
                << " not supported by platform.";
       return IsNotSupported;
     }
@@ -524,6 +524,7 @@
     const std::string& mime_type_lower_case,
     bool is_encrypted,
     const PlatformInfo& platform_info) {
+  DVLOG(3) << __func__;
   DCHECK_NE(mime_type_lower_case, "");
 
   // Encrypted block support is never available without platform decoders.
@@ -568,8 +569,10 @@
         return true;
 
       // Otherwise, platform support is required.
-      if (!platform_info.supports_opus)
+      if (!platform_info.supports_opus) {
+        DVLOG(3) << "Platform does not support opus";
         return false;
+      }
 
       // MediaPlayer does not support Opus in ogg containers.
       if (base::EndsWith(mime_type_lower_case, "ogg",
@@ -837,6 +840,8 @@
                                         uint8_t video_level,
                                         const VideoColorSpace& color_space,
                                         bool is_encrypted) const {
+  DVLOG(3) << __func__;
+
   DCHECK_EQ(base::ToLowerASCII(mime_type_lower_case), mime_type_lower_case);
   DCHECK_NE(codec, INVALID_CODEC);
 
diff --git a/media/blink/key_system_config_selector.cc b/media/blink/key_system_config_selector.cc
index 621023e..9acbb149 100644
--- a/media/blink/key_system_config_selector.cc
+++ b/media/blink/key_system_config_selector.cc
@@ -298,6 +298,10 @@
 bool IsSupportedMediaFormat(const std::string& container_mime_type,
                             const std::string& codecs,
                             bool use_aes_decryptor) {
+  DVLOG(3) << __func__ << ": container_mime_type=" << container_mime_type
+           << ", codecs=" << codecs
+           << ", use_aes_decryptor=" << use_aes_decryptor;
+
   std::vector<std::string> codec_vector;
   SplitCodecsToVector(codecs, &codec_vector, false);
   // AesDecryptor decrypts the stream in the demuxer before it reaches the
@@ -317,6 +321,8 @@
     const std::string& container_mime_type,
     const std::string& codecs,
     KeySystemConfigSelector::ConfigState* config_state) {
+  DVLOG(3) << __func__;
+
   // From RFC6838: "Both top-level type and subtype names are case-insensitive."
   std::string container_lower = base::ToLowerASCII(container_mime_type);
 
@@ -324,7 +330,7 @@
   // particular codec. For EME, none of the currently supported containers
   // imply a codec, so |codecs| must be provided.
   if (codecs.empty()) {
-    DVLOG(3) << __func__ << " KeySystemConfig for " << container_mime_type
+    DVLOG(3) << "KeySystemConfig for " << container_mime_type
              << " does not specify necessary codecs.";
     return false;
   }
@@ -335,6 +341,7 @@
   // robustness algorithm).
   if (!IsSupportedMediaFormat(container_lower, codecs,
                               CanUseAesDecryptor(key_system))) {
+    DVLOG(3) << "Container mime type and codecs are not supported";
     return false;
   }
 
@@ -392,6 +399,7 @@
         !IsSupportedContentType(
             key_system, media_type, capability.mime_type.Ascii(),
             capability.codecs.Ascii(), &proposed_config_state)) {
+      DVLOG(3) << "The current capability is not supported.";
       continue;
     }
 
@@ -413,8 +421,10 @@
     //       encrypted media data for the combination of container, media types,
     //       robustness and local accumulated configuration in combination with
     //       restrictions:
-    if (!proposed_config_state.IsRuleSupported(robustness_rule))
+    if (!proposed_config_state.IsRuleSupported(robustness_rule)) {
+      DVLOG(3) << "The current robustness rule is not supported.";
       continue;
+    }
 
     // 3.13.1. Add requested media capability to supported media capabilities.
     supported_media_capabilities->push_back(capability);
@@ -454,6 +464,8 @@
     const blink::WebMediaKeySystemConfiguration& candidate,
     ConfigState* config_state,
     blink::WebMediaKeySystemConfiguration* accumulated_configuration) {
+  DVLOG(3) << __func__;
+
   // From
   // http://w3c.github.io/encrypted-media/#get-supported-configuration-and-consent
   // 1. Let accumulated configuration be a new MediaKeySystemConfiguration
@@ -672,6 +684,8 @@
     if (!GetSupportedCapabilities(key_system, EmeMediaType::VIDEO,
                                   candidate.video_capabilities, config_state,
                                   &video_capabilities)) {
+      DVLOG(2) << "Rejecting requested configuration because the specified "
+                  "videoCapabilities are not supported.";
       return CONFIGURATION_NOT_SUPPORTED;
     }
 
@@ -696,6 +710,8 @@
     if (!GetSupportedCapabilities(key_system, EmeMediaType::AUDIO,
                                   candidate.audio_capabilities, config_state,
                                   &audio_capabilities)) {
+      DVLOG(2) << "Rejecting requested configuration because the specified "
+                  "audioCapabilities are not supported.";
       return CONFIGURATION_NOT_SUPPORTED;
     }
 
@@ -869,6 +885,8 @@
 
 void KeySystemConfigSelector::SelectConfigInternal(
     std::unique_ptr<SelectionRequest> request) {
+  DVLOG(3) << __func__;
+
   // Continued from requestMediaKeySystemAccess(), step 6, from
   // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess
   //
@@ -906,6 +924,7 @@
           // Note: the GURL must not be constructed inline because
           // base::Passed(&request) sets |request| to null.
           GURL security_origin(url::Origin(request->security_origin).GetURL());
+          DVLOG(3) << "Request permission.";
           media_permission_->RequestPermission(
               MediaPermission::PROTECTED_MEDIA_IDENTIFIER, security_origin,
               base::Bind(&KeySystemConfigSelector::OnPermissionResult,
@@ -934,6 +953,8 @@
 void KeySystemConfigSelector::OnPermissionResult(
     std::unique_ptr<SelectionRequest> request,
     bool is_permission_granted) {
+  DVLOG(3) << __func__;
+
   request->was_permission_requested = true;
   request->is_permission_granted = is_permission_granted;
   SelectConfigInternal(std::move(request));
diff --git a/media/blink/key_system_config_selector_unittest.cc b/media/blink/key_system_config_selector_unittest.cc
index 15a686d..7c3c08d86 100644
--- a/media/blink/key_system_config_selector_unittest.cc
+++ b/media/blink/key_system_config_selector_unittest.cc
@@ -34,8 +34,11 @@
 const char kUnsupportedContainer[] = "video/foo";
 
 // TODO(sandersd): Extended codec variants (requires proprietary codec support).
-const char kSupportedVideoCodec[] = "vp8";
+// TODO(xhwang): Platform Opus is not available on all Android versions, where
+// some encrypted Opus related tests may fail. See PlatformHasOpusSupport()
+// for more details.
 const char kSupportedAudioCodec[] = "opus";
+const char kSupportedVideoCodec[] = "vp8";
 const char kUnsupportedCodec[] = "foo";
 const char kUnsupportedCodecs[] = "vp8,foo";
 const char kSupportedVideoCodecs[] = "vp8,vp8";
diff --git a/media/blink/run_all_unittests.cc b/media/blink/run_all_unittests.cc
index 94efcba..8a2951a 100644
--- a/media/blink/run_all_unittests.cc
+++ b/media/blink/run_all_unittests.cc
@@ -18,6 +18,7 @@
 
 #if defined(OS_ANDROID)
 #include "base/android/jni_android.h"
+#include "media/base/android/media_codec_util.h"
 #include "media/base/android/media_jni_registrar.h"
 #endif
 
@@ -76,6 +77,9 @@
 
 #if defined(OS_ANDROID)
   media::RegisterJni(base::android::AttachCurrentThread());
+
+  if (media::MediaCodecUtil::IsMediaCodecAvailable())
+    media::EnablePlatformDecoderSupport();
 #endif
 
   // Run this here instead of main() to ensure an AtExitManager is already
diff --git a/net/base/directory_lister.cc b/net/base/directory_lister.cc
index e5ca942..d8b2fea 100644
--- a/net/base/directory_lister.cc
+++ b/net/base/directory_lister.cc
@@ -87,7 +87,7 @@
 }
 
 void DirectoryLister::Cancel() {
-  core_->CancelOnOriginThread();
+  core_->CancelOnOriginSequence();
 }
 
 DirectoryLister::Core::Core(const base::FilePath& dir,
@@ -103,8 +103,8 @@
 
 DirectoryLister::Core::~Core() {}
 
-void DirectoryLister::Core::CancelOnOriginThread() {
-  DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
+void DirectoryLister::Core::CancelOnOriginSequence() {
+  DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
 
   base::subtle::NoBarrier_Store(&cancelled_, 1);
   // Core must not call into |lister_| after cancellation, as the |lister_| may
@@ -118,7 +118,7 @@
 
   if (!base::DirectoryExists(dir_)) {
     origin_task_runner_->PostTask(
-        FROM_HERE, base::Bind(&Core::DoneOnOriginThread, this,
+        FROM_HERE, base::Bind(&Core::DoneOnOriginSequence, this,
                               base::Passed(std::move(directory_list)),
                               ERR_FILE_NOT_FOUND));
     return;
@@ -137,7 +137,7 @@
   base::FilePath path;
   while (!(path = file_enum.Next()).empty()) {
     // Abort on cancellation. This is purely for performance reasons.
-    // Correctness guarantees are made by checks in DoneOnOriginThread.
+    // Correctness guarantees are made by checks in DoneOnOriginSequence.
     if (IsCancelled())
       return;
 
@@ -166,7 +166,7 @@
   SortData(directory_list.get(), type_);
 
   origin_task_runner_->PostTask(
-      FROM_HERE, base::Bind(&Core::DoneOnOriginThread, this,
+      FROM_HERE, base::Bind(&Core::DoneOnOriginSequence, this,
                             base::Passed(std::move(directory_list)), OK));
 }
 
@@ -174,10 +174,10 @@
   return !!base::subtle::NoBarrier_Load(&cancelled_);
 }
 
-void DirectoryLister::Core::DoneOnOriginThread(
+void DirectoryLister::Core::DoneOnOriginSequence(
     std::unique_ptr<DirectoryList> directory_list,
     int error) const {
-  DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
 
   // Need to check if the operation was before first callback.
   if (IsCancelled())
diff --git a/net/base/directory_lister.h b/net/base/directory_lister.h
index 0489341..3f8b5418 100644
--- a/net/base/directory_lister.h
+++ b/net/base/directory_lister.h
@@ -84,8 +84,8 @@
   // refcounted, it's destroyed when the final reference is released, which may
   // happen on either thread.
   //
-  // It's kept alive during the calls to Start() and DoneOnOriginThread() by the
-  // reference owned by the callback itself.
+  // It's kept alive during the calls to Start() and DoneOnOriginSequence() by
+  // the reference owned by the callback itself.
   class Core : public base::RefCountedThreadSafe<Core> {
    public:
     Core(const base::FilePath& dir, ListingType type, DirectoryLister* lister);
@@ -94,7 +94,7 @@
     void Start();
 
     // Must be called on the origin thread.
-    void CancelOnOriginThread();
+    void CancelOnOriginSequence();
 
    private:
     friend class base::RefCountedThreadSafe<Core>;
@@ -106,8 +106,8 @@
     bool IsCancelled() const;
 
     // Called on origin thread.
-    void DoneOnOriginThread(std::unique_ptr<DirectoryList> directory_list,
-                            int error) const;
+    void DoneOnOriginSequence(std::unique_ptr<DirectoryList> directory_list,
+                              int error) const;
 
     const base::FilePath dir_;
     const ListingType type_;
diff --git a/net/cert/cert_database_mac.cc b/net/cert/cert_database_mac.cc
index 98f8dc9..bc266c3b 100644
--- a/net/cert/cert_database_mac.cc
+++ b/net/cert/cert_database_mac.cc
@@ -39,12 +39,12 @@
                                       base::Unretained(this)));
   }
 
-  // Should be called from the |task_runner_|'s thread. Use Shutdown()
-  // to shutdown on arbitrary threads.
+  // Should be called from the |task_runner_|'s sequence. Use Shutdown()
+  // to shutdown on arbitrary sequence.
   ~Notifier() {
     DCHECK(called_shutdown_);
-    // Only unregister from the same thread where registration was performed.
-    if (registered_ && task_runner_->RunsTasksOnCurrentThread())
+    // Only unregister from the same sequence where registration was performed.
+    if (registered_ && task_runner_->RunsTasksInCurrentSequence())
       SecKeychainRemoveCallback(&Notifier::KeychainCallback);
   }
 
diff --git a/net/cert_net/cert_net_fetcher_impl.cc b/net/cert_net/cert_net_fetcher_impl.cc
index d579fe8..7748e04 100644
--- a/net/cert_net/cert_net_fetcher_impl.cc
+++ b/net/cert_net/cert_net_fetcher_impl.cc
@@ -205,7 +205,7 @@
         task_runner_(std::move(task_runner)) {}
 
   void AttachedToJob(Job* job) {
-    DCHECK(task_runner_->RunsTasksOnCurrentThread());
+    DCHECK(task_runner_->RunsTasksInCurrentSequence());
     DCHECK(!job_);
     // Requests should not be attached to jobs after they have been signalled
     // with a cancellation error (which happens via either Cancel() or
@@ -217,7 +217,7 @@
   void OnJobCompleted(Job* job,
                       Error error,
                       const std::vector<uint8_t>& response_body) {
-    DCHECK(task_runner_->RunsTasksOnCurrentThread());
+    DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
     DCHECK_EQ(job_, job);
     job_ = nullptr;
@@ -237,7 +237,7 @@
 
   // Should only be called once.
   void WaitForResult(Error* error, std::vector<uint8_t>* bytes) {
-    DCHECK(!task_runner_->RunsTasksOnCurrentThread());
+    DCHECK(!task_runner_->RunsTasksInCurrentSequence());
 
     completion_event_.Wait();
     *bytes = std::move(bytes_);
@@ -384,7 +384,7 @@
 };
 
 void RequestCore::CancelJob() {
-  if (!task_runner_->RunsTasksOnCurrentThread()) {
+  if (!task_runner_->RunsTasksInCurrentSequence()) {
     task_runner_->PostTask(FROM_HERE,
                            base::Bind(&RequestCore::CancelJob, this));
     return;
@@ -711,7 +711,7 @@
       : task_runner_(base::ThreadTaskRunnerHandle::Get()), context_(context) {}
 
   void Shutdown() override {
-    DCHECK(task_runner_->RunsTasksOnCurrentThread());
+    DCHECK(task_runner_->RunsTasksInCurrentSequence());
     if (impl_) {
       impl_->Shutdown();
       impl_.reset();
@@ -769,9 +769,9 @@
     DCHECK(!context_);
   }
 
-  void DoFetchOnNetworkThread(std::unique_ptr<RequestParams> request_params,
-                              scoped_refptr<RequestCore> request) {
-    DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  void DoFetchOnNetworkSequence(std::unique_ptr<RequestParams> request_params,
+                                scoped_refptr<RequestCore> request) {
+    DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
     if (!context_) {
       // The fetcher might have been shutdown between when this task was posted
@@ -792,13 +792,13 @@
       std::unique_ptr<RequestParams> request_params) {
     scoped_refptr<RequestCore> request_core = new RequestCore(task_runner_);
 
-    // If the fetcher has already been shutdown, DoFetchOnNetworkThread will
+    // If the fetcher has already been shutdown, DoFetchOnNetworkSequence will
     // signal the request with an error. However, if the fetcher shuts down
-    // before DoFetchOnNetworkThread runs and PostTask still returns true, then
-    // the request will hang (that is, WaitForResult will not return).
+    // before DoFetchOnNetworkSequence runs and PostTask still returns true,
+    // then the request will hang (that is, WaitForResult will not return).
     if (!task_runner_->PostTask(
             FROM_HERE,
-            base::Bind(&CertNetFetcherImpl::DoFetchOnNetworkThread, this,
+            base::Bind(&CertNetFetcherImpl::DoFetchOnNetworkSequence, this,
                        base::Passed(&request_params), request_core))) {
       request_core->SignalImmediateError();
     }
diff --git a/net/disk_cache/blockfile/backend_impl.cc b/net/disk_cache/blockfile/backend_impl.cc
index 4557531fc..2dd24cca 100644
--- a/net/disk_cache/blockfile/backend_impl.cc
+++ b/net/disk_cache/blockfile/backend_impl.cc
@@ -179,8 +179,8 @@
     background_queue_.DropPendingIO();
   }
 
-  if (background_queue_.BackgroundIsCurrentThread()) {
-    // Unit tests may use the same thread for everything.
+  if (background_queue_.BackgroundIsCurrentSequence()) {
+    // Unit tests may use the same sequence for everything.
     CleanupCache();
   } else {
     background_queue_.background_thread()->PostTask(
diff --git a/net/disk_cache/blockfile/in_flight_backend_io.h b/net/disk_cache/blockfile/in_flight_backend_io.h
index 489d333..8d8b8c4 100644
--- a/net/disk_cache/blockfile/in_flight_backend_io.h
+++ b/net/disk_cache/blockfile/in_flight_backend_io.h
@@ -219,9 +219,9 @@
     return background_thread_;
   }
 
-  // Returns true if the current thread is the background thread.
-  bool BackgroundIsCurrentThread() {
-    return background_thread_->RunsTasksOnCurrentThread();
+  // Returns true if the current sequence is the background thread.
+  bool BackgroundIsCurrentSequence() {
+    return background_thread_->RunsTasksInCurrentSequence();
   }
 
   base::WeakPtr<InFlightBackendIO> GetWeakPtr();
diff --git a/net/disk_cache/blockfile/in_flight_io.cc b/net/disk_cache/blockfile/in_flight_io.cc
index 3694b75..03dda643 100644
--- a/net/disk_cache/blockfile/in_flight_io.cc
+++ b/net/disk_cache/blockfile/in_flight_io.cc
@@ -73,10 +73,10 @@
   }
 }
 
-// Runs on a background thread.
+// Runs in a background sequence.
 void InFlightIO::OnIOComplete(BackgroundIO* operation) {
 #if DCHECK_IS_ON()
-  if (callback_task_runner_->RunsTasksOnCurrentThread()) {
+  if (callback_task_runner_->RunsTasksInCurrentSequence()) {
     DCHECK(single_thread_ || !running_);
     single_thread_ = true;
   }
@@ -109,7 +109,7 @@
 
 // Runs on the primary thread.
 void InFlightIO::OnOperationPosted(BackgroundIO* operation) {
-  DCHECK(callback_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(callback_task_runner_->RunsTasksInCurrentSequence());
   io_list_.insert(make_scoped_refptr(operation));
 }
 
diff --git a/net/extras/sqlite/sqlite_channel_id_store.cc b/net/extras/sqlite/sqlite_channel_id_store.cc
index 9dc30d37..70ca8d9 100644
--- a/net/extras/sqlite/sqlite_channel_id_store.cc
+++ b/net/extras/sqlite/sqlite_channel_id_store.cc
@@ -197,7 +197,7 @@
 void SQLiteChannelIDStore::Backend::LoadInBackground(
     std::vector<std::unique_ptr<DefaultChannelIDStore::ChannelID>>*
         channel_ids) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   // This method should be called only once per instance.
   DCHECK(!db_.get());
@@ -428,7 +428,7 @@
 void SQLiteChannelIDStore::Backend::DatabaseErrorCallback(
     int error,
     sql::Statement* stmt) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   if (!sql::IsErrorCatastrophic(error))
     return;
@@ -448,7 +448,7 @@
 }
 
 void SQLiteChannelIDStore::Backend::KillDatabase() {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   if (db_) {
     // This Backend will now be in-memory only. In a future run the database
@@ -521,7 +521,7 @@
 
 void SQLiteChannelIDStore::Backend::PrunePendingOperationsForDeletes(
     const std::list<std::string>& server_identifiers) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
   base::AutoLock locked(lock_);
 
   for (PendingOperationsList::iterator it = pending_.begin();
@@ -547,7 +547,7 @@
 }
 
 void SQLiteChannelIDStore::Backend::Commit() {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   PendingOperationsList ops;
   {
@@ -620,7 +620,7 @@
 }
 
 void SQLiteChannelIDStore::Backend::InternalBackgroundClose() {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
   // Commit any pending operations
   Commit();
   db_.reset();
@@ -628,7 +628,7 @@
 
 void SQLiteChannelIDStore::Backend::BackgroundDeleteAllInList(
     const std::list<std::string>& server_identifiers) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   if (!db_.get())
     return;
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
index 83cc469..f0167a3 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -498,7 +498,7 @@
 void SQLitePersistentCookieStore::Backend::LoadAndNotifyInBackground(
     const LoadedCallback& loaded_callback,
     const base::Time& posted_at) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
   IncrementTimeDelta increment(&cookie_load_duration_);
 
   UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeLoadDBQueueWait",
@@ -518,7 +518,7 @@
     const std::string& key,
     const LoadedCallback& loaded_callback,
     const base::Time& posted_at) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
   IncrementTimeDelta increment(&cookie_load_duration_);
 
   UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeKeyLoadDBQueueWait",
@@ -556,7 +556,7 @@
     const LoadedCallback& loaded_callback,
     bool load_success,
     const ::Time& requested_at) {
-  DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(client_task_runner_->RunsTasksInCurrentSequence());
 
   UMA_HISTOGRAM_CUSTOM_TIMES("Cookie.TimeKeyLoadTotalWait",
                              base::Time::Now() - requested_at,
@@ -615,7 +615,7 @@
 void SQLitePersistentCookieStore::Backend::Notify(
     const LoadedCallback& loaded_callback,
     bool load_success) {
-  DCHECK(client_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(client_task_runner_->RunsTasksInCurrentSequence());
 
   std::vector<std::unique_ptr<CanonicalCookie>> cookies;
   {
@@ -627,7 +627,7 @@
 }
 
 bool SQLitePersistentCookieStore::Backend::InitializeDatabase() {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   if (initialized_ || corruption_detected_) {
     // Return false if we were previously initialized but the DB has since been
@@ -730,7 +730,7 @@
 
 void SQLitePersistentCookieStore::Backend::ChainLoadCookies(
     const LoadedCallback& loaded_callback) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
   IncrementTimeDelta increment(&cookie_load_duration_);
 
   bool load_success = true;
@@ -765,7 +765,7 @@
 
 bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
     const std::set<std::string>& domains) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   sql::Statement smt;
   if (restore_old_session_cookies_) {
@@ -1073,7 +1073,7 @@
   static const int kCommitIntervalMs = 30 * 1000;
   // Commit right away if we have more than 512 outstanding operations.
   static const size_t kCommitAfterBatchSize = 512;
-  DCHECK(!background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(!background_task_runner_->RunsTasksInCurrentSequence());
 
   // We do a full copy of the cookie here, and hopefully just here.
   std::unique_ptr<PendingOperation> po(new PendingOperation(op, cc));
@@ -1099,7 +1099,7 @@
 }
 
 void SQLitePersistentCookieStore::Backend::Commit() {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   PendingOperationsList ops;
   {
@@ -1202,7 +1202,7 @@
 
 void SQLitePersistentCookieStore::Backend::Flush(
     const base::Closure& callback) {
-  DCHECK(!background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(!background_task_runner_->RunsTasksInCurrentSequence());
   PostBackgroundTask(FROM_HERE, base::Bind(&Backend::FlushAndNotifyInBackground,
                                            this, callback));
 }
@@ -1212,7 +1212,7 @@
 // this fires we will already have been cleaned up and it will be ignored.
 void SQLitePersistentCookieStore::Backend::Close(
     const base::Closure& callback) {
-  if (background_task_runner_->RunsTasksOnCurrentThread()) {
+  if (background_task_runner_->RunsTasksInCurrentSequence()) {
     InternalBackgroundClose(callback);
   } else {
     // Must close the backend on the background runner.
@@ -1223,7 +1223,7 @@
 
 void SQLitePersistentCookieStore::Backend::InternalBackgroundClose(
     const base::Closure& callback) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
   // Commit any pending operations
   Commit();
 
@@ -1238,7 +1238,7 @@
 void SQLitePersistentCookieStore::Backend::DatabaseErrorCallback(
     int error,
     sql::Statement* stmt) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   if (!sql::IsErrorCatastrophic(error))
     return;
@@ -1259,7 +1259,7 @@
 }
 
 void SQLitePersistentCookieStore::Backend::KillDatabase() {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   if (db_) {
     // This Backend will now be in-memory only. In a future run we will recreate
@@ -1276,7 +1276,7 @@
   if (cookies.empty())
     return;
 
-  if (background_task_runner_->RunsTasksOnCurrentThread()) {
+  if (background_task_runner_->RunsTasksInCurrentSequence()) {
     BackgroundDeleteAllInList(cookies);
   } else {
     // Perform deletion on background task runner.
@@ -1287,7 +1287,7 @@
 }
 
 void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
   base::Time start_time = base::Time::Now();
   if (!db_->Execute("DELETE FROM cookies WHERE persistent != 1"))
     LOG(WARNING) << "Unable to delete session cookies.";
@@ -1300,7 +1300,7 @@
 
 void SQLitePersistentCookieStore::Backend::BackgroundDeleteAllInList(
     const std::list<CookieOrigin>& cookies) {
-  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
 
   if (!db_)
     return;
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index 4b3c0c1a..d8be57e 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -203,7 +203,8 @@
   std::unique_ptr<CookieCryptor> cookie_crypto_delegate_;
 };
 
-TEST_F(SQLitePersistentCookieStoreTest, TestInvalidMetaTableRecovery) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_TestInvalidMetaTableRecovery) {
   InitializeStore(false, false);
   AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
   DestroyStore();
@@ -244,7 +245,8 @@
 }
 
 // Test if data is stored as expected in the SQLite database.
-TEST_F(SQLitePersistentCookieStoreTest, TestPersistance) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_TestPersistance) {
   InitializeStore(false, false);
   AddCookie("A", "B", "foo.bar", "/", base::Time::Now());
   // Replace the store effectively destroying the current one and forcing it
@@ -269,7 +271,9 @@
   ASSERT_EQ(0U, cookies.size());
 }
 
-TEST_F(SQLitePersistentCookieStoreTest, TestSessionCookiesDeletedOnStartup) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest,
+       DISABLED_TestSessionCookiesDeletedOnStartup) {
   // Initialize the cookie store with 3 persistent cookies, 5 transient
   // cookies.
   InitializeStore(false, false);
@@ -343,7 +347,8 @@
 
 // Test that priority load of cookies for a specfic domain key could be
 // completed before the entire store is loaded
-TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
+// TODO(mattcary): disabled for flakily timing out: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_TestLoadCookiesForKey) {
   InitializeStore(false, false);
   base::Time t = base::Time::Now();
   AddCookie("A", "B", "foo.bar", "/", t);
@@ -421,7 +426,8 @@
 }
 
 // Test that we can force the database to be written by calling Flush().
-TEST_F(SQLitePersistentCookieStoreTest, TestFlush) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_TestFlush) {
   InitializeStore(false, false);
   // File timestamps don't work well on all platforms, so we'll determine
   // whether the DB file has been modified by checking its size.
@@ -447,7 +453,8 @@
 }
 
 // Test loading old session cookies from the disk.
-TEST_F(SQLitePersistentCookieStoreTest, TestLoadOldSessionCookies) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_TestLoadOldSessionCookies) {
   InitializeStore(false, true);
 
   // Add a session cookie.
@@ -474,7 +481,9 @@
 }
 
 // Test loading old session cookies from the disk.
-TEST_F(SQLitePersistentCookieStoreTest, TestDontLoadOldSessionCookies) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest,
+       DISABLED_TestDontLoadOldSessionCookies) {
   InitializeStore(false, true);
 
   // Add a session cookie.
@@ -502,7 +511,8 @@
   ASSERT_EQ(0U, cookies.size());
 }
 
-TEST_F(SQLitePersistentCookieStoreTest, PersistIsPersistent) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_PersistIsPersistent) {
   InitializeStore(false, true);
   static const char kSessionName[] = "session";
   static const char kPersistentName[] = "persistent";
@@ -543,7 +553,8 @@
   cookies.clear();
 }
 
-TEST_F(SQLitePersistentCookieStoreTest, PriorityIsPersistent) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_PriorityIsPersistent) {
   static const char kDomain[] = "sessioncookie.com";
   static const char kLowName[] = "low";
   static const char kMediumName[] = "medium";
@@ -604,7 +615,8 @@
   cookies.clear();
 }
 
-TEST_F(SQLitePersistentCookieStoreTest, SameSiteIsPersistent) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_SameSiteIsPersistent) {
   const char kDomain[] = "sessioncookie.com";
   const char kNoneName[] = "none";
   const char kLaxName[] = "lax";
@@ -662,7 +674,7 @@
   cookies.clear();
 }
 
-// TODO(mattcary): disabled for breaking cronet K build: crbug.com/727566.
+// TODO(mattcary): disabled for flakily timing out: crbug.com/727566.
 TEST_F(SQLitePersistentCookieStoreTest, DISABLED_UpdateToEncryption) {
   CanonicalCookieVector cookies;
 
@@ -733,7 +745,8 @@
   EXPECT_EQ(contents.find("something456ABC"), std::string::npos);
 }
 
-TEST_F(SQLitePersistentCookieStoreTest, UpdateFromEncryption) {
+// TODO(mattcary): disabled for flakily timing out: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_UpdateFromEncryption) {
   CanonicalCookieVector cookies;
 
   // Create unencrypted cookie store and write something to it.
@@ -792,7 +805,8 @@
 }
 }
 
-TEST_F(SQLitePersistentCookieStoreTest, EmptyLoadAfterClose) {
+// TODO(mattcary): disabled for possibly causing iOS timeouts: crbug.com/727566.
+TEST_F(SQLitePersistentCookieStoreTest, DISABLED_EmptyLoadAfterClose) {
   // Create unencrypted cookie store and write something to it.
   InitializeStore(false, false);
   AddCookie("name", "value123XYZ", "foo.bar", "/", base::Time::Now());
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc
index 2af299f..95ef2f4 100644
--- a/net/http/http_server_properties_manager.cc
+++ b/net/http/http_server_properties_manager.cc
@@ -81,7 +81,7 @@
       setting_prefs_(false),
       is_initialized_(false),
       network_task_runner_(std::move(network_task_runner)) {
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
   DCHECK(pref_delegate_);
   pref_weak_ptr_factory_.reset(
       new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
@@ -94,12 +94,12 @@
 }
 
 HttpServerPropertiesManager::~HttpServerPropertiesManager() {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   network_weak_ptr_factory_.reset();
 }
 
-void HttpServerPropertiesManager::InitializeOnNetworkThread() {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+void HttpServerPropertiesManager::InitializeOnNetworkSequence() {
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
 
   network_weak_ptr_factory_.reset(
       new base::WeakPtrFactory<HttpServerPropertiesManager>(this));
@@ -107,19 +107,20 @@
 
   network_prefs_update_timer_.reset(new base::OneShotTimer);
   network_prefs_update_timer_->SetTaskRunner(network_task_runner_);
-  // UpdateCacheFromPrefsOnPrefThread() will post a task to network thread to
+  // UpdateCacheFromPrefsOnPrefSequence() will post a task to network thread to
   // update server properties. SetInitialized() will be run after that task is
   // run as |network_task_runner_| is single threaded.
   pref_task_runner_->PostTaskAndReply(
       FROM_HERE,
-      base::Bind(&HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread,
-                 pref_weak_ptr_),
+      base::Bind(
+          &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefSequence,
+          pref_weak_ptr_),
       base::Bind(&HttpServerPropertiesManager::SetInitialized,
                  network_weak_ptr_factory_->GetWeakPtr()));
 }
 
-void HttpServerPropertiesManager::ShutdownOnPrefThread() {
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+void HttpServerPropertiesManager::ShutdownOnPrefSequence() {
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
   // Cancel any pending updates, and stop listening for pref change updates.
   pref_cache_update_timer_->Stop();
   pref_weak_ptr_factory_.reset();
@@ -142,59 +143,59 @@
 }
 
 void HttpServerPropertiesManager::Clear(const base::Closure& completion) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
 
   http_server_properties_impl_->Clear();
-  UpdatePrefsFromCacheOnNetworkThread(completion);
+  UpdatePrefsFromCacheOnNetworkSequence(completion);
 }
 
 bool HttpServerPropertiesManager::SupportsRequestPriority(
     const url::SchemeHostPort& server) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->SupportsRequestPriority(server);
 }
 
 bool HttpServerPropertiesManager::GetSupportsSpdy(
     const url::SchemeHostPort& server) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->GetSupportsSpdy(server);
 }
 
 void HttpServerPropertiesManager::SetSupportsSpdy(
     const url::SchemeHostPort& server,
     bool support_spdy) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
 
   bool old_support_spdy = http_server_properties_impl_->GetSupportsSpdy(server);
   http_server_properties_impl_->SetSupportsSpdy(server, support_spdy);
   bool new_support_spdy = http_server_properties_impl_->GetSupportsSpdy(server);
   if (old_support_spdy != new_support_spdy)
-    ScheduleUpdatePrefsOnNetworkThread(SUPPORTS_SPDY);
+    ScheduleUpdatePrefsOnNetworkSequence(SUPPORTS_SPDY);
 }
 
 bool HttpServerPropertiesManager::RequiresHTTP11(const HostPortPair& server) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->RequiresHTTP11(server);
 }
 
 void HttpServerPropertiesManager::SetHTTP11Required(
     const HostPortPair& server) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
 
   http_server_properties_impl_->SetHTTP11Required(server);
-  ScheduleUpdatePrefsOnNetworkThread(HTTP_11_REQUIRED);
+  ScheduleUpdatePrefsOnNetworkSequence(HTTP_11_REQUIRED);
 }
 
 void HttpServerPropertiesManager::MaybeForceHTTP11(const HostPortPair& server,
                                                    SSLConfig* ssl_config) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   http_server_properties_impl_->MaybeForceHTTP11(server, ssl_config);
 }
 
 AlternativeServiceInfoVector
 HttpServerPropertiesManager::GetAlternativeServiceInfos(
     const url::SchemeHostPort& origin) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->GetAlternativeServiceInfos(origin);
 }
 
@@ -202,11 +203,11 @@
     const url::SchemeHostPort& origin,
     const AlternativeService& alternative_service,
     base::Time expiration) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   const bool changed = http_server_properties_impl_->SetAlternativeService(
       origin, alternative_service, expiration);
   if (changed) {
-    ScheduleUpdatePrefsOnNetworkThread(SET_ALTERNATIVE_SERVICES);
+    ScheduleUpdatePrefsOnNetworkSequence(SET_ALTERNATIVE_SERVICES);
   }
   return changed;
 }
@@ -214,48 +215,49 @@
 bool HttpServerPropertiesManager::SetAlternativeServices(
     const url::SchemeHostPort& origin,
     const AlternativeServiceInfoVector& alternative_service_info_vector) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   const bool changed = http_server_properties_impl_->SetAlternativeServices(
       origin, alternative_service_info_vector);
   if (changed) {
-    ScheduleUpdatePrefsOnNetworkThread(SET_ALTERNATIVE_SERVICES);
+    ScheduleUpdatePrefsOnNetworkSequence(SET_ALTERNATIVE_SERVICES);
   }
   return changed;
 }
 
 void HttpServerPropertiesManager::MarkAlternativeServiceBroken(
     const AlternativeService& alternative_service) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   http_server_properties_impl_->MarkAlternativeServiceBroken(
       alternative_service);
-  ScheduleUpdatePrefsOnNetworkThread(MARK_ALTERNATIVE_SERVICE_BROKEN);
+  ScheduleUpdatePrefsOnNetworkSequence(MARK_ALTERNATIVE_SERVICE_BROKEN);
 }
 
 void HttpServerPropertiesManager::MarkAlternativeServiceRecentlyBroken(
     const AlternativeService& alternative_service) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   http_server_properties_impl_->MarkAlternativeServiceRecentlyBroken(
       alternative_service);
-  ScheduleUpdatePrefsOnNetworkThread(MARK_ALTERNATIVE_SERVICE_RECENTLY_BROKEN);
+  ScheduleUpdatePrefsOnNetworkSequence(
+      MARK_ALTERNATIVE_SERVICE_RECENTLY_BROKEN);
 }
 
 bool HttpServerPropertiesManager::IsAlternativeServiceBroken(
     const AlternativeService& alternative_service) const {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->IsAlternativeServiceBroken(
       alternative_service);
 }
 
 bool HttpServerPropertiesManager::WasAlternativeServiceRecentlyBroken(
     const AlternativeService& alternative_service) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->WasAlternativeServiceRecentlyBroken(
       alternative_service);
 }
 
 void HttpServerPropertiesManager::ConfirmAlternativeService(
     const AlternativeService& alternative_service) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   bool old_value = http_server_properties_impl_->IsAlternativeServiceBroken(
       alternative_service);
   http_server_properties_impl_->ConfirmAlternativeService(alternative_service);
@@ -264,43 +266,43 @@
   // For persisting, we only care about the value returned by
   // IsAlternativeServiceBroken. If that value changes, then call persist.
   if (old_value != new_value)
-    ScheduleUpdatePrefsOnNetworkThread(CONFIRM_ALTERNATIVE_SERVICE);
+    ScheduleUpdatePrefsOnNetworkSequence(CONFIRM_ALTERNATIVE_SERVICE);
 }
 
 const AlternativeServiceMap&
 HttpServerPropertiesManager::alternative_service_map() const {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->alternative_service_map();
 }
 
 std::unique_ptr<base::Value>
 HttpServerPropertiesManager::GetAlternativeServiceInfoAsValue() const {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->GetAlternativeServiceInfoAsValue();
 }
 
 bool HttpServerPropertiesManager::GetSupportsQuic(
     IPAddress* last_address) const {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->GetSupportsQuic(last_address);
 }
 
 void HttpServerPropertiesManager::SetSupportsQuic(bool used_quic,
                                                   const IPAddress& address) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   IPAddress old_last_quic_addr;
   http_server_properties_impl_->GetSupportsQuic(&old_last_quic_addr);
   http_server_properties_impl_->SetSupportsQuic(used_quic, address);
   IPAddress new_last_quic_addr;
   http_server_properties_impl_->GetSupportsQuic(&new_last_quic_addr);
   if (old_last_quic_addr != new_last_quic_addr)
-    ScheduleUpdatePrefsOnNetworkThread(SET_SUPPORTS_QUIC);
+    ScheduleUpdatePrefsOnNetworkSequence(SET_SUPPORTS_QUIC);
 }
 
 void HttpServerPropertiesManager::SetServerNetworkStats(
     const url::SchemeHostPort& server,
     ServerNetworkStats stats) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   ServerNetworkStats old_stats;
   const ServerNetworkStats* old_stats_ptr =
       http_server_properties_impl_->GetServerNetworkStats(server);
@@ -310,70 +312,70 @@
   ServerNetworkStats new_stats =
       *(http_server_properties_impl_->GetServerNetworkStats(server));
   if (old_stats != new_stats)
-    ScheduleUpdatePrefsOnNetworkThread(SET_SERVER_NETWORK_STATS);
+    ScheduleUpdatePrefsOnNetworkSequence(SET_SERVER_NETWORK_STATS);
 }
 
 void HttpServerPropertiesManager::ClearServerNetworkStats(
     const url::SchemeHostPort& server) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   bool need_update =
       http_server_properties_impl_->GetServerNetworkStats(server) != nullptr;
   http_server_properties_impl_->ClearServerNetworkStats(server);
   if (need_update)
-    ScheduleUpdatePrefsOnNetworkThread(CLEAR_SERVER_NETWORK_STATS);
+    ScheduleUpdatePrefsOnNetworkSequence(CLEAR_SERVER_NETWORK_STATS);
 }
 
 const ServerNetworkStats* HttpServerPropertiesManager::GetServerNetworkStats(
     const url::SchemeHostPort& server) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->GetServerNetworkStats(server);
 }
 
 const ServerNetworkStatsMap&
 HttpServerPropertiesManager::server_network_stats_map() const {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->server_network_stats_map();
 }
 
 bool HttpServerPropertiesManager::SetQuicServerInfo(
     const QuicServerId& server_id,
     const std::string& server_info) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   bool changed =
       http_server_properties_impl_->SetQuicServerInfo(server_id, server_info);
   if (changed)
-    ScheduleUpdatePrefsOnNetworkThread(SET_QUIC_SERVER_INFO);
+    ScheduleUpdatePrefsOnNetworkSequence(SET_QUIC_SERVER_INFO);
   return changed;
 }
 
 const std::string* HttpServerPropertiesManager::GetQuicServerInfo(
     const QuicServerId& server_id) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->GetQuicServerInfo(server_id);
 }
 
 const QuicServerInfoMap& HttpServerPropertiesManager::quic_server_info_map()
     const {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->quic_server_info_map();
 }
 
 size_t HttpServerPropertiesManager::max_server_configs_stored_in_properties()
     const {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_
       ->max_server_configs_stored_in_properties();
 }
 
 void HttpServerPropertiesManager::SetMaxServerConfigsStoredInProperties(
     size_t max_server_configs_stored_in_properties) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   return http_server_properties_impl_->SetMaxServerConfigsStoredInProperties(
       max_server_configs_stored_in_properties);
 }
 
 bool HttpServerPropertiesManager::IsInitialized() const {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
 
   return is_initialized_;
 }
@@ -392,19 +394,19 @@
 // Update the HttpServerPropertiesImpl's cache with data from preferences.
 //
 void HttpServerPropertiesManager::ScheduleUpdateCacheOnPrefThread() {
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
   // Do not schedule a new update if there is already one scheduled.
   if (pref_cache_update_timer_->IsRunning())
     return;
 
   pref_cache_update_timer_->Start(
       FROM_HERE, kUpdateCacheDelay, this,
-      &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread);
+      &HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefSequence);
 }
 
-void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread() {
+void HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefSequence() {
   // The preferences can only be read on the pref thread.
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
 
   if (!pref_delegate_->HasServerProperties())
     return;
@@ -515,7 +517,7 @@
   network_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(
-          &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread,
+          &HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkSequence,
           base::Unretained(this), base::Owned(spdy_servers.release()),
           base::Owned(alternative_service_map.release()), base::Owned(addr),
           base::Owned(server_network_stats_map.release()),
@@ -772,7 +774,7 @@
   return !detected_corrupted_prefs;
 }
 
-void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkThread(
+void HttpServerPropertiesManager::UpdateCacheFromPrefsOnNetworkSequence(
     ServerList* spdy_servers,
     AlternativeServiceMap* alternative_service_map,
     IPAddress* last_quic_address,
@@ -781,7 +783,7 @@
     bool detected_corrupted_prefs) {
   // Preferences have the master data because admins might have pushed new
   // preferences. Update the cached data with new data from preferences.
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
 
   UMA_HISTOGRAM_COUNTS("Net.CountOfSpdyServers", spdy_servers->size());
   http_server_properties_impl_->SetSpdyServers(spdy_servers, true);
@@ -804,22 +806,22 @@
 
   // Update the prefs with what we have read (delete all corrupted prefs).
   if (detected_corrupted_prefs)
-    ScheduleUpdatePrefsOnNetworkThread(DETECTED_CORRUPTED_PREFS);
+    ScheduleUpdatePrefsOnNetworkSequence(DETECTED_CORRUPTED_PREFS);
 }
 
 //
 // Update Preferences with data from the cached data.
 //
-void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread(
+void HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkSequence(
     Location location) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   // Do not schedule a new update if there is already one scheduled.
   if (network_prefs_update_timer_->IsRunning())
     return;
 
   network_prefs_update_timer_->Start(
       FROM_HERE, kUpdatePrefsDelay, this,
-      &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread);
+      &HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkSequence);
 
   // TODO(rtenneti): Delete the following histogram after collecting some data.
   UMA_HISTOGRAM_ENUMERATION("Net.HttpServerProperties.UpdatePrefs", location,
@@ -827,13 +829,13 @@
 }
 
 // This is required so we can set this as the callback for a timer.
-void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread() {
-  UpdatePrefsFromCacheOnNetworkThread(base::Closure());
+void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkSequence() {
+  UpdatePrefsFromCacheOnNetworkSequence(base::Closure());
 }
 
-void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(
+void HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkSequence(
     const base::Closure& completion) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
 
   // It is in MRU order.
   base::ListValue* spdy_server_list = new base::ListValue;
@@ -964,7 +966,7 @@
   typedef base::MRUCache<url::SchemeHostPort, ServerPref> ServerPrefMap;
   ServerPrefMap server_pref_map(ServerPrefMap::NO_AUTO_EVICT);
 
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
 
   // Add servers that support spdy to server_pref_map in the MRU order.
   for (size_t index = spdy_server_list->GetSize(); index > 0; --index) {
@@ -1143,13 +1145,13 @@
 }
 
 void HttpServerPropertiesManager::OnHttpServerPropertiesChanged() {
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
   if (!setting_prefs_)
     ScheduleUpdateCacheOnPrefThread();
 }
 
 void HttpServerPropertiesManager::SetInitialized() {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   is_initialized_ = true;
 }
 
diff --git a/net/http/http_server_properties_manager.h b/net/http/http_server_properties_manager.h
index b8ac58d2..0b7dc11 100644
--- a/net/http/http_server_properties_manager.h
+++ b/net/http/http_server_properties_manager.h
@@ -49,7 +49,7 @@
 // It must be constructed with correct task runners passed in to set up
 // |pref_task_runner_| and |network_task_runner| as well as the prefs listeners.
 //
-// ShutdownOnPrefThread must be called from pref thread before destruction, to
+// ShutdownOnPrefSequence must be called from pref thread before destruction, to
 // release the prefs listeners on the pref thread.
 //
 // Class requires that update tasks from the Pref thread can post safely to the
@@ -99,10 +99,10 @@
   ~HttpServerPropertiesManager() override;
 
   // Initialize on Network thread.
-  void InitializeOnNetworkThread();
+  void InitializeOnNetworkSequence();
 
   // Prepare for shutdown. Must be called on the Pref thread before destruction.
-  void ShutdownOnPrefThread();
+  void ShutdownOnPrefSequence();
 
   // Helper function for unit tests to set the version in the dictionary.
   static void SetVersion(base::DictionaryValue* http_server_properties_dict,
@@ -167,7 +167,7 @@
   static base::TimeDelta GetUpdatePrefsDelayForTesting();
 
  protected:
-  // The location where ScheduleUpdatePrefsOnNetworkThread was called.
+  // The location where ScheduleUpdatePrefsOnNetworkSequence was called.
   // Must be kept up to date with HttpServerPropertiesUpdatePrefsLocation in
   // histograms.xml.
   enum Location {
@@ -201,11 +201,11 @@
   // preferences. It gets the data on pref thread and calls
   // UpdateSpdyServersFromPrefsOnNetworkThread() to perform the update on
   // network thread.
-  virtual void UpdateCacheFromPrefsOnPrefThread();
+  virtual void UpdateCacheFromPrefsOnPrefSequence();
 
   // Starts the update of cached prefs in |http_server_properties_impl_| on the
   // network thread. Protected for testing.
-  void UpdateCacheFromPrefsOnNetworkThread(
+  void UpdateCacheFromPrefsOnNetworkSequence(
       std::vector<std::string>* spdy_servers,
       AlternativeServiceMap* alternative_service_map,
       IPAddress* last_quic_address,
@@ -217,17 +217,17 @@
   // |http_server_properties_impl_| is changing, and execute only one update per
   // simultaneous spdy_servers or spdy_settings or alternative_service changes.
   // |location| specifies where this method is called from. Virtual for testing.
-  virtual void ScheduleUpdatePrefsOnNetworkThread(Location location);
+  virtual void ScheduleUpdatePrefsOnNetworkSequence(Location location);
 
   // Update prefs::kHttpServerProperties in preferences with the cached data
   // from |http_server_properties_impl_|. This gets the data on network thread
   // and posts a task (UpdatePrefsOnPrefThread) to update preferences on pref
   // thread.
-  void UpdatePrefsFromCacheOnNetworkThread();
+  void UpdatePrefsFromCacheOnNetworkSequence();
 
   // Same as above, but fires an optional |completion| callback on pref thread
   // when finished. Virtual for testing.
-  virtual void UpdatePrefsFromCacheOnNetworkThread(
+  virtual void UpdatePrefsFromCacheOnNetworkSequence(
       const base::Closure& completion);
 
   // Update prefs::kHttpServerProperties preferences on pref thread. Executes an
@@ -303,7 +303,7 @@
   // Network thread
   // --------------
 
-  // Whether InitializeOnNetworkThread() has completed.
+  // Whether InitializeOnNetworkSequence() has completed.
   bool is_initialized_;
 
   const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc
index c22ed26..b10b337 100644
--- a/net/http/http_server_properties_manager_unittest.cc
+++ b/net/http/http_server_properties_manager_unittest.cc
@@ -91,7 +91,7 @@
         net_task_runner_(std::move(net_task_runner)) {
     // This call must run in the context of |net_task_runner_|.
     TestMockTimeTaskRunner::ScopedContext scoped_context(net_task_runner_);
-    HttpServerPropertiesManager::InitializeOnNetworkThread();
+    HttpServerPropertiesManager::InitializeOnNetworkSequence();
   }
 
   ~TestingHttpServerPropertiesManager() override {}
@@ -101,31 +101,33 @@
 
   void UpdateCacheFromPrefsOnUIConcrete() {
     TestMockTimeTaskRunner::ScopedContext scoped_context(pref_task_runner_);
-    HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefThread();
+    HttpServerPropertiesManager::UpdateCacheFromPrefsOnPrefSequence();
   }
 
-  void UpdatePrefsFromCacheOnNetworkThreadConcrete(
+  void UpdatePrefsFromCacheOnNetworkSequenceConcrete(
       const base::Closure& callback) {
     TestMockTimeTaskRunner::ScopedContext scoped_context(net_task_runner_);
-    HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkThread(callback);
+    HttpServerPropertiesManager::UpdatePrefsFromCacheOnNetworkSequence(
+        callback);
   }
 
-  void ScheduleUpdatePrefsOnNetworkThreadConcrete(Location location) {
+  void ScheduleUpdatePrefsOnNetworkSequenceConcrete(Location location) {
     TestMockTimeTaskRunner::ScopedContext scoped_context(net_task_runner_);
-    HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread(location);
+    HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkSequence(location);
   }
 
-  void ScheduleUpdatePrefsOnNetworkThreadDefault() {
+  void ScheduleUpdatePrefsOnNetworkSequenceDefault() {
     TestMockTimeTaskRunner::ScopedContext scoped_context(net_task_runner_);
     // Picked a random Location as caller.
-    HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkThread(
+    HttpServerPropertiesManager::ScheduleUpdatePrefsOnNetworkSequence(
         DETECTED_CORRUPTED_PREFS);
   }
 
-  MOCK_METHOD0(UpdateCacheFromPrefsOnPrefThread, void());
-  MOCK_METHOD1(UpdatePrefsFromCacheOnNetworkThread, void(const base::Closure&));
-  MOCK_METHOD1(ScheduleUpdatePrefsOnNetworkThread, void(Location location));
-  MOCK_METHOD6(UpdateCacheFromPrefsOnNetworkThread,
+  MOCK_METHOD0(UpdateCacheFromPrefsOnPrefSequence, void());
+  MOCK_METHOD1(UpdatePrefsFromCacheOnNetworkSequence,
+               void(const base::Closure&));
+  MOCK_METHOD1(ScheduleUpdatePrefsOnNetworkSequence, void(Location location));
+  MOCK_METHOD6(UpdateCacheFromPrefsOnNetworkSequence,
                void(std::vector<std::string>* spdy_servers,
                     AlternativeServiceMap* alternative_service_map,
                     IPAddress* last_quic_address,
@@ -179,7 +181,7 @@
 
   void TearDown() override {
     if (http_server_props_manager_.get())
-      http_server_props_manager_->ShutdownOnPrefThread();
+      http_server_props_manager_->ShutdownOnPrefSequence();
     // Run pending non-delayed tasks but don't FastForwardUntilNoTasksRemain()
     // as some delayed tasks may forever repost (e.g. because impl doesn't use a
     // mock clock and doesn't see timings as having expired, ref.
@@ -191,37 +193,39 @@
   }
 
   void ExpectCacheUpdate() {
-    EXPECT_CALL(*http_server_props_manager_, UpdateCacheFromPrefsOnPrefThread())
+    EXPECT_CALL(*http_server_props_manager_,
+                UpdateCacheFromPrefsOnPrefSequence())
         .WillOnce(Invoke(http_server_props_manager_.get(),
                          &TestingHttpServerPropertiesManager::
                              UpdateCacheFromPrefsOnUIConcrete));
   }
 
-  void ExpectScheduleUpdatePrefsOnNetworkThread() {
+  void ExpectScheduleUpdatePrefsOnNetworkSequence() {
     EXPECT_CALL(*http_server_props_manager_,
-                ScheduleUpdatePrefsOnNetworkThread(_))
+                ScheduleUpdatePrefsOnNetworkSequence(_))
         .WillOnce(Invoke(http_server_props_manager_.get(),
                          &TestingHttpServerPropertiesManager::
-                             ScheduleUpdatePrefsOnNetworkThreadConcrete));
+                             ScheduleUpdatePrefsOnNetworkSequenceConcrete));
   }
 
-  void ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(int times) {
+  void ExpectScheduleUpdatePrefsOnNetworkSequenceRepeatedly(int times) {
     EXPECT_CALL(*http_server_props_manager_,
-                ScheduleUpdatePrefsOnNetworkThread(_))
+                ScheduleUpdatePrefsOnNetworkSequence(_))
         .Times(AtLeast(times))
-        .WillRepeatedly(Invoke(http_server_props_manager_.get(),
-                               &TestingHttpServerPropertiesManager::
-                                   ScheduleUpdatePrefsOnNetworkThreadConcrete));
+        .WillRepeatedly(
+            Invoke(http_server_props_manager_.get(),
+                   &TestingHttpServerPropertiesManager::
+                       ScheduleUpdatePrefsOnNetworkSequenceConcrete));
   }
 
   void ExpectPrefsUpdate(int times) {
     EXPECT_CALL(*http_server_props_manager_,
-                UpdatePrefsFromCacheOnNetworkThread(_))
+                UpdatePrefsFromCacheOnNetworkSequence(_))
         .Times(times)
         .WillRepeatedly(
             Invoke(http_server_props_manager_.get(),
                    &TestingHttpServerPropertiesManager::
-                       UpdatePrefsFromCacheOnNetworkThreadConcrete));
+                       UpdatePrefsFromCacheOnNetworkSequenceConcrete));
   }
 
   bool HasAlternativeService(const url::SchemeHostPort& server) {
@@ -478,7 +482,7 @@
   ExpectCacheUpdate();
   // The prefs are automatically updated in the case corruption is detected.
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThread();
+  ExpectScheduleUpdatePrefsOnNetworkSequence();
 
   auto server_pref_dict = base::MakeUnique<base::DictionaryValue>();
 
@@ -567,7 +571,7 @@
   ExpectCacheUpdate();
   // The prefs are automatically updated in the case corruption is detected.
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThread();
+  ExpectScheduleUpdatePrefsOnNetworkSequence();
 
   auto server_pref_dict = base::MakeUnique<base::DictionaryValue>();
 
@@ -628,17 +632,17 @@
 
 TEST_P(HttpServerPropertiesManagerTest, SupportsSpdy) {
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThread();
+  ExpectScheduleUpdatePrefsOnNetworkSequence();
 
   // Post an update task to the network thread. SetSupportsSpdy calls
-  // ScheduleUpdatePrefsOnNetworkThread.
+  // ScheduleUpdatePrefsOnNetworkSequence.
 
   // Add mail.google.com:443 as a supporting spdy server.
   url::SchemeHostPort spdy_server("https", "mail.google.com", 443);
   EXPECT_FALSE(
       http_server_props_manager_->SupportsRequestPriority(spdy_server));
   http_server_props_manager_->SetSupportsSpdy(spdy_server, true);
-  // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
+  // ExpectScheduleUpdatePrefsOnNetworkSequence() should be called only once.
   http_server_props_manager_->SetSupportsSpdy(spdy_server, true);
 
   // Run the task.
@@ -661,10 +665,10 @@
 TEST_P(HttpServerPropertiesManagerTest,
        SinglePrefUpdateForTwoSpdyServerCacheChanges) {
   ExpectPrefsUpdate(2);
-  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(3);
+  ExpectScheduleUpdatePrefsOnNetworkSequenceRepeatedly(3);
 
   // Post an update task to the network thread. SetSupportsSpdy calls
-  // ScheduleUpdatePrefsOnNetworkThread with a delay of 60ms.
+  // ScheduleUpdatePrefsOnNetworkSequence with a delay of 60ms.
   url::SchemeHostPort spdy_server("https", "mail.google.com", 443);
   EXPECT_FALSE(
       http_server_props_manager_->SupportsRequestPriority(spdy_server));
@@ -678,8 +682,8 @@
       base::TimeDelta::FromMilliseconds(20));
 
   // Set another spdy server to trigger another call to
-  // ScheduleUpdatePrefsOnNetworkThread. There should be no new update posted to
-  // the network thread.
+  // ScheduleUpdatePrefsOnNetworkSequence. There should be no new update posted
+  // to the network thread.
   url::SchemeHostPort spdy_server2("https", "drive.google.com", 443);
   http_server_props_manager_->SetSupportsSpdy(spdy_server2, true);
   EXPECT_EQ(1u, net_test_task_runner_->GetPendingTaskCount());
@@ -697,7 +701,7 @@
   EXPECT_TRUE(
       http_server_props_manager_->SupportsRequestPriority(spdy_server2));
   // Set the third spdy server to trigger one more call to
-  // ScheduleUpdatePrefsOnNetworkThread. A new update task should be posted to
+  // ScheduleUpdatePrefsOnNetworkSequence. A new update task should be posted to
   // network thread now since the previous one is completed.
   url::SchemeHostPort spdy_server3("https", "maps.google.com", 443);
   http_server_props_manager_->SetSupportsSpdy(spdy_server3, true);
@@ -718,7 +722,7 @@
 
 TEST_P(HttpServerPropertiesManagerTest, GetAlternativeServiceInfos) {
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThread();
+  ExpectScheduleUpdatePrefsOnNetworkSequence();
 
   url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
   EXPECT_FALSE(HasAlternativeService(spdy_server_mail));
@@ -726,7 +730,7 @@
                                                443);
   http_server_props_manager_->SetAlternativeService(
       spdy_server_mail, alternative_service, one_day_from_now_);
-  // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
+  // ExpectScheduleUpdatePrefsOnNetworkSequence() should be called only once.
   http_server_props_manager_->SetAlternativeService(
       spdy_server_mail, alternative_service, one_day_from_now_);
 
@@ -750,7 +754,7 @@
 
 TEST_P(HttpServerPropertiesManagerTest, SetAlternativeServices) {
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThread();
+  ExpectScheduleUpdatePrefsOnNetworkSequence();
 
   url::SchemeHostPort spdy_server_mail("http", "mail.google.com", 80);
   EXPECT_FALSE(HasAlternativeService(spdy_server_mail));
@@ -765,7 +769,7 @@
       AlternativeServiceInfo(alternative_service2, one_day_from_now_));
   http_server_props_manager_->SetAlternativeServices(
       spdy_server_mail, alternative_service_info_vector);
-  // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
+  // ExpectScheduleUpdatePrefsOnNetworkSequence() should be called only once.
   http_server_props_manager_->SetAlternativeServices(
       spdy_server_mail, alternative_service_info_vector);
 
@@ -797,7 +801,7 @@
   http_server_props_manager_->SetAlternativeServices(
       spdy_server_mail, AlternativeServiceInfoVector());
 
-  // ExpectScheduleUpdatePrefsOnNetworkThread() should not be called.
+  // ExpectScheduleUpdatePrefsOnNetworkSequence() should not be called.
   EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
   EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
   Mock::VerifyAndClearExpectations(http_server_props_manager_.get());
@@ -819,7 +823,7 @@
     alternative_service =
         AlternativeService(kProtoHTTP2, "mail.google.com", 443);
 
-    ExpectScheduleUpdatePrefsOnNetworkThread();
+    ExpectScheduleUpdatePrefsOnNetworkSequence();
     http_server_props_manager_->SetAlternativeService(
         spdy_server_mail, alternative_service, one_day_from_now_);
 
@@ -829,7 +833,7 @@
         http_server_props_manager_->WasAlternativeServiceRecentlyBroken(
             alternative_service));
 
-    ExpectScheduleUpdatePrefsOnNetworkThread();
+    ExpectScheduleUpdatePrefsOnNetworkSequence();
     http_server_props_manager_->MarkAlternativeServiceBroken(
         alternative_service);
     EXPECT_TRUE(http_server_props_manager_->IsAlternativeServiceBroken(
@@ -837,14 +841,14 @@
     EXPECT_TRUE(http_server_props_manager_->WasAlternativeServiceRecentlyBroken(
         alternative_service));
 
-    ExpectScheduleUpdatePrefsOnNetworkThread();
+    ExpectScheduleUpdatePrefsOnNetworkSequence();
     http_server_props_manager_->ConfirmAlternativeService(alternative_service);
     EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken(
         alternative_service));
     EXPECT_FALSE(
         http_server_props_manager_->WasAlternativeServiceRecentlyBroken(
             alternative_service));
-    // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
+    // ExpectScheduleUpdatePrefsOnNetworkSequence() should be called only once.
     http_server_props_manager_->ConfirmAlternativeService(alternative_service);
     EXPECT_FALSE(http_server_props_manager_->IsAlternativeServiceBroken(
         alternative_service));
@@ -876,14 +880,14 @@
 
 TEST_P(HttpServerPropertiesManagerTest, SupportsQuic) {
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThread();
+  ExpectScheduleUpdatePrefsOnNetworkSequence();
 
   IPAddress address;
   EXPECT_FALSE(http_server_props_manager_->GetSupportsQuic(&address));
 
   IPAddress actual_address(127, 0, 0, 1);
   http_server_props_manager_->SetSupportsQuic(true, actual_address);
-  // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
+  // ExpectScheduleUpdatePrefsOnNetworkSequence() should be called only once.
   http_server_props_manager_->SetSupportsQuic(true, actual_address);
 
   // Run the task.
@@ -903,7 +907,7 @@
 
 TEST_P(HttpServerPropertiesManagerTest, ServerNetworkStats) {
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThread();
+  ExpectScheduleUpdatePrefsOnNetworkSequence();
 
   url::SchemeHostPort mail_server("http", "mail.google.com", 80);
   const ServerNetworkStats* stats =
@@ -912,7 +916,7 @@
   ServerNetworkStats stats1;
   stats1.srtt = base::TimeDelta::FromMicroseconds(10);
   http_server_props_manager_->SetServerNetworkStats(mail_server, stats1);
-  // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
+  // ExpectScheduleUpdatePrefsOnNetworkSequence() should be called only once.
   http_server_props_manager_->SetServerNetworkStats(mail_server, stats1);
 
   // Run the task.
@@ -931,7 +935,7 @@
   EXPECT_EQ(10, stats2->srtt.ToInternalValue());
 
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThread();
+  ExpectScheduleUpdatePrefsOnNetworkSequence();
 
   http_server_props_manager_->ClearServerNetworkStats(mail_server);
 
@@ -951,7 +955,7 @@
 
 TEST_P(HttpServerPropertiesManagerTest, QuicServerInfo) {
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThread();
+  ExpectScheduleUpdatePrefsOnNetworkSequence();
 
   QuicServerId mail_quic_server_id("mail.google.com", 80);
   EXPECT_EQ(nullptr,
@@ -959,7 +963,7 @@
   std::string quic_server_info1("quic_server_info1");
   http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id,
                                                 quic_server_info1);
-  // ExpectScheduleUpdatePrefsOnNetworkThread() should be called only once.
+  // ExpectScheduleUpdatePrefsOnNetworkSequence() should be called only once.
   http_server_props_manager_->SetQuicServerInfo(mail_quic_server_id,
                                                 quic_server_info1);
 
@@ -980,7 +984,7 @@
 
 TEST_P(HttpServerPropertiesManagerTest, Clear) {
   ExpectPrefsUpdate(1);
-  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(5);
+  ExpectScheduleUpdatePrefsOnNetworkSequenceRepeatedly(5);
 
   const url::SchemeHostPort spdy_server("https", "mail.google.com", 443);
   const IPAddress actual_address(127, 0, 0, 1);
@@ -1153,7 +1157,7 @@
 }
 
 TEST_P(HttpServerPropertiesManagerTest, UpdatePrefsWithCache) {
-  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(5);
+  ExpectScheduleUpdatePrefsOnNetworkSequenceRepeatedly(5);
 
   const url::SchemeHostPort server_www("https", "www.google.com", 80);
   const url::SchemeHostPort server_mail("https", "mail.google.com", 80);
@@ -1338,7 +1342,7 @@
 // Do not persist expired or broken alternative service entries to disk.
 TEST_P(HttpServerPropertiesManagerTest,
        DoNotPersistExpiredOrBrokenAlternativeService) {
-  ExpectScheduleUpdatePrefsOnNetworkThreadRepeatedly(2);
+  ExpectScheduleUpdatePrefsOnNetworkSequenceRepeatedly(2);
 
   {
     TestMockTimeTaskRunner::ScopedContext scoped_context(net_test_task_runner_);
@@ -1466,7 +1470,7 @@
   // Post an update task to the UI thread.
   http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
   // Shutdown comes before the task is executed.
-  http_server_props_manager_->ShutdownOnPrefThread();
+  http_server_props_manager_->ShutdownOnPrefSequence();
   http_server_props_manager_.reset();
   // Run the task after shutdown and deletion.
   EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
@@ -1480,7 +1484,7 @@
   // Post an update task.
   http_server_props_manager_->ScheduleUpdateCacheOnPrefThread();
   // Shutdown comes before the task is executed.
-  http_server_props_manager_->ShutdownOnPrefThread();
+  http_server_props_manager_->ShutdownOnPrefSequence();
   // Run the task after shutdown, but before deletion.
   EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
   EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
@@ -1497,7 +1501,7 @@
 TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdateCache2) {
   http_server_props_manager_->UpdateCacheFromPrefsOnUIConcrete();
   // Shutdown comes before the task is executed.
-  http_server_props_manager_->ShutdownOnPrefThread();
+  http_server_props_manager_->ShutdownOnPrefSequence();
   // There should be no tasks to run.
   EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
   EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
@@ -1512,9 +1516,9 @@
 //
 TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs0) {
   // Post an update task to the IO thread.
-  http_server_props_manager_->ScheduleUpdatePrefsOnNetworkThreadDefault();
+  http_server_props_manager_->ScheduleUpdatePrefsOnNetworkSequenceDefault();
   // Shutdown comes before the task is executed.
-  http_server_props_manager_->ShutdownOnPrefThread();
+  http_server_props_manager_->ShutdownOnPrefSequence();
   http_server_props_manager_.reset();
   // Run the task after shutdown and deletion.
   EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
@@ -1527,9 +1531,9 @@
 TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs1) {
   ExpectPrefsUpdate(1);
   // Post an update task.
-  http_server_props_manager_->ScheduleUpdatePrefsOnNetworkThreadDefault();
+  http_server_props_manager_->ScheduleUpdatePrefsOnNetworkSequenceDefault();
   // Shutdown comes before the task is executed.
-  http_server_props_manager_->ShutdownOnPrefThread();
+  http_server_props_manager_->ShutdownOnPrefSequence();
   // Run the task after shutdown, but before deletion.
   EXPECT_TRUE(net_test_task_runner_->HasPendingTask());
   EXPECT_FALSE(pref_test_task_runner_->HasPendingTask());
@@ -1547,10 +1551,10 @@
 
 TEST_P(HttpServerPropertiesManagerTest, ShutdownWithPendingUpdatePrefs2) {
   // This posts a task to the UI thread.
-  http_server_props_manager_->UpdatePrefsFromCacheOnNetworkThreadConcrete(
+  http_server_props_manager_->UpdatePrefsFromCacheOnNetworkSequenceConcrete(
       base::Closure());
   // Shutdown comes before the task is executed.
-  http_server_props_manager_->ShutdownOnPrefThread();
+  http_server_props_manager_->ShutdownOnPrefSequence();
   // Run the task after shutdown, but before deletion.
   EXPECT_FALSE(net_test_task_runner_->HasPendingTask());
   EXPECT_TRUE(pref_test_task_runner_->HasPendingTask());
diff --git a/net/http/transport_security_persister.cc b/net/http/transport_security_persister.cc
index 8938b27..44233b6e 100644
--- a/net/http/transport_security_persister.cc
+++ b/net/http/transport_security_persister.cc
@@ -306,7 +306,7 @@
 }
 
 TransportSecurityPersister::~TransportSecurityPersister() {
-  DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+  DCHECK(foreground_runner_->RunsTasksInCurrentSequence());
 
   if (writer_.HasPendingWrite())
     writer_.DoScheduledWrite();
@@ -315,7 +315,7 @@
 }
 
 void TransportSecurityPersister::StateIsDirty(TransportSecurityState* state) {
-  DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+  DCHECK(foreground_runner_->RunsTasksInCurrentSequence());
   DCHECK_EQ(transport_security_state_, state);
 
   if (!readonly_)
@@ -323,7 +323,7 @@
 }
 
 bool TransportSecurityPersister::SerializeData(std::string* output) {
-  DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+  DCHECK(foreground_runner_->RunsTasksInCurrentSequence());
 
   base::DictionaryValue toplevel;
 
@@ -340,7 +340,7 @@
 
 bool TransportSecurityPersister::LoadEntries(const std::string& serialized,
                                              bool* dirty) {
-  DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+  DCHECK(foreground_runner_->RunsTasksInCurrentSequence());
 
   transport_security_state_->ClearDynamicData();
   return Deserialize(serialized, dirty, transport_security_state_);
@@ -491,7 +491,7 @@
 }
 
 void TransportSecurityPersister::CompleteLoad(const std::string& state) {
-  DCHECK(foreground_runner_->RunsTasksOnCurrentThread());
+  DCHECK(foreground_runner_->RunsTasksInCurrentSequence());
 
   if (state.empty())
     return;
diff --git a/net/log/file_net_log_observer.cc b/net/log/file_net_log_observer.cc
index f344556..721ae87 100644
--- a/net/log/file_net_log_observer.cc
+++ b/net/log/file_net_log_observer.cc
@@ -380,7 +380,7 @@
 
 void FileNetLogObserver::BoundedFileWriter::Initialize(
     std::unique_ptr<base::Value> constants_value) {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   event_files_[current_file_idx_] = base::ScopedFILE(
       base::OpenFile(directory_.AppendASCII("event_file_0.json"), "w"));
@@ -400,7 +400,7 @@
 
 void FileNetLogObserver::BoundedFileWriter::Stop(
     std::unique_ptr<base::Value> polled_data) {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   base::ScopedFILE closing_file(
       base::OpenFile(directory_.AppendASCII("end_netlog.json"), "w"));
@@ -418,7 +418,7 @@
 }
 
 void FileNetLogObserver::BoundedFileWriter::IncrementCurrentFile() {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   current_file_idx_++;
   current_file_idx_ %= total_num_files_;
@@ -431,7 +431,7 @@
 
 void FileNetLogObserver::BoundedFileWriter::Flush(
     scoped_refptr<FileNetLogObserver::WriteQueue> write_queue) {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   EventQueue local_file_queue;
   write_queue->SwapQueue(&local_file_queue);
@@ -455,7 +455,7 @@
 }
 
 void FileNetLogObserver::BoundedFileWriter::DeleteAllFiles() {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   // Reset |event_files_| to release all file handles so base::DeleteFile can
   // safely access files.
@@ -479,7 +479,7 @@
 
 void FileNetLogObserver::UnboundedFileWriter::Initialize(
     std::unique_ptr<base::Value> constants_value) {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   file_.reset(base::OpenFile(file_path_, "w"));
   first_event_written_ = false;
@@ -495,7 +495,7 @@
 
 void FileNetLogObserver::UnboundedFileWriter::Stop(
     std::unique_ptr<base::Value> polled_data) {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   std::string json;
   if (polled_data)
@@ -511,7 +511,7 @@
 
 void FileNetLogObserver::UnboundedFileWriter::Flush(
     scoped_refptr<FileNetLogObserver::WriteQueue> write_queue) {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   EventQueue local_file_queue;
   write_queue->SwapQueue(&local_file_queue);
@@ -528,7 +528,7 @@
 }
 
 void FileNetLogObserver::UnboundedFileWriter::DeleteAllFiles() {
-  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
 
   // Reset |file_| to release the file handle so base::DeleteFile can
   // safely access it.
diff --git a/net/nqe/network_qualities_prefs_manager.cc b/net/nqe/network_qualities_prefs_manager.cc
index 82e22c47..94c7e15 100644
--- a/net/nqe/network_qualities_prefs_manager.cc
+++ b/net/nqe/network_qualities_prefs_manager.cc
@@ -78,7 +78,7 @@
 NetworkQualitiesPrefsManager::~NetworkQualitiesPrefsManager() {
   if (!network_task_runner_)
     return;
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
   if (network_quality_estimator_)
     network_quality_estimator_->RemoveNetworkQualitiesCacheObserver(this);
 }
@@ -99,34 +99,34 @@
 void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQuality(
     const nqe::internal::NetworkID& network_id,
     const nqe::internal::CachedNetworkQuality& cached_network_quality) {
-  DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
 
   // Notify |this| on the pref thread.
   pref_task_runner_->PostTask(
       FROM_HERE,
       base::Bind(&NetworkQualitiesPrefsManager::
-                     OnChangeInCachedNetworkQualityOnPrefThread,
+                     OnChangeInCachedNetworkQualityOnPrefSequence,
                  pref_weak_ptr_, network_id, cached_network_quality));
 }
 
-void NetworkQualitiesPrefsManager::ShutdownOnPrefThread() {
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+void NetworkQualitiesPrefsManager::ShutdownOnPrefSequence() {
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
   pref_weak_ptr_factory_.InvalidateWeakPtrs();
   pref_delegate_.reset();
 }
 
 void NetworkQualitiesPrefsManager::ClearPrefs() {
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
   prefs_->Clear();
   DCHECK_EQ(0u, prefs_->size());
   pref_delegate_->SetDictionaryValue(*prefs_);
 }
 
-void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQualityOnPrefThread(
+void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQualityOnPrefSequence(
     const nqe::internal::NetworkID& network_id,
     const nqe::internal::CachedNetworkQuality& cached_network_quality) {
   // The prefs can only be written on the pref thread.
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
   DCHECK_GE(kMaxCacheSize, prefs_->size());
 
   std::string network_id_string = network_id.ToString();
@@ -170,7 +170,7 @@
 }
 
 ParsedPrefs NetworkQualitiesPrefsManager::ForceReadPrefsForTesting() const {
-  DCHECK(pref_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(pref_task_runner_->RunsTasksInCurrentSequence());
   std::unique_ptr<base::DictionaryValue> value(
       pref_delegate_->GetDictionaryValue());
   return ConvertDictionaryValueToMap(value.get());
diff --git a/net/nqe/network_qualities_prefs_manager.h b/net/nqe/network_qualities_prefs_manager.h
index db315e3..549d9b5 100644
--- a/net/nqe/network_qualities_prefs_manager.h
+++ b/net/nqe/network_qualities_prefs_manager.h
@@ -42,7 +42,8 @@
 // propagates network quality pref changes from the network thread to the
 // provided pref delegate on the pref thread.
 //
-// ShutdownOnPrefThread must be called from the pref thread before destruction.
+// ShutdownOnPrefSequence must be called from the pref thread before
+// destruction.
 class NET_EXPORT NetworkQualitiesPrefsManager
     : public nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver {
  public:
@@ -70,7 +71,7 @@
       NetworkQualityEstimator* network_quality_estimator);
 
   // Prepare for shutdown. Must be called on the pref thread before destruction.
-  void ShutdownOnPrefThread();
+  void ShutdownOnPrefSequence();
 
   // Clear the network quality estimator prefs.
   void ClearPrefs();
@@ -82,7 +83,7 @@
  private:
   // Pref thread members:
   // Called on pref thread when there is a change in the cached network quality.
-  void OnChangeInCachedNetworkQualityOnPrefThread(
+  void OnChangeInCachedNetworkQualityOnPrefSequence(
       const nqe::internal::NetworkID& network_id,
       const nqe::internal::CachedNetworkQuality& cached_network_quality);
 
diff --git a/net/nqe/network_qualities_prefs_manager_unittest.cc b/net/nqe/network_qualities_prefs_manager_unittest.cc
index 34cb11b..1f6d3d4 100644
--- a/net/nqe/network_qualities_prefs_manager_unittest.cc
+++ b/net/nqe/network_qualities_prefs_manager_unittest.cc
@@ -107,7 +107,7 @@
   // Prefs should not be read again.
   EXPECT_EQ(1u, prefs_delegate_ptr->read_count());
 
-  manager.ShutdownOnPrefThread();
+  manager.ShutdownOnPrefSequence();
 }
 
 // Verify that the pref is not written if the network ID contains a period.
@@ -134,7 +134,7 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0u, prefs_delegate_ptr->write_count());
 
-  manager.ShutdownOnPrefThread();
+  manager.ShutdownOnPrefSequence();
 }
 
 TEST(NetworkQualitiesPrefManager, WriteAndReadWithMultipleNetworkIDs) {
@@ -194,7 +194,7 @@
   estimator.OnPrefsRead(read_prefs);
   histogram_tester.ExpectUniqueSample("NQE.Prefs.ReadSize", kMaxCacheSize, 1);
 
-  manager.ShutdownOnPrefThread();
+  manager.ShutdownOnPrefSequence();
 }
 
 // Verifies that the prefs are cleared correctly.
@@ -233,7 +233,7 @@
   // Verify that the observer was notified, and the updated network quality was
   // written to the prefs.
   EXPECT_EQ(1u, manager.ForceReadPrefsForTesting().size());
-  manager.ShutdownOnPrefThread();
+  manager.ShutdownOnPrefSequence();
 }
 
 }  // namespace
diff --git a/net/proxy/proxy_config_service_android.cc b/net/proxy/proxy_config_service_android.cc
index 1b3878d..3d1a40c 100644
--- a/net/proxy/proxy_config_service_android.cc
+++ b/net/proxy/proxy_config_service_android.cc
@@ -204,7 +204,7 @@
   }
 
   void SetupJNI() {
-    DCHECK(OnJNIThread());
+    DCHECK(InJNISequence());
     JNIEnv* env = AttachCurrentThread();
     if (java_proxy_change_listener_.is_null()) {
       java_proxy_change_listener_.Reset(Java_ProxyChangeListener_create(env));
@@ -215,60 +215,58 @@
   }
 
   void FetchInitialConfig() {
-    DCHECK(OnJNIThread());
+    DCHECK(InJNISequence());
     ProxyConfig proxy_config;
     GetLatestProxyConfigInternal(get_property_callback_, &proxy_config);
     network_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(&Delegate::SetNewConfigOnNetworkThread, this, proxy_config));
+        FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this,
+                              proxy_config));
   }
 
   void Shutdown() {
-    if (OnJNIThread()) {
-      ShutdownOnJNIThread();
+    if (InJNISequence()) {
+      ShutdownInJNISequence();
     } else {
       jni_task_runner_->PostTask(
-          FROM_HERE,
-          base::Bind(&Delegate::ShutdownOnJNIThread, this));
+          FROM_HERE, base::Bind(&Delegate::ShutdownInJNISequence, this));
     }
   }
 
-  // Called only on the network thread.
+  // Called only in the network sequence.
   void AddObserver(Observer* observer) {
-    DCHECK(OnNetworkThread());
+    DCHECK(InNetworkSequence());
     observers_.AddObserver(observer);
   }
 
   void RemoveObserver(Observer* observer) {
-    DCHECK(OnNetworkThread());
+    DCHECK(InNetworkSequence());
     observers_.RemoveObserver(observer);
   }
 
   ConfigAvailability GetLatestProxyConfig(ProxyConfig* config) {
-    DCHECK(OnNetworkThread());
+    DCHECK(InNetworkSequence());
     if (!config)
       return ProxyConfigService::CONFIG_UNSET;
     *config = proxy_config_;
     return ProxyConfigService::CONFIG_VALID;
   }
 
-  // Called on the JNI thread.
+  // Called in the JNI sequence.
   void ProxySettingsChanged() {
-    DCHECK(OnJNIThread());
+    DCHECK(InJNISequence());
     ProxyConfig proxy_config;
     GetLatestProxyConfigInternal(get_property_callback_, &proxy_config);
     network_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(
-            &Delegate::SetNewConfigOnNetworkThread, this, proxy_config));
+        FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this,
+                              proxy_config));
   }
 
-  // Called on the JNI thread.
+  // Called in the JNI sequence.
   void ProxySettingsChangedTo(const std::string& host,
                               int port,
                               const std::string& pac_url,
                               const std::vector<std::string>& exclusion_list) {
-    DCHECK(OnJNIThread());
+    DCHECK(InJNISequence());
     ProxyConfig proxy_config;
     if (exclude_pac_url_) {
       CreateStaticProxyConfig(host, port, "", exclusion_list, &proxy_config);
@@ -277,9 +275,8 @@
           &proxy_config);
     }
     network_task_runner_->PostTask(
-        FROM_HERE,
-        base::Bind(
-            &Delegate::SetNewConfigOnNetworkThread, this, proxy_config));
+        FROM_HERE, base::Bind(&Delegate::SetNewConfigInNetworkSequence, this,
+                              proxy_config));
   }
 
   void set_exclude_pac_url(bool enabled) {
@@ -322,16 +319,16 @@
 
   virtual ~Delegate() {}
 
-  void ShutdownOnJNIThread() {
+  void ShutdownInJNISequence() {
     if (java_proxy_change_listener_.is_null())
       return;
     JNIEnv* env = AttachCurrentThread();
     Java_ProxyChangeListener_stop(env, java_proxy_change_listener_);
   }
 
-  // Called on the network thread.
-  void SetNewConfigOnNetworkThread(const ProxyConfig& proxy_config) {
-    DCHECK(OnNetworkThread());
+  // Called on the network sequence.
+  void SetNewConfigInNetworkSequence(const ProxyConfig& proxy_config) {
+    DCHECK(InNetworkSequence());
     proxy_config_ = proxy_config;
     for (auto& observer : observers_) {
       observer.OnProxyConfigChanged(proxy_config,
@@ -339,12 +336,12 @@
     }
   }
 
-  bool OnJNIThread() const {
-    return jni_task_runner_->RunsTasksOnCurrentThread();
+  bool InJNISequence() const {
+    return jni_task_runner_->RunsTasksInCurrentSequence();
   }
 
-  bool OnNetworkThread() const {
-    return network_task_runner_->RunsTasksOnCurrentThread();
+  bool InNetworkSequence() const {
+    return network_task_runner_->RunsTasksInCurrentSequence();
   }
 
   ScopedJavaGlobalRef<jobject> java_proxy_change_listener_;
diff --git a/net/quic/chromium/bidirectional_stream_quic_impl.cc b/net/quic/chromium/bidirectional_stream_quic_impl.cc
index c3864fc..5d2ae044 100644
--- a/net/quic/chromium/bidirectional_stream_quic_impl.cc
+++ b/net/quic/chromium/bidirectional_stream_quic_impl.cc
@@ -53,15 +53,10 @@
     std::unique_ptr<base::Timer> /* timer */) {
   DCHECK(!stream_);
   CHECK(delegate);
+  DLOG_IF(WARNING, !session_->IsConnected())
+      << "Trying to start request headers after session has been closed.";
 
   send_request_headers_automatically_ = send_request_headers_automatically;
-  if (!session_->IsConnected()) {
-    NotifyError(session_->IsCryptoHandshakeConfirmed()
-                    ? ERR_QUIC_PROTOCOL_ERROR
-                    : ERR_QUIC_HANDSHAKE_FAILED);
-    return;
-  }
-
   delegate_ = delegate;
   request_info_ = request_info;
 
@@ -72,11 +67,17 @@
   if (rv == ERR_IO_PENDING)
     return;
 
-  if (rv == OK) {
-    OnStreamReady(rv);
-  } else if (!session_->IsCryptoHandshakeConfirmed()) {
-    NotifyError(ERR_QUIC_HANDSHAKE_FAILED);
+  if (rv != OK) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::Bind(&BidirectionalStreamQuicImpl::NotifyError,
+                              weak_factory_.GetWeakPtr(),
+                              session_->IsCryptoHandshakeConfirmed()
+                                  ? rv
+                                  : ERR_QUIC_HANDSHAKE_FAILED));
+    return;
   }
+
+  OnStreamReady(rv);
 }
 
 void BidirectionalStreamQuicImpl::SendRequestHeaders() {
diff --git a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
index 5b6ecded..94d6009 100644
--- a/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/chromium/bidirectional_stream_quic_impl_unittest.cc
@@ -60,6 +60,15 @@
 // Size of the buffer to be allocated for each read.
 const size_t kReadBufferSize = 4096;
 
+enum DelegateMethod {
+  kOnStreamReady,
+  kOnHeadersReceived,
+  kOnTrailersReceived,
+  kOnDataRead,
+  kOnDataSent,
+  kOnFailed
+};
+
 class TestDelegateBase : public BidirectionalStreamImpl::Delegate {
  public:
   TestDelegateBase(IOBuffer* read_buf, int read_buf_len)
@@ -178,9 +187,27 @@
   }
 
   // Waits until next Delegate callback.
-  void WaitUntilNextCallback() {
+  void WaitUntilNextCallback(DelegateMethod method) {
+    ASSERT_FALSE(on_failed_called_);
+    bool is_ready = is_ready_;
+    bool headers_received = !response_headers_.empty();
+    bool trailers_received = trailers_received_;
+    int on_data_read_count = on_data_read_count_;
+    int on_data_sent_count = on_data_sent_count_;
+
     loop_->Run();
     loop_.reset(new base::RunLoop);
+
+    EXPECT_EQ(method == kOnFailed, on_failed_called_);
+    EXPECT_EQ(is_ready || (method == kOnStreamReady), is_ready_);
+    EXPECT_EQ(headers_received || (method == kOnHeadersReceived),
+              !response_headers_.empty());
+    EXPECT_EQ(trailers_received || (method == kOnTrailersReceived),
+              trailers_received_);
+    EXPECT_EQ(on_data_read_count + (method == kOnDataRead ? 1 : 0),
+              on_data_read_count_);
+    EXPECT_EQ(on_data_sent_count + (method == kOnDataSent ? 1 : 0),
+              on_data_sent_count_);
   }
 
   // Calls ReadData on the |stream_| and updates |data_received_|.
@@ -766,7 +793,7 @@
       new TestDelegateBase(read_buffer.get(), kReadBufferSize));
   delegate->set_trailers_expected(true);
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
   ConfirmHandshake();
 
   // Server acks the request.
@@ -781,7 +808,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   LoadTimingInfo load_timing_info;
   EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
   ExpectLoadTimingValid(load_timing_info, /*session_reused=*/false);
@@ -807,7 +834,7 @@
   ProcessPacket(ConstructResponseTrailersPacket(
       4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnTrailersReceived
+  delegate->WaitUntilNextCallback(kOnTrailersReceived);
   EXPECT_THAT(cb2.WaitForResult(), IsOk());
   trailers.erase(kFinalOffsetHeaderKey);
   EXPECT_EQ(trailers, delegate->trailers());
@@ -874,8 +901,8 @@
       new TestDelegateBase(read_buffer2.get(), kReadBufferSize));
   delegate2->Start(&request, net_log().bound(), session()->CreateHandle());
 
-  delegate->WaitUntilNextCallback();   // OnStreamReady
-  delegate2->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
+  delegate2->WaitUntilNextCallback(kOnStreamReady);
 
   ConfirmHandshake();
   // Server acks the request.
@@ -891,8 +918,8 @@
       3, GetNthClientInitiatedStreamId(1), kFin,
       ConstructResponseHeaders("200"), nullptr, &offset));
 
-  delegate->WaitUntilNextCallback();   // OnHeadersReceived
-  delegate2->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
+  delegate2->WaitUntilNextCallback(kOnHeadersReceived);
 
   LoadTimingInfo load_timing_info;
   EXPECT_TRUE(delegate->GetLoadTimingInfo(&load_timing_info));
@@ -947,7 +974,7 @@
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   EXPECT_FALSE(delegate->is_ready());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
   EXPECT_TRUE(delegate->is_ready());
 
   // Sends request headers separately, which causes them to be sent in a
@@ -959,7 +986,7 @@
 
   std::vector<int> lengths = {buf1->size(), buf2->size()};
   delegate->SendvData({buf1, buf2}, lengths, !kFin);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -972,7 +999,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
   int rv = delegate->ReadData(cb.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -991,7 +1018,7 @@
 
   delegate->SendvData({buf3, buf4, buf5},
                       {buf3->size(), buf4->size(), buf5->size()}, kFin);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   size_t spdy_trailers_frame_length;
   SpdyHeaderBlock trailers;
@@ -1001,7 +1028,7 @@
   ProcessPacket(ConstructResponseTrailersPacket(
       4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnTrailersReceived
+  delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(kFinalOffsetHeaderKey);
   EXPECT_EQ(trailers, delegate->trailers());
   EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());
@@ -1053,13 +1080,13 @@
   delegate->DoNotSendRequestHeadersAutomatically();
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Send a Data packet.
   scoped_refptr<StringIOBuffer> buf1(new StringIOBuffer(kBody1));
 
   delegate->SendData(buf1, buf1->size(), false);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1072,7 +1099,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
   int rv = delegate->ReadData(cb.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -1088,7 +1115,7 @@
   scoped_refptr<StringIOBuffer> buf2(new StringIOBuffer(kBody2));
 
   delegate->SendData(buf2, buf2->size(), true);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   size_t spdy_trailers_frame_length;
   SpdyHeaderBlock trailers;
@@ -1098,7 +1125,7 @@
   ProcessPacket(ConstructResponseTrailersPacket(
       4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnTrailersReceived
+  delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(kFinalOffsetHeaderKey);
   EXPECT_EQ(trailers, delegate->trailers());
   EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());
@@ -1152,7 +1179,7 @@
   delegate->DoNotSendRequestHeadersAutomatically();
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Send a Data packet.
   scoped_refptr<StringIOBuffer> buf1(new StringIOBuffer(kBody1));
@@ -1160,7 +1187,7 @@
 
   std::vector<int> lengths = {buf1->size(), buf2->size()};
   delegate->SendvData({buf1, buf2}, lengths, !kFin);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1173,7 +1200,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
   int rv = delegate->ReadData(cb.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -1192,7 +1219,7 @@
 
   delegate->SendvData({buf3, buf4, buf5},
                       {buf3->size(), buf4->size(), buf5->size()}, kFin);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   size_t spdy_trailers_frame_length;
   SpdyHeaderBlock trailers;
@@ -1202,7 +1229,7 @@
   ProcessPacket(ConstructResponseTrailersPacket(
       4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnTrailersReceived
+  delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(kFinalOffsetHeaderKey);
   EXPECT_EQ(trailers, delegate->trailers());
   EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());
@@ -1246,13 +1273,13 @@
       new TestDelegateBase(read_buffer.get(), kReadBufferSize));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Send a DATA frame.
   scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData));
 
   delegate->SendData(buf, buf->size(), true);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1265,7 +1292,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
   int rv = delegate->ReadData(cb.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -1285,7 +1312,7 @@
   ProcessPacket(ConstructResponseTrailersPacket(
       4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnTrailersReceived
+  delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(kFinalOffsetHeaderKey);
   EXPECT_EQ(trailers, delegate->trailers());
   EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());
@@ -1323,13 +1350,13 @@
   std::unique_ptr<TestDelegateBase> delegate(
       new TestDelegateBase(read_buffer.get(), kReadBufferSize));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Send a DATA frame.
   scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData));
 
   delegate->SendData(buf, buf->size(), true);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1342,7 +1369,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
   int rv = delegate->ReadData(cb.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
@@ -1362,7 +1389,7 @@
   ProcessPacket(ConstructResponseTrailersPacket(
       4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnTrailersReceived
+  delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(kFinalOffsetHeaderKey);
   EXPECT_EQ(trailers, delegate->trailers());
   EXPECT_THAT(delegate->ReadData(cb.callback()), IsOk());
@@ -1405,7 +1432,7 @@
       new TestDelegateBase(read_buffer.get(), kReadBufferSize));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1417,14 +1444,14 @@
       ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                      &spdy_response_headers_frame_length, 0));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
 
   // Client sends a data packet.
   scoped_refptr<StringIOBuffer> buf(new StringIOBuffer(kUploadData));
 
   delegate->SendData(buf, buf->size(), false);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   TestCompletionCallback cb;
   int rv = delegate->ReadData(cb.callback());
@@ -1440,7 +1467,7 @@
 
   // Client sends a data packet.
   delegate->SendData(buf, buf->size(), true);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   TestCompletionCallback cb2;
   rv = delegate->ReadData(cb2.callback());
@@ -1487,13 +1514,14 @@
   std::unique_ptr<TestDelegateBase> delegate(
       new TestDelegateBase(read_buffer.get(), kReadBufferSize));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
   ConfirmHandshake();
 
   // Server sends a Rst.
   ProcessPacket(ConstructServerRstStreamPacket(1));
 
-  delegate->WaitUntilNextCallback();  // OnFailed
+  EXPECT_TRUE(delegate->on_failed_called());
+
   TestCompletionCallback cb;
   EXPECT_THAT(delegate->ReadData(cb.callback()),
               IsError(ERR_QUIC_PROTOCOL_ERROR));
@@ -1531,7 +1559,7 @@
   std::unique_ptr<TestDelegateBase> delegate(
       new TestDelegateBase(read_buffer.get(), kReadBufferSize));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
   ConfirmHandshake();
 
   // Server acks the request.
@@ -1546,7 +1574,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
 
   TestCompletionCallback cb;
@@ -1556,7 +1584,7 @@
   // Server sends a Rst.
   ProcessPacket(ConstructServerRstStreamPacket(3));
 
-  delegate->WaitUntilNextCallback();  // OnFailed
+  EXPECT_TRUE(delegate->on_failed_called());
 
   EXPECT_THAT(delegate->ReadData(cb.callback()),
               IsError(ERR_QUIC_PROTOCOL_ERROR));
@@ -1590,7 +1618,7 @@
       new TestDelegateBase(read_buffer.get(), kReadBufferSize));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1604,13 +1632,12 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   TestCompletionCallback cb;
   int rv = delegate->ReadData(cb.callback());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   session()->connection()->CloseConnection(
       QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
-  delegate->WaitUntilNextCallback();  // OnFailed
   EXPECT_TRUE(delegate->on_failed_called());
 
   // Try to send data after OnFailed(), should not get called back.
@@ -1629,6 +1656,51 @@
             delegate->GetTotalReceivedBytes());
 }
 
+TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeStartConfirmed) {
+  SetRequest("POST", "/", DEFAULT_PRIORITY);
+  Initialize();
+
+  BidirectionalStreamRequestInfo request;
+  request.method = "POST";
+  request.url = GURL("http://www.google.com/");
+  request.end_stream_on_headers = false;
+  request.priority = DEFAULT_PRIORITY;
+
+  ConfirmHandshake();
+  session()->connection()->CloseConnection(
+      QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
+
+  scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+  std::unique_ptr<TestDelegateBase> delegate(
+      new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+  delegate->Start(&request, net_log().bound(), session()->CreateHandle());
+  delegate->WaitUntilNextCallback(kOnFailed);
+  EXPECT_TRUE(delegate->on_failed_called());
+  EXPECT_THAT(delegate->error(), IsError(ERR_CONNECTION_CLOSED));
+}
+
+TEST_P(BidirectionalStreamQuicImplTest, SessionClosedBeforeStartNotConfirmed) {
+  SetRequest("POST", "/", DEFAULT_PRIORITY);
+  Initialize();
+
+  session()->connection()->CloseConnection(
+      QUIC_NO_ERROR, "test", ConnectionCloseBehavior::SILENT_CLOSE);
+
+  BidirectionalStreamRequestInfo request;
+  request.method = "POST";
+  request.url = GURL("http://www.google.com/");
+  request.end_stream_on_headers = false;
+  request.priority = DEFAULT_PRIORITY;
+
+  scoped_refptr<IOBuffer> read_buffer(new IOBuffer(kReadBufferSize));
+  std::unique_ptr<TestDelegateBase> delegate(
+      new TestDelegateBase(read_buffer.get(), kReadBufferSize));
+  delegate->Start(&request, net_log().bound(), session()->CreateHandle());
+  delegate->WaitUntilNextCallback(kOnFailed);
+  EXPECT_TRUE(delegate->on_failed_called());
+  EXPECT_THAT(delegate->error(), IsError(ERR_QUIC_HANDSHAKE_FAILED));
+}
+
 TEST_P(BidirectionalStreamQuicImplTest, SessionCloseDuringOnStreamReady) {
   SetRequest("POST", "/", DEFAULT_PRIORITY);
   QuicStreamOffset header_stream_offset = 0;
@@ -1648,7 +1720,7 @@
       read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_FAILED));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnFailed);
 
   EXPECT_EQ(0, delegate->on_data_read_count());
   EXPECT_EQ(0, delegate->on_data_sent_count());
@@ -1678,7 +1750,7 @@
                                DeleteStreamDelegate::ON_STREAM_READY));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   EXPECT_EQ(0, delegate->on_data_read_count());
   EXPECT_EQ(0, delegate->on_data_sent_count());
@@ -1707,7 +1779,7 @@
       new TestDelegateBase(read_buffer.get(), kReadBufferSize));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1719,7 +1791,7 @@
       ConstructResponseHeadersPacket(2, !kFin, std::move(response_headers),
                                      &spdy_response_headers_frame_length, 0));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
 
   // Cancel the stream after ReadData returns ERR_IO_PENDING.
@@ -1762,7 +1834,7 @@
                                DeleteStreamDelegate::ON_HEADERS_RECEIVED));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1775,7 +1847,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, nullptr));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
 
   base::RunLoop().RunUntilIdle();
@@ -1808,7 +1880,7 @@
       read_buffer.get(), kReadBufferSize, DeleteStreamDelegate::ON_DATA_READ));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1821,7 +1893,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, nullptr));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
 
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
 
@@ -1867,12 +1939,12 @@
 
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
   ConfirmHandshake();
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Send a Data packet with fin set.
   scoped_refptr<StringIOBuffer> buf1(new StringIOBuffer(kBody));
   delegate->SendData(buf1, buf1->size(), /*fin*/ true);
-  delegate->WaitUntilNextCallback();  // OnDataSent
+  delegate->WaitUntilNextCallback(kOnDataSent);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1885,7 +1957,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, nullptr));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
 
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
 
@@ -1928,7 +2000,7 @@
       new DeleteStreamDelegate(read_buffer.get(), kReadBufferSize,
                                DeleteStreamDelegate::ON_TRAILERS_RECEIVED));
   delegate->Start(&request, net_log().bound(), session()->CreateHandle());
-  delegate->WaitUntilNextCallback();  // OnStreamReady
+  delegate->WaitUntilNextCallback(kOnStreamReady);
 
   // Server acks the request.
   ProcessPacket(ConstructServerAckPacket(1, 0, 0, 0));
@@ -1942,7 +2014,7 @@
       2, !kFin, std::move(response_headers),
       &spdy_response_headers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnHeadersReceived
+  delegate->WaitUntilNextCallback(kOnHeadersReceived);
 
   EXPECT_EQ("200", delegate->response_headers().find(":status")->second);
 
@@ -1965,7 +2037,7 @@
   ProcessPacket(ConstructResponseTrailersPacket(
       4, kFin, trailers.Clone(), &spdy_trailers_frame_length, &offset));
 
-  delegate->WaitUntilNextCallback();  // OnTrailersReceived
+  delegate->WaitUntilNextCallback(kOnTrailersReceived);
   trailers.erase(kFinalOffsetHeaderKey);
   EXPECT_EQ(trailers, delegate->trailers());
 
diff --git a/net/ssl/channel_id_service.cc b/net/ssl/channel_id_service.cc
index 2be6a6b..8aa3732 100644
--- a/net/ssl/channel_id_service.cc
+++ b/net/ssl/channel_id_service.cc
@@ -112,7 +112,7 @@
 
   // Starts the worker asynchronously.
   void Start(const scoped_refptr<base::TaskRunner>& task_runner) {
-    DCHECK(origin_task_runner_->RunsTasksOnCurrentThread());
+    DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
 
     auto callback = base::Bind(&ChannelIDServiceWorker::Run, base::Owned(this));
 
diff --git a/net/url_request/test_url_request_interceptor.cc b/net/url_request/test_url_request_interceptor.cc
index 321bd7d..063a4b5 100644
--- a/net/url_request/test_url_request_interceptor.cc
+++ b/net/url_request/test_url_request_interceptor.cc
@@ -77,7 +77,7 @@
   void SetResponse(const GURL& url,
                    const base::FilePath& path,
                    bool ignore_query) {
-    DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+    DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
     if (ignore_query) {
       ignore_query_responses_[url] = path;
     } else {
@@ -98,7 +98,7 @@
   URLRequestJob* MaybeInterceptRequest(
       URLRequest* request,
       NetworkDelegate* network_delegate) const override {
-    DCHECK(network_task_runner_->RunsTasksOnCurrentThread());
+    DCHECK(network_task_runner_->RunsTasksInCurrentSequence());
     if (request->url().scheme() != scheme_ ||
         request->url().host() != hostname_) {
       return NULL;
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc
index a4727c7c..08b1b91 100644
--- a/net/url_request/url_fetcher_core.cc
+++ b/net/url_request/url_fetcher_core.cc
@@ -127,13 +127,13 @@
 
 void URLFetcherCore::Stop() {
   if (delegate_task_runner_)  // May be NULL in tests.
-    DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+    DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
 
   delegate_ = NULL;
   fetcher_ = NULL;
   if (!network_task_runner_.get())
     return;
-  if (network_task_runner_->RunsTasksOnCurrentThread()) {
+  if (network_task_runner_->RunsTasksInCurrentSequence()) {
     CancelURLRequest(ERR_ABORTED);
   } else {
     network_task_runner_->PostTask(
@@ -291,21 +291,21 @@
 void URLFetcherCore::SaveResponseToFileAtPath(
     const base::FilePath& file_path,
     scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
-  DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
   SaveResponseWithWriter(std::unique_ptr<URLFetcherResponseWriter>(
       new URLFetcherFileWriter(file_task_runner, file_path)));
 }
 
 void URLFetcherCore::SaveResponseToTemporaryFile(
     scoped_refptr<base::SequencedTaskRunner> file_task_runner) {
-  DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
   SaveResponseWithWriter(std::unique_ptr<URLFetcherResponseWriter>(
       new URLFetcherFileWriter(file_task_runner, base::FilePath())));
 }
 
 void URLFetcherCore::SaveResponseWithWriter(
     std::unique_ptr<URLFetcherResponseWriter> response_writer) {
-  DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
   response_writer_ = std::move(response_writer);
 }
 
@@ -353,7 +353,7 @@
 }
 
 void URLFetcherCore::ReceivedContentWasMalformed() {
-  DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
   if (network_task_runner_.get()) {
     network_task_runner_->PostTask(
         FROM_HERE, base::Bind(&URLFetcherCore::NotifyMalformedContent, this));
@@ -375,7 +375,7 @@
 
 bool URLFetcherCore::GetResponseAsFilePath(bool take_ownership,
                                            base::FilePath* out_response_path) {
-  DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
 
   URLFetcherFileWriter* file_writer =
       response_writer_ ? response_writer_->AsFileWriter() : NULL;
@@ -715,7 +715,7 @@
 
 void URLFetcherCore::OnCompletedURLRequest(
     base::TimeDelta backoff_delay) {
-  DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
 
   // Save the status and backoff_delay so that delegates can read it.
   if (delegate_) {
@@ -725,7 +725,7 @@
 }
 
 void URLFetcherCore::InformDelegateFetchIsComplete() {
-  DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
   if (delegate_)
     delegate_->OnURLFetchComplete(fetcher_);
 }
@@ -926,7 +926,7 @@
 void URLFetcherCore::InformDelegateUploadProgressInDelegateSequence(
     int64_t current,
     int64_t total) {
-  DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
   if (delegate_)
     delegate_->OnURLFetchUploadProgress(fetcher_, current, total);
 }
@@ -951,7 +951,7 @@
     int64_t current,
     int64_t total,
     int64_t current_network_bytes) {
-  DCHECK(delegate_task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(delegate_task_runner_->RunsTasksInCurrentSequence());
   if (delegate_)
     delegate_->OnURLFetchDownloadProgress(fetcher_, current, total,
                                           current_network_bytes);
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc
index 2cb0c5e..782edaf 100644
--- a/net/url_request/url_fetcher_impl_unittest.cc
+++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -252,7 +252,7 @@
                          double jitter_factor,
                          int maximum_backoff_ms,
                          bool reserve_sending_time_for_next_request) {
-    if (!network_task_runner_->RunsTasksOnCurrentThread()) {
+    if (!network_task_runner_->RunsTasksInCurrentSequence()) {
       network_task_runner_->PostTask(
           FROM_HERE,
           base::Bind(&FetcherTestURLRequestContextGetter::AddThrottlerEntry,
@@ -277,7 +277,7 @@
   // Tells the getter to act as if the URLRequestContext is about to be shut
   // down.
   void Shutdown() {
-    if (!network_task_runner_->RunsTasksOnCurrentThread()) {
+    if (!network_task_runner_->RunsTasksInCurrentSequence()) {
       network_task_runner_->PostTask(
           FROM_HERE,
           base::Bind(&FetcherTestURLRequestContextGetter::Shutdown, this));
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 2a42e6c..eccd308 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -839,6 +839,45 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_blink_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_blink_unittests"
+      },
+      {
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -2373,6 +2412,47 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_blink_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "android_devices": "4",
+              "device_os": "LMY48I",
+              "device_type": "hammerhead"
+            }
+          ],
+          "expiration": 10800,
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_blink_unittests"
+      },
+      {
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -3052,6 +3132,9 @@
         "test": "ipc_tests"
       },
       {
+        "test": "media_blink_unittests"
+      },
+      {
         "test": "media_unittests"
       },
       {
@@ -4275,6 +4358,45 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "media_blink_unittests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_type": "bullhead"
+            }
+          ],
+          "hard_timeout": 960,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "media_blink_unittests"
+      },
+      {
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "media_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -4840,6 +4962,9 @@
         "test": "ipc_tests"
       },
       {
+        "test": "media_blink_unittests"
+      },
+      {
         "test": "media_unittests"
       },
       {
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2 b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
index a25a05a0..c1a47b6 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-slimming-paint-v2
@@ -110,7 +110,6 @@
 Bug(none) paint/invalidation/clip-flex-text.html [ Failure ]
 Bug(none) virtual/new-remote-playback-pipeline/media/controls/video-controls-with-cast-rendering.html [ Failure ]
 Bug(none) virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-dark-rendering.html [ Failure ]
-Bug(none) paint/invalidation/compositing/newly-composited-repaint-rect.html [ Failure ]
 Bug(none) virtual/new-remote-playback-pipeline/media/controls/video-overlay-cast-light-rendering.html [ Failure ]
 Bug(none) svg/foreignObject/overflow-clip-in-hidden-container-crash.html [ Crash ]
 Bug(none) images/rendering-broken-0px-images.html [ Failure ]
@@ -1020,48 +1019,28 @@
 Bug(none) paint/invalidation/absolute-position-moved.html [ Failure ]
 Bug(none) paint/invalidation/abspos-shift-image-incorrect-repaint.html [ Failure ]
 Bug(none) paint/invalidation/add-table-overpaint.html [ Failure ]
-Bug(none) paint/invalidation/align-content-change.html [ Failure ]
-Bug(none) paint/invalidation/align-content-distribution-change-grid.html [ Failure ]
 Bug(none) paint/invalidation/align-items-change.html [ Failure ]
-Bug(none) paint/invalidation/align-self-change-grid.html [ Failure ]
 Bug(none) paint/invalidation/align-self-change.html [ Failure ]
-Bug(none) paint/invalidation/animated-gif-background.html [ Failure ]
 Bug(none) paint/invalidation/animated-gif-transformed-offscreen.html [ Failure ]
-Bug(none) paint/invalidation/animated-gif.html [ Failure ]
-Bug(none) paint/invalidation/animated-png-background.html [ Failure ]
-Bug(none) paint/invalidation/animated-png.html [ Failure ]
-Bug(none) paint/invalidation/animated-webp-background.html [ Failure ]
-Bug(none) paint/invalidation/animated-webp.html [ Failure ]
 Bug(none) paint/invalidation/background-currentColor-repaint.html [ Failure ]
-Bug(none) paint/invalidation/background-generated.html [ Failure ]
 Bug(none) paint/invalidation/background-image-paint-invalidation-large-abspos-div.html [ Failure ]
 Bug(none) paint/invalidation/background-image-paint-invalidation.html [ Failure ]
 Bug(none) paint/invalidation/background-misaligned.html [ Failure ]
 Bug(none) paint/invalidation/background-resize-height.html [ Failure ]
-Bug(none) paint/invalidation/background-shorthand-with-gradient-and-height-changes.html [ Failure ]
-Bug(none) paint/invalidation/background-size-auto-with-gradient-and-height-changes.html [ Failure ]
 Bug(none) paint/invalidation/backgroundSizeRepaint.html [ Failure ]
 Bug(none) paint/invalidation/block-layout-inline-children-float-positioned.html [ Failure ]
 Bug(none) paint/invalidation/block-layout-inline-children-replaced.html [ Failure ]
 Bug(none) paint/invalidation/block-no-inflow-children.html [ Failure ]
 Bug(none) paint/invalidation/block-shift-repaint.html [ Failure ]
 Bug(none) paint/invalidation/body-background-image.html [ Failure ]
-Bug(none) paint/invalidation/border-current-color.html [ Failure ]
 Bug(none) paint/invalidation/border-image-outset-add-repaint.html [ Failure ]
 Bug(none) paint/invalidation/border-image-outset-change-repaint.html [ Failure ]
 Bug(none) paint/invalidation/border-outline-0.html [ Failure ]
 Bug(none) paint/invalidation/border-radius-repaint-2.html [ Failure ]
 Bug(none) paint/invalidation/border-radius-repaint.html [ Failure ]
-Bug(none) paint/invalidation/border-radius-with-outline.html [ Failure ]
-Bug(none) paint/invalidation/border-radius-without-border.html [ Failure ]
 Bug(none) paint/invalidation/border-repaint-glitch.html [ Failure ]
 Bug(none) paint/invalidation/box-inline-resize.html [ Failure ]
-Bug(none) paint/invalidation/box-shadow-add-repaint.html [ Failure ]
-Bug(none) paint/invalidation/box-shadow-change-repaint.html [ Failure ]
-Bug(none) paint/invalidation/box-shadow-dynamic.html [ Failure ]
 Bug(none) paint/invalidation/box-shadow-inset-repaint.html [ Failure ]
-Bug(none) paint/invalidation/box-sizing-border-keeping-size.html [ Failure ]
-Bug(none) paint/invalidation/box-sizing-padding-keeping-size.html [ Failure ]
 Bug(none) paint/invalidation/box-sizing.html [ Failure ]
 Bug(none) paint/invalidation/bugzilla-3509.html [ Failure ]
 Bug(none) paint/invalidation/bugzilla-5699.html [ Failure ]
@@ -1069,11 +1048,8 @@
 Bug(none) paint/invalidation/bugzilla-6388.html [ Failure ]
 Bug(none) paint/invalidation/bugzilla-6473.html [ Failure ]
 Bug(none) paint/invalidation/bugzilla-7235.html [ Failure ]
-Bug(none) paint/invalidation/button-checkbox-click-method-repaint.html [ Failure ]
-Bug(none) paint/invalidation/button-spurious-layout-hint.html [ Failure ]
 Bug(none) paint/invalidation/canvas-composite-repaint-by-all-imagesource.html [ Failure ]
 Bug(none) paint/invalidation/canvas-putImageData.html [ Failure ]
-Bug(none) paint/invalidation/canvas-resize-no-full-invalidation.html [ Failure ]
 Bug(none) paint/invalidation/canvas-resize.html [ Failure ]
 Bug(none) paint/invalidation/caret-invalidation-in-overflow-scroll.html [ Failure ]
 Bug(none) paint/invalidation/caret-outside-block.html [ Failure ]
@@ -1084,7 +1060,6 @@
 Bug(none) paint/invalidation/change-transform.html [ Failure ]
 Bug(none) paint/invalidation/child-of-sub-pixel-offset-composited-layer.html [ Failure ]
 Bug(none) paint/invalidation/clip-path-constant-repaint.html [ Failure ]
-Bug(none) paint/invalidation/clip-unclip-and-change.html [ Failure ]
 Bug(none) paint/invalidation/clip-with-layout-delta.html [ Failure ]
 Bug(none) paint/invalidation/clipped-overflow-visible-subtree.html [ Failure ]
 Bug(none) paint/invalidation/clipped-relative.html [ Failure ]
@@ -1161,7 +1136,6 @@
 Bug(none) paint/invalidation/destroy-overlay-scrollbar.html [ Failure ]
 Bug(none) paint/invalidation/destroy-scrollbar.html [ Failure ]
 Bug(none) paint/invalidation/details-open-repaint.html [ Failure ]
-Bug(none) paint/invalidation/do-not-paint-below-image-baseline.html [ Failure ]
 Bug(none) paint/invalidation/document-flipped-blocks-writing-mode-scroll.html [ Failure ]
 Bug(none) paint/invalidation/dont-invalidate-root-layer-when-composited-layer-becomes-visible.html [ Failure ]
 Bug(none) paint/invalidation/dynamic-table-vertical-alignment-change.html [ Failure ]
@@ -1212,16 +1186,13 @@
 Bug(none) paint/invalidation/fixed-under-composited-fixed-scrolled.html [ Failure ]
 Bug(none) paint/invalidation/fixed-with-border-under-composited-absolute-scrolled.html [ Failure ]
 Bug(none) paint/invalidation/fixed.html [ Failure ]
-Bug(none) paint/invalidation/flexbox/repaint-during-resize-no-flex.html [ Failure ]
 Bug(none) paint/invalidation/flexbox/repaint-on-layout.html [ Failure ]
 Bug(none) paint/invalidation/flexbox/repaint-opacity-change.html [ Failure ]
 Bug(none) paint/invalidation/flexbox/repaint-rtl-column.html [ Failure ]
 Bug(none) paint/invalidation/flexbox/repaint.html [ Failure ]
 Bug(none) paint/invalidation/flexbox/scrollbars-changed.html [ Failure ]
 Bug(none) paint/invalidation/flipped-blocks-writing-mode-scroll.html [ Failure ]
-Bug(none) paint/invalidation/float-in-new-block-with-layout-delta.html [ Failure ]
 Bug(none) paint/invalidation/float-move-during-layout.html [ Failure ]
-Bug(none) paint/invalidation/float-new-in-block.html [ Failure ]
 Bug(none) paint/invalidation/float-overflow-right.html [ Failure ]
 Bug(none) paint/invalidation/float-overflow.html [ Failure ]
 Bug(none) paint/invalidation/focus-continuations.html [ Failure ]
@@ -1229,13 +1200,10 @@
 Bug(none) paint/invalidation/focus-ring-on-child-move.html [ Failure ]
 Bug(none) paint/invalidation/focus-ring-on-inline-continuation-move.html [ Failure ]
 Bug(none) paint/invalidation/forms/button-reset-focus-by-mouse-then-keydown.html [ Failure ]
-Bug(none) paint/invalidation/forms/checkbox-focus-by-mouse-then-keydown.html [ Failure ]
-Bug(none) paint/invalidation/forms/radio-focus-by-mouse-then-keydown.html [ Failure ]
 Bug(none) paint/invalidation/forms/range-focus-by-mouse-then-keydown.html [ Failure ]
 Bug(none) paint/invalidation/forms/submit-focus-by-mouse-then-keydown.html [ Failure ]
 Bug(none) paint/invalidation/full-viewport-repaint-for-background-attachment-fixed.html [ Failure ]
 Bug(none) paint/invalidation/gradients-em-stops-repaint.html [ Failure ]
-Bug(none) paint/invalidation/hover-pseudo-borders-whitespace.html [ Failure ]
 Bug(none) paint/invalidation/hover-pseudo-borders.html [ Failure ]
 Bug(none) paint/invalidation/iframe-display-block-to-display-none.html [ Failure ]
 Bug(none) paint/invalidation/iframe-display-none-to-display-block.html [ Failure ]
@@ -1274,9 +1242,6 @@
 Bug(none) paint/invalidation/invalidation-with-scale-transform.html [ Failure ]
 Bug(none) paint/invalidation/japanese-rl-selection-clear.html [ Failure ]
 Bug(none) paint/invalidation/japanese-rl-selection-repaint.html [ Failure ]
-Bug(none) paint/invalidation/justify-content-distribution-change-grid.html [ Failure ]
-Bug(none) paint/invalidation/justify-self-change.html [ Failure ]
-Bug(none) paint/invalidation/layer-full-repaint.html [ Failure ]
 Bug(none) paint/invalidation/layer-hide-when-needs-layout.html [ Failure ]
 Bug(none) paint/invalidation/layout-state-only-positioned.html [ Failure ]
 Bug(none) paint/invalidation/layout-state-relative.html [ Failure ]
@@ -1306,7 +1271,6 @@
 Bug(none) paint/invalidation/multicol-nested.html [ Failure ]
 Bug(none) paint/invalidation/multicol-relpos-with-abspos.html [ Failure ]
 Bug(none) paint/invalidation/multicol-repaint.html [ Failure ]
-Bug(none) paint/invalidation/multicol-resize-with-rule.html [ Failure ]
 Bug(none) paint/invalidation/multicol-with-abspos-in-relpos.html [ Failure ]
 Bug(none) paint/invalidation/multicol-with-abspos.html [ Failure ]
 Bug(none) paint/invalidation/multicol-with-block.html [ Failure ]
@@ -1316,8 +1280,6 @@
 Bug(none) paint/invalidation/multicol-with-text.html [ Failure ]
 Bug(none) paint/invalidation/multiple-backgrounds-style-change.html [ Failure ]
 Bug(none) paint/invalidation/negative-shadow-box-expand.html [ Failure ]
-Bug(none) paint/invalidation/negative-shadow-box-shrink.html [ Failure ]
-Bug(none) paint/invalidation/negative-text-indent-with-overflow-hidden.html [ Failure ]
 Bug(none) paint/invalidation/nested-fixed-iframe-scrolled.html [ Failure ]
 Bug(none) paint/invalidation/non-text-link-invalidation-optimization.html [ Failure ]
 Bug(none) paint/invalidation/offset-change-wrong-invalidation-with-float.html [ Failure ]
@@ -1326,17 +1288,13 @@
 Bug(none) paint/invalidation/outline-become-affected-by-descendant.html [ Failure ]
 Bug(none) paint/invalidation/outline-become-not-affected-by-descendant.html [ Failure ]
 Bug(none) paint/invalidation/outline-change-invalidation.html [ Failure ]
-Bug(none) paint/invalidation/outline-change-offset.html [ Failure ]
 Bug(none) paint/invalidation/outline-change-repaint.html [ Failure ]
 Bug(none) paint/invalidation/outline-child-repaint.html [ Failure ]
 Bug(none) paint/invalidation/outline-clip-change.html [ Failure ]
 Bug(none) paint/invalidation/outline-containing-image-in-non-standard-mode.html [ Failure ]
 Bug(none) paint/invalidation/outline-continuations.html [ Failure ]
-Bug(none) paint/invalidation/outline-current-color.html [ Failure ]
 Bug(none) paint/invalidation/outline-inset.html [ Failure ]
-Bug(none) paint/invalidation/outline-not-affected-by-descendant.html [ Failure ]
 Bug(none) paint/invalidation/outline-repaint-glitch.html [ Failure ]
-Bug(none) paint/invalidation/outline-shrinking.html [ Failure ]
 Bug(none) paint/invalidation/overflow-auto-in-overflow-auto-scrolled.html [ Failure ]
 Bug(none) paint/invalidation/overflow-changed-on-child-of-composited-layer.html [ Failure ]
 Bug(none) paint/invalidation/overflow-delete-line.html [ Failure ]
@@ -1355,7 +1313,6 @@
 Bug(none) paint/invalidation/overflow-scroll-in-overflow-scroll-scrolled.html [ Failure ]
 Bug(none) paint/invalidation/overflow-scroll-local-background-text-color-change.html [ Failure ]
 Bug(none) paint/invalidation/overflow-show.html [ Failure ]
-Bug(none) paint/invalidation/padding-border-keeping-border-box-and-content-box.html [ Failure ]
 Bug(none) paint/invalidation/padding-keeping-content-size.html [ Failure ]
 Bug(none) paint/invalidation/padding-keeping-visual-size.html [ Failure ]
 Bug(none) paint/invalidation/paged-with-overflowing-block-rl.html [ Failure ]
@@ -1374,7 +1331,6 @@
 Bug(none) paint/invalidation/reflection-invalidation-positioned-child.html [ Failure ]
 Bug(none) paint/invalidation/reflection-redraw.html [ Failure ]
 Bug(none) paint/invalidation/reflection-repaint-test.html [ Failure ]
-Bug(none) paint/invalidation/rel-positioned-inline-with-overflow.html [ Failure ]
 Bug(none) paint/invalidation/relative-inline-positioned-movement-repaint.html [ Failure ]
 Bug(none) paint/invalidation/relative-margin-change-repaint.html [ Failure ]
 Bug(none) paint/invalidation/relative-positioned-movement-repaint.html [ Failure ]
@@ -1388,12 +1344,10 @@
 Bug(none) paint/invalidation/repaint-during-scroll-with-zoom.html [ Failure ]
 Bug(none) paint/invalidation/repaint-during-scroll.html [ Failure ]
 Bug(none) paint/invalidation/repaint-in-iframe.html [ Failure ]
-Bug(none) paint/invalidation/repaint-on-style-change.html [ Failure ]
 Bug(none) paint/invalidation/repaint-resized-overflow.html [ Failure ]
 Bug(none) paint/invalidation/repaint-table-row-in-composited-document.html [ Failure ]
 Bug(none) paint/invalidation/replaced-clipped-positioned-not-wrong-incremental-repainting.html [ Failure ]
 Bug(none) paint/invalidation/requestAnimation-translation-leave-traces.html [ Failure ]
-Bug(none) paint/invalidation/resize-child-within-overflow.html [ Failure ]
 Bug(none) paint/invalidation/resize-iframe-text.html [ Failure ]
 Bug(none) paint/invalidation/resize-scrollable-div.html [ Failure ]
 Bug(none) paint/invalidation/resize-scrollable-iframe.html [ Failure ]
@@ -1424,7 +1378,6 @@
 Bug(none) paint/invalidation/selection-after-delete.html [ Failure ]
 Bug(none) paint/invalidation/selection-after-remove.html [ Failure ]
 Bug(none) paint/invalidation/selection-change-in-iframe-with-relative-parent.html [ Failure ]
-Bug(none) paint/invalidation/selection-clear-after-move.html [ Failure ]
 Bug(none) paint/invalidation/selection-clear.html [ Failure ]
 Bug(none) paint/invalidation/selection-partial-invalidation-between-blocks.html [ Failure ]
 Bug(none) paint/invalidation/selection-rl.html [ Failure ]
@@ -1437,8 +1390,6 @@
 Bug(none) paint/invalidation/selection/selection-in-composited-scrolling-container.html [ Failure ]
 Bug(none) paint/invalidation/selection/selection-in-non-composited-scrolling-container.html [ Failure ]
 Bug(none) paint/invalidation/selection/selection-within-composited-scroller.html [ Failure ]
-Bug(none) paint/invalidation/shadow-box-resize-writing-mode.html [ Failure ]
-Bug(none) paint/invalidation/shadow-box-resize.html [ Failure ]
 Bug(none) paint/invalidation/shift-relative-positioned-container-with-image-addition.html [ Failure ]
 Bug(none) paint/invalidation/shift-relative-positioned-container-with-image-removal.html [ Failure ]
 Bug(none) paint/invalidation/stacked-diacritics.html [ Failure ]
@@ -1446,6 +1397,7 @@
 Bug(none) paint/invalidation/subpixel-offset-scaled-transform.html [ Failure ]
 Bug(none) paint/invalidation/subpixel-shadow-included-in-invalidation.html [ Failure ]
 Bug(none) paint/invalidation/subtree-layoutstate-transform.html [ Failure ]
+Bug(none) paint/invalidation/subtree-root-clip.html [ Failure ]
 Bug(none) paint/invalidation/subtree-root-clip-2.html [ Failure ]
 Bug(none) paint/invalidation/subtree-root-clip-3.html [ Failure ]
 Bug(none) paint/invalidation/subtree-root-skipped.html [ Failure ]
@@ -1454,11 +1406,9 @@
 Bug(none) paint/invalidation/svg/add-border-property-on-root.html [ Failure ]
 Bug(none) paint/invalidation/svg/add-outline-property-on-root.html [ Failure ]
 Bug(none) paint/invalidation/svg/animate-fill.svg [ Failure ]
-Bug(none) paint/invalidation/svg/animate-target-id-changed.svg [ Failure ]
 Bug(none) paint/invalidation/svg/animated-path-inside-transformed-html.xhtml [ Failure ]
 Bug(none) paint/invalidation/svg/animated-svg-as-image-transformed-offscreen.html [ Failure ]
 Bug(none) paint/invalidation/svg/append-text-node-to-tspan.html [ Failure ]
-Bug(none) paint/invalidation/svg/change-background-color.html [ Failure ]
 Bug(none) paint/invalidation/svg/circle-move-invalidation.svg [ Failure ]
 Bug(none) paint/invalidation/svg/clip-path-child-changes.svg [ Failure ]
 Bug(none) paint/invalidation/svg/clip-path-href-changes.svg [ Failure ]
@@ -1486,17 +1436,13 @@
 Bug(none) paint/invalidation/svg/feImage-target-remove-from-document.svg [ Failure ]
 Bug(none) paint/invalidation/svg/feImage-target-style-change.svg [ Failure ]
 Bug(none) paint/invalidation/svg/fecomponenttransfer-in1-change.svg [ Failure ]
-Bug(none) paint/invalidation/svg/fill-opacity-update.svg [ Failure ]
 Bug(none) paint/invalidation/svg/filter-child-repaint.svg [ Failure ]
 Bug(none) paint/invalidation/svg/filter-refresh.svg [ Failure ]
 Bug(none) paint/invalidation/svg/filter-width-update.svg [ Failure ]
 Bug(none) paint/invalidation/svg/focus-element.html [ Failure ]
 Bug(none) paint/invalidation/svg/foreign-object-repaint.svg [ Failure ]
-Bug(none) paint/invalidation/svg/gradient-add-stops.svg [ Failure ]
-Bug(none) paint/invalidation/svg/gradient-stop-style-change.svg [ Failure ]
 Bug(none) paint/invalidation/svg/hairline-stroke-squarecap.svg [ Failure ]
 Bug(none) paint/invalidation/svg/image-animation-with-zoom.html [ Failure ]
-Bug(none) paint/invalidation/svg/image-href-change.svg [ Failure ]
 Bug(none) paint/invalidation/svg/image-with-clip-path.svg [ Failure ]
 Bug(none) paint/invalidation/svg/inner-svg-change-viewBox-contract.svg [ Failure ]
 Bug(none) paint/invalidation/svg/inner-svg-change-viewBox.svg [ Failure ]
@@ -1513,14 +1459,9 @@
 Bug(none) paint/invalidation/svg/js-repaint-rect-on-path-with-stroke.svg [ Failure ]
 Bug(none) paint/invalidation/svg/js-update-bounce.svg [ Failure ]
 Bug(none) paint/invalidation/svg/js-update-container.svg [ Failure ]
-Bug(none) paint/invalidation/svg/js-update-gradient.svg [ Failure ]
 Bug(none) paint/invalidation/svg/js-update-image.svg [ Failure ]
-Bug(none) paint/invalidation/svg/js-update-pattern-child.svg [ Failure ]
-Bug(none) paint/invalidation/svg/js-update-pattern.svg [ Failure ]
 Bug(none) paint/invalidation/svg/js-update-polygon-changes.svg [ Failure ]
 Bug(none) paint/invalidation/svg/js-update-polygon-removal.svg [ Failure ]
-Bug(none) paint/invalidation/svg/js-update-stop-linked-gradient.svg [ Failure ]
-Bug(none) paint/invalidation/svg/js-update-stop.svg [ Failure ]
 Bug(none) paint/invalidation/svg/js-update-style.svg [ Failure ]
 Bug(none) paint/invalidation/svg/js-update-transform-addition.svg [ Failure ]
 Bug(none) paint/invalidation/svg/js-update-transform-changes.svg [ Failure ]
@@ -1539,8 +1480,6 @@
 Bug(none) paint/invalidation/svg/outline-offset-text.html [ Failure ]
 Bug(none) paint/invalidation/svg/paintorder-filtered.svg [ Failure ]
 Bug(none) paint/invalidation/svg/path-pathlength-change.html [ Failure ]
-Bug(none) paint/invalidation/svg/pending-resource-after-removal.xhtml [ Failure ]
-Bug(none) paint/invalidation/svg/rect-modify-rx.svg [ Failure ]
 Bug(none) paint/invalidation/svg/relative-sized-content-with-resources.xhtml [ Failure ]
 Bug(none) paint/invalidation/svg/relative-sized-content.xhtml [ Failure ]
 Bug(none) paint/invalidation/svg/relative-sized-deep-shadow-tree-content.xhtml [ Failure ]
@@ -1559,7 +1498,6 @@
 Bug(none) paint/invalidation/svg/repaint-in-scrolled-view.html [ Failure ]
 Bug(none) paint/invalidation/svg/repaint-non-scaling-stroke-text-decoration.html [ Failure ]
 Bug(none) paint/invalidation/svg/repaint-non-scaling-stroke-text.html [ Failure ]
-Bug(none) paint/invalidation/svg/repaint-on-constant-size-change.svg [ Failure ]
 Bug(none) paint/invalidation/svg/repaint-on-image-bounds-change.svg [ Failure ]
 Bug(none) paint/invalidation/svg/repaint-paintorder.svg [ Failure ]
 Bug(none) paint/invalidation/svg/repaint-stroke-width-changes.svg [ Failure ]
@@ -1570,7 +1508,6 @@
 Bug(none) paint/invalidation/svg/shape-transform-change.html [ Failure ]
 Bug(none) paint/invalidation/svg/shape-with-nested-outline.html [ Failure ]
 Bug(none) paint/invalidation/svg/stroke-opacity-update.svg [ Failure ]
-Bug(none) paint/invalidation/svg/svg-absolute-children.svg [ Failure ]
 Bug(none) paint/invalidation/svg/svg-image-change-content-size.xhtml [ Failure ]
 Bug(none) paint/invalidation/svg/svg-image-par-resize.html [ Failure ]
 Bug(none) paint/invalidation/svg/svgsvgelement-repaint-children.html [ Failure ]
@@ -1603,14 +1540,10 @@
 Bug(none) paint/invalidation/table-outer-border.html [ Failure ]
 Bug(none) paint/invalidation/table-overflow-auto-in-overflow-auto-scrolled.html [ Failure ]
 Bug(none) paint/invalidation/table-overflow-scroll-in-overflow-scroll-scrolled.html [ Failure ]
-Bug(none) paint/invalidation/table-row-bg-change.html [ Failure ]
-Bug(none) paint/invalidation/table-row.html [ Failure ]
 Bug(none) paint/invalidation/table-section-overflow.html [ Failure ]
 Bug(none) paint/invalidation/table-section-repaint.html [ Failure ]
 Bug(none) paint/invalidation/table-shrink-row-repaint.html [ Failure ]
 Bug(none) paint/invalidation/table-two-pass-layout-overpaint.html [ Failure ]
-Bug(none) paint/invalidation/table-with-padding-row-invalidation.html [ Failure ]
-Bug(none) paint/invalidation/table/animated-row-background.html [ Failure ]
 Bug(none) paint/invalidation/table/border-collapse-change-collapse-to-separate.html [ Failure ]
 Bug(none) paint/invalidation/table/border-collapse-change-separate-to-collapse.html [ Failure ]
 Bug(none) paint/invalidation/table/cached-69296.html [ Failure ]
@@ -1666,7 +1599,6 @@
 Bug(none) paint/invalidation/vertical-overflow-parent.html [ Failure ]
 Bug(none) paint/invalidation/vertical-overflow-same.html [ Failure ]
 Bug(none) paint/invalidation/vertical-rl-as-paint-container.html [ Failure ]
-Bug(none) paint/invalidation/vertical-rl-overflow.html [ Failure ]
 Bug(none) paint/invalidation/video-mute-repaint.html [ Failure ]
 Bug(none) paint/invalidation/video-unmute-repaint.html [ Failure ]
 Bug(none) paint/invalidation/view-background-from-body-2.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index d21de14..991f99e 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1979,10 +1979,6 @@
 crbug.com/594639 external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html [ Failure ]
 crbug.com/594639 external/wpt/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html [ Failure ]
 crbug.com/594639 external/wpt/html/semantics/scripting-1/the-script-element/module/specifier-error.html [ Failure ]
-crbug.com/721070 http/tests/htmlimports/import-and-script-module-inline.html [ Crash ]
-crbug.com/721070 http/tests/htmlimports/import-and-script-module-external.html [ Crash ]
-crbug.com/721070 virtual/mojo-loading/http/tests/htmlimports/import-and-script-module-inline.html [ Crash ]
-crbug.com/721070 virtual/mojo-loading/http/tests/htmlimports/import-and-script-module-external.html [ Crash ]
 
 # This test has a failure console message with specific performance
 # numbers so a consistent baseline cannot be added. This test could be
diff --git a/third_party/WebKit/LayoutTests/fast/multicol/balance-repeating-table-headers.html b/third_party/WebKit/LayoutTests/fast/multicol/balance-repeating-table-headers.html
index 807120d..6450fbb59 100644
--- a/third_party/WebKit/LayoutTests/fast/multicol/balance-repeating-table-headers.html
+++ b/third_party/WebKit/LayoutTests/fast/multicol/balance-repeating-table-headers.html
@@ -15,11 +15,23 @@
                 <td><br></td>
             </tr>
             <tr>
+                <td><br></td>
+            </tr>
+            <tr>
+                <td><br></td>
+            </tr>
+            <tr>
                 <td style="background:yellow;"><br></td>
             </tr>
             <tr>
                 <td><br></td>
             </tr>
+            <tr>
+                <td><br></td>
+            </tr>
+            <tr>
+                <td><br></td>
+            </tr>
         </tbody>
     </table>
     <br>
diff --git a/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html b/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
index 5248363..05057cd 100644
--- a/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
+++ b/third_party/WebKit/LayoutTests/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html
@@ -204,14 +204,12 @@
       assert_equals(document.scrollingElement.scrollTop, scrollingElementTop, "For scrollingElement on step " + step);
     };
 
-    assertScrollTops(0, 0, 0, 0);
-
     var frame_actions = [
       function() {
         eventSender.gestureFlingStart(10, 10, -1000000, -1000000, "touchscreen");
       },
       flingTest.step_func(function() {
-        assertScrollTops(100, 0, 0, 1);
+        assertScrollTops(0, 0, 0, 1);
       }),
       flingTest.step_func(function() {
         assertScrollTops(100, 0, 0, 2);
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-avoid-content-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-avoid-content-expected.html
new file mode 100644
index 0000000..f339698
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-avoid-content-expected.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<p>crbug.com/720620: Break-inside avoid content doesn't overlap with repeating headers.</p>
+<div style="columns:2; line-height:20px; column-fill:auto; height:100px; orphans:1; widows:1; background:yellow;">
+    <table cellspacing="0" cellpadding="0" style="background:pink;">
+        <tbody>
+            <tr>
+                <th>repeated header</th>
+            </tr>
+            <tr>
+                <td>
+                    <div>
+                        line1<br>
+                        line2<br>
+                        line3<br><br>
+                    </div>
+                </td>
+            </tr>
+            <tr>
+                <th>repeated header</th>
+            </tr>
+                <td>
+                    <div>
+                        <div style="break-inside:avoid;">
+                            line4<br>
+                            line5<br>
+                            line6<br>
+                        </div>
+                    </div>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-avoid-content.html b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-avoid-content.html
new file mode 100644
index 0000000..de4f9f7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-avoid-content.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<style>
+thead {
+    break-inside: avoid;
+}
+</style>
+<p>crbug.com/720620: Break-inside avoid content doesn't overlap with repeating headers.</p>
+<div style="columns:2; line-height:20px; column-fill:auto; height:100px; orphans:1; widows:1; background:yellow;">
+    <table cellspacing="0" cellpadding="0" style="background:pink;">
+        <thead>
+            <tr>
+                <th>repeated header</th>
+            </tr>
+        </thead>
+        <tbody>
+            <tr>
+                <td>
+                    <div>
+                        line1<br>
+                        line2<br>
+                        line3<br>
+                        <div style="break-inside:avoid;">
+                            line4<br>
+                            line5<br>
+                            line6<br>
+                        </div>
+                    </div>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content-expected.html
new file mode 100644
index 0000000..38fdd173
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content-expected.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<p>crbug.com/720620: Break-inside avoid content doesn't overlap with repeating headers.</p>
+<div style="columns:2; line-height:20px; column-fill:auto; height:100px; orphans:1; widows:1; background:yellow;">
+    <table cellspacing="0" cellpadding="0" style="background:pink;">
+        <tbody>
+            <tr>
+                <th>repeated header</th>
+            </tr>
+            <tr>
+                <td>
+                    <div>
+                        line1<br>
+                        line2<br>
+                        line3<br>
+                        line4<br>
+                    </div>
+                </td>
+            </tr>
+            <tr>
+                <th>repeated header</th>
+            </tr>
+                <td>
+                    <div>
+                        <div style="break-inside:avoid;">
+                            line5<br>
+                            line6<br>
+                        </div>
+                    </div>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content-first-line-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content-first-line-expected.html
new file mode 100644
index 0000000..ef88a47
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content-first-line-expected.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<p>crbug.com/720620: The border on a div straddling a page-break doesn't overlap repeating headers.</p>
+<div style="columns:2; line-height:20px; column-fill:auto; height:100px; orphans:1; widows:1; background:yellow;">
+    <table cellspacing="0" cellpadding="0" style="background:pink;">
+        <tbody>
+            <tr>
+                <th>repeated header</th>
+            </tr>
+            <tr>
+                <td>
+                    <div>
+                        line1<br>
+                        line2<br>
+                        line3<br>
+                        <br>
+                    </div>
+                </td>
+            </tr>
+            <tr>
+                <th>repeated header</th>
+            </tr>
+                <td>
+                    <div>
+                        <div style="border-top: 40px solid black;">
+                            line4<br>
+                            line5<br>
+                        </div>
+                    </div>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content-first-line.html b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content-first-line.html
new file mode 100644
index 0000000..8b9117c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content-first-line.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<style>
+thead {
+    break-inside: avoid;
+}
+</style>
+<p>crbug.com/720620: The border on a div straddling a page-break doesn't overlap repeating headers.</p>
+<div style="columns:2; line-height:20px; column-fill:auto; height:100px; orphans:1; widows:1; background:yellow;">
+    <table cellspacing="0" cellpadding="0" style="background:pink;">
+        <thead>
+            <tr>
+                <th>repeated header</th>
+            </tr>
+        </thead>
+        <tbody>
+            <tr>
+                <td>
+                    <div>
+                        line1<br>
+                        line2<br>
+                        line3<br>
+                        <div style="border-top: 40px solid black;">
+                            line4<br>
+                            line5<br>
+                        </div>
+                    </div>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content.html b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content.html
new file mode 100644
index 0000000..9767424
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-cell-repeating-thead-break-inside-content.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<style>
+thead {
+    break-inside: avoid;
+}
+</style>
+<p>crbug.com/720620: Break-inside avoid content doesn't overlap with repeating headers.</p>
+<div style="columns:2; line-height:20px; column-fill:auto; height:100px; orphans:1; widows:1; background:yellow;">
+    <table cellspacing="0" cellpadding="0" style="background:pink;">
+        <thead>
+            <tr>
+                <th>repeated header</th>
+            </tr>
+        </thead>
+        <tbody>
+            <tr>
+                <td>
+                    <div>
+                        line1<br>
+                        line2<br>
+                        line3<br>
+                        <div>
+                            line4<br>
+                            line5<br>
+                            line6<br>
+                        </div>
+                    </div>
+                </td>
+            </tr>
+        </tbody>
+    </table>
+</div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header-expected.html
index 125579c..f71077c 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header-expected.html
@@ -1,39 +1,22 @@
 <!DOCTYPE html>
-<style>
-td, th {
-  background-color: #ddd;
-  border: 1px solid black;
-}
-</style>
-<p>crbug.com/669690: If the body's first row doesn't fit on a page then don't repeat headers.</p>
-<div style="columns:3; line-height: 18px; column-fill: auto; height:74px; background-color: yellow;">
-  <table>
-    <thead>
-      <tr>
-        <th>Col 1</th>
-      </tr>
-    </thead>
+<p>crbug.com/669690: If the body's first row doesn't fit on a page then stil repeat headers.</p>
+<div style="columns:3; line-height: 18px; column-fill: auto; height:105px; background-color: yellow;">
+  <table cellspacing="0" cellpadding="0" style="background:pink;">
+    <tr>
+      <th>Col 1</th>
+    </tr>
     <tr><td>
-        <p>1</p>
-        <p>2</p>
-        <p>3</p>
-        <p>4</p>
-        <p>5</p>
-        <p>6</p>
-        <p>7</p>
-        <p>8</p>
-        <p>9</p>
-
-        <p>10</p>
-        <p>11</p>
-        <p>12</p>
-        <p>13</p>
-        <p>14</p>
-        <p>15</p>
-        <p>16</p>
-        <p>17</p>
-        <p>18</p>
-        <p>19</p>
+        1<br>
+        2<br>
+        3<br>
+        4
+      </td></tr>
+    <tr>
+      <th>Col 1</th>
+    </tr>
+    <tr><td>
+        5<br>
+        6<br>
       </td></tr>
   </table>
 </div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header.html b/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header.html
index 57b9768..2dfc91a 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-large-cell-with-header.html
@@ -1,42 +1,24 @@
 <!DOCTYPE html>
 <style>
-td, th {
-  background-color: #ddd;
-  border: 1px solid black;
-}
 thead, tr {
   break-inside: avoid;
 }
 </style>
-<p>crbug.com/669690: If the body's first row doesn't fit on a page then don't repeat headers.</p>
-<div style="columns:3; line-height: 18px; column-fill: auto; height:74px; background-color: yellow;">
-  <table>
+<p>crbug.com/669690: If the body's first row doesn't fit on a page then stil repeat headers.</p>
+<div style="columns:3; line-height: 18px; column-fill: auto; height:105px; background-color: yellow;">
+  <table cellspacing="0" cellpadding="0" style="background:pink;">
     <thead>
       <tr>
         <th>Col 1</th>
       </tr>
     </thead>
     <tr><td>
-        <p>1</p>
-        <p>2</p>
-        <p>3</p>
-        <p>4</p>
-        <p>5</p>
-        <p>6</p>
-        <p>7</p>
-        <p>8</p>
-        <p>9</p>
-
-        <p>10</p>
-        <p>11</p>
-        <p>12</p>
-        <p>13</p>
-        <p>14</p>
-        <p>15</p>
-        <p>16</p>
-        <p>17</p>
-        <p>18</p>
-        <p>19</p>
+        1<br>
+        2<br>
+        3<br>
+        4<br>
+        5<br>
+        6<br>
       </td></tr>
   </table>
 </div>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-2-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-2-expected.html
index 22a7b90..35c587a 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-2-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-2-expected.html
@@ -32,8 +32,10 @@
                     </tr></td>
                 </table>
         </tr></td>
+        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
+                  <tr><td class="header" colspan=2>Col 1</td></tr>
                     <tr><td style="padding-top: 0px;">
                             <table>
                                 <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -42,20 +44,22 @@
                                 <tr><td>Te</td><td>xt</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
-                                <tr><td>Te</td><td>xt</td></tr>
-                                <tr><td>Te</td><td>xt</td></tr>
                             </table>
                     </tr></td>
                 </table>
         </tr></td>
+        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
+                  <tr><td class="header" colspan=2>Col 1</td></tr>
                     <tr><td style="padding-top: 0px;">
                             <table>
                                 <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
                                 <tr><td>Te</td><td>xt</td></tr>
+                                <tr><td>Te</td><td>xt</td></tr>
+                                <tr><td>Te</td><td>xt</td></tr>
                             </table>
                     </tr></td>
                 </table>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-3-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-3-expected.html
index 3d4ffc5..e33e876 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-3-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-3-expected.html
@@ -28,6 +28,7 @@
                     <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
+        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -37,9 +38,9 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
-                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
+        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -48,6 +49,7 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
+                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
     </table>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-4-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-4-expected.html
index 6c8afcd..9a24a2e 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-4-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-4-expected.html
@@ -28,6 +28,7 @@
                     <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
+        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -37,9 +38,9 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
-                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
+        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -48,6 +49,7 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
+                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
     </table>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-expected.html
index 3d4ffc5..e33e876 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-nested-repeating-thead-expected.html
@@ -28,6 +28,7 @@
                     <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
+        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -37,9 +38,9 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
-                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
+        <tr><td class="header" colspan=2>Col 1</td></tr>
         <tr><td style="padding-top: 0px;">
                 <table>
                     <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
@@ -48,6 +49,7 @@
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
                     <tr><td>Te</td><td>xt</td></tr>
+                    <tr><td>Te</td><td>xt</td></tr>
                 </table>
         </tr></td>
     </table>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2-expected.html
index 3a9ef6e..dea40dcd 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2-expected.html
@@ -12,7 +12,7 @@
 }
 </style>
 <p>crbug.com/624814: A row positioned naturally at the top of a column should move below any repeating table header.</p>
-<div style="columns:3; line-height: 18px; column-fill: auto; height:91px; background-color: yellow; position: relative;">
+<div style="columns:3; line-height: 18px; column-fill: auto; height:105px; background-color: yellow; position: relative;">
     <br>
     <table>
         <tr>
@@ -22,6 +22,7 @@
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
     </table>
+    <br>
     <table style="position: absolute; top: 0px">
         <tr>
             <th>Col 1</th>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2.html
index 60de484..18ca3f0 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-2.html
@@ -12,7 +12,7 @@
 }
 </style>
 <p>crbug.com/624814: A row positioned naturally at the top of a column should move below any repeating table header.</p>
-<div style="columns:3; line-height: 18px; column-fill: auto; height:91px; background-color: yellow;">
+<div style="columns:3; line-height: 18px; column-fill: auto; height:105px; background-color: yellow;">
     <br>
     <table>
         <thead>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3-expected.html
index dcede5d..c03d6831 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3-expected.html
@@ -13,7 +13,7 @@
 }
 </style>
 <p>crbug.com/624814: A row positioned naturally at the top of a column should move below any repeating table header.</p>
-<div style="columns:3; line-height: 20px; column-fill: auto; height:91px; background-color: yellow;">
+<div style="columns:3; line-height: 20px; column-fill: auto; height:110px; background-color: yellow;">
     <table>
         <tr>
             <th>Col 1</th>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3.html
index 7e059999..84e3f93 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-3.html
@@ -13,7 +13,7 @@
 }
 </style>
 <p>crbug.com/624814: A row positioned naturally at the top of a column should move below any repeating table header.</p>
-<div style="columns:3; line-height: 20px; column-fill: auto; height:91px; background-color: yellow;">
+<div style="columns:3; line-height: 20px; column-fill: auto; height:110px; background-color: yellow;">
     <table>
         <thead>
             <tr>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-expected.html
index 54f5c2f..6ae34d4 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-starts-middle-of-page-break-after-avoid-expected.html
@@ -10,6 +10,10 @@
 tr {
     break-inside: avoid;
 }
+.header {
+    font-weight: bold;
+    text-align: center
+}
 </style>
 <p>crbug.com/624814: A table header group should not repeat on each page if we can't fit at least one content row below it.</p>
 <div style="-webkit-columns:3; line-height: 20px; column-fill: auto; height:190px; background-color: yellow;">
@@ -22,13 +26,9 @@
     <br>
     <br>
     <table>
-        <thead>
-            <tr>
-                <th>Col 1</th>
-                <th>Col 2</th>
-            </tr>
-        </thead>
+        <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
         <tbody>
+        <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
@@ -36,6 +36,7 @@
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
+        <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
@@ -43,6 +44,7 @@
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
+        <tr><td class="header">Col 1</td><td class="header">Col 2</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row-expected.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row-expected.html
index 55daec89..976dfbc 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row-expected.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row-expected.html
@@ -9,7 +9,7 @@
 }
 </style>
 <p>crbug.com/642814: A row positioned naturally at the top of a column should move below any repeating table header.</p>
-<div style="columns:3; line-height: 18px; column-fill: auto; height:72px; background-color: yellow; position:relative;">
+<div style="columns:3; line-height: 18px; column-fill: auto; height:110px; background-color: yellow; position:relative;">
     <table>
         <tr>
             <th>Col 1</th>
@@ -17,7 +17,9 @@
         </tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
+        <tr><td>Te</td><td>xt</td></tr>
     </table>
+    <br>
     <table style="position: absolute; top: 0px">
         <tr>
             <th>Col 1</th>
@@ -25,6 +27,7 @@
         </tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
+        <tr><td>Te</td><td>xt</td></tr>
     </table>
 </div>
 
diff --git a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row.html b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row.html
index 648e11c6..8e05216b 100644
--- a/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row.html
+++ b/third_party/WebKit/LayoutTests/fragmentation/single-line-cells-repeating-thead-with-border-spacing-at-top-of-row.html
@@ -9,7 +9,7 @@
 }
 </style>
 <p>crbug.com/642814: A row positioned naturally at the top of a column should move below any repeating table header.</p>
-<div style="columns:3; line-height: 18px; column-fill: auto; height:72px; background-color: yellow;">
+<div style="columns:3; line-height: 18px; column-fill: auto; height:110px; background-color: yellow;">
     <table>
         <thead>
             <tr>
@@ -21,6 +21,8 @@
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
         <tr><td>Te</td><td>xt</td></tr>
+        <tr><td>Te</td><td>xt</td></tr>
+        <tr><td>Te</td><td>xt</td></tr>
     </table>
 </div>
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
index a4d57926..238e6af 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.cpp
@@ -110,11 +110,11 @@
     const v8::Local<v8::Function>& disconnected_callback,
     const v8::Local<v8::Function>& adopted_callback,
     const v8::Local<v8::Function>& attribute_changed_callback,
-    const HashSet<AtomicString>& observed_attributes) {
+    HashSet<AtomicString>&& observed_attributes) {
   ScriptCustomElementDefinition* definition = new ScriptCustomElementDefinition(
       script_state, descriptor, constructor, connected_callback,
       disconnected_callback, adopted_callback, attribute_changed_callback,
-      observed_attributes);
+      std::move(observed_attributes));
 
   // Add a constructor -> name mapping to the registry.
   v8::Local<v8::Value> name_value =
@@ -151,8 +151,8 @@
     const v8::Local<v8::Function>& disconnected_callback,
     const v8::Local<v8::Function>& adopted_callback,
     const v8::Local<v8::Function>& attribute_changed_callback,
-    const HashSet<AtomicString>& observed_attributes)
-    : CustomElementDefinition(descriptor, observed_attributes),
+    HashSet<AtomicString>&& observed_attributes)
+    : CustomElementDefinition(descriptor, std::move(observed_attributes)),
       script_state_(script_state),
       constructor_(script_state->GetIsolate(), constructor) {}
 
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h
index b8ecf40a..5d848d5f 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinition.h
@@ -37,7 +37,7 @@
       const v8::Local<v8::Function>& disconnected_callback,
       const v8::Local<v8::Function>& adopted_callback,
       const v8::Local<v8::Function>& attribute_changed_callback,
-      const HashSet<AtomicString>& observed_attributes);
+      HashSet<AtomicString>&& observed_attributes);
 
   virtual ~ScriptCustomElementDefinition() = default;
 
@@ -68,7 +68,7 @@
       const v8::Local<v8::Function>& disconnected_callback,
       const v8::Local<v8::Function>& adopted_callback,
       const v8::Local<v8::Function>& attribute_changed_callback,
-      const HashSet<AtomicString>& observed_attributes);
+      HashSet<AtomicString>&& observed_attributes);
 
   // Implementations of |CustomElementDefinition|
   ScriptValue GetConstructorForScript() final;
diff --git a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp
index 7100cc4..1d8c6d4 100644
--- a/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp
+++ b/third_party/WebKit/Source/bindings/core/v8/ScriptCustomElementDefinitionBuilder.cpp
@@ -138,7 +138,7 @@
   return ScriptCustomElementDefinition::Create(
       script_state_.Get(), registry_, descriptor, constructor_,
       connected_callback_, disconnected_callback_, adopted_callback_,
-      attribute_changed_callback_, observed_attributes_);
+      attribute_changed_callback_, std::move(observed_attributes_));
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp b/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp
index ff48065..39e3dffa 100644
--- a/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp
+++ b/third_party/WebKit/Source/core/animation/CSSInterpolationType.cpp
@@ -48,8 +48,8 @@
     // full CSSValue resolve.
     bool omit_animation_tainted = false;
     const CSSValue* resolved_value =
-        CSSVariableResolver::ResolveVariableReferences(
-            state, property_, *variable_reference_, omit_animation_tainted);
+        CSSVariableResolver(state).ResolveVariableReferences(
+            property_, *variable_reference_, omit_animation_tainted);
     return DataEquivalent(resolved_value_.Get(), resolved_value);
   }
 
@@ -144,8 +144,8 @@
       value->IsPendingSubstitutionValue()) {
     bool omit_animation_tainted = false;
     const CSSValue* resolved_value =
-        CSSVariableResolver::ResolveVariableReferences(
-            state, CssProperty(), *value, omit_animation_tainted);
+        CSSVariableResolver(state).ResolveVariableReferences(
+            CssProperty(), *value, omit_animation_tainted);
     conversion_checkers.push_back(
         ResolvedVariableChecker::Create(CssProperty(), value, resolved_value));
     value = resolved_value;
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimationUpdate.h b/third_party/WebKit/Source/core/animation/css/CSSAnimationUpdate.h
index fe0f2e8..e99959a0 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimationUpdate.h
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimationUpdate.h
@@ -104,8 +104,10 @@
     new_animations_ = update.NewAnimations();
     animations_with_updates_ = update.AnimationsWithUpdates();
     new_transitions_ = update.NewTransitions();
-    active_interpolations_for_animations_ =
-        update.ActiveInterpolationsForAnimations();
+    active_interpolations_for_custom_animations_ =
+        update.ActiveInterpolationsForCustomAnimations();
+    active_interpolations_for_standard_animations_ =
+        update.ActiveInterpolationsForStandardAnimations();
     active_interpolations_for_custom_transitions_ =
         update.ActiveInterpolationsForCustomTransitions();
     active_interpolations_for_standard_transitions_ =
@@ -122,7 +124,8 @@
     new_animations_.clear();
     animations_with_updates_.clear();
     new_transitions_.clear();
-    active_interpolations_for_animations_.clear();
+    active_interpolations_for_custom_animations_.clear();
+    active_interpolations_for_standard_animations_.clear();
     active_interpolations_for_custom_transitions_.clear();
     active_interpolations_for_standard_transitions_.clear();
     cancelled_animation_indices_.clear();
@@ -236,9 +239,13 @@
     return finished_transitions_;
   }
 
-  void AdoptActiveInterpolationsForAnimations(
+  void AdoptActiveInterpolationsForCustomAnimations(
       ActiveInterpolationsMap& new_map) {
-    new_map.swap(active_interpolations_for_animations_);
+    new_map.swap(active_interpolations_for_custom_animations_);
+  }
+  void AdoptActiveInterpolationsForStandardAnimations(
+      ActiveInterpolationsMap& new_map) {
+    new_map.swap(active_interpolations_for_standard_animations_);
   }
   void AdoptActiveInterpolationsForCustomTransitions(
       ActiveInterpolationsMap& new_map) {
@@ -248,8 +255,19 @@
       ActiveInterpolationsMap& new_map) {
     new_map.swap(active_interpolations_for_standard_transitions_);
   }
-  const ActiveInterpolationsMap& ActiveInterpolationsForAnimations() const {
-    return active_interpolations_for_animations_;
+  const ActiveInterpolationsMap& ActiveInterpolationsForCustomAnimations()
+      const {
+    return active_interpolations_for_custom_animations_;
+  }
+  ActiveInterpolationsMap& ActiveInterpolationsForCustomAnimations() {
+    return active_interpolations_for_custom_animations_;
+  }
+  const ActiveInterpolationsMap& ActiveInterpolationsForStandardAnimations()
+      const {
+    return active_interpolations_for_standard_animations_;
+  }
+  ActiveInterpolationsMap& ActiveInterpolationsForStandardAnimations() {
+    return active_interpolations_for_standard_animations_;
   }
   const ActiveInterpolationsMap& ActiveInterpolationsForCustomTransitions()
       const {
@@ -259,9 +277,6 @@
       const {
     return active_interpolations_for_standard_transitions_;
   }
-  ActiveInterpolationsMap& ActiveInterpolationsForAnimations() {
-    return active_interpolations_for_animations_;
-  }
 
   bool IsEmpty() const {
     return new_animations_.IsEmpty() &&
@@ -271,7 +286,8 @@
            animations_with_updates_.IsEmpty() && new_transitions_.IsEmpty() &&
            cancelled_transitions_.IsEmpty() &&
            finished_transitions_.IsEmpty() &&
-           active_interpolations_for_animations_.IsEmpty() &&
+           active_interpolations_for_custom_animations_.IsEmpty() &&
+           active_interpolations_for_standard_animations_.IsEmpty() &&
            active_interpolations_for_custom_transitions_.IsEmpty() &&
            active_interpolations_for_standard_transitions_.IsEmpty() &&
            updated_compositor_keyframes_.IsEmpty();
@@ -301,7 +317,8 @@
   HashSet<PropertyHandle> cancelled_transitions_;
   HashSet<PropertyHandle> finished_transitions_;
 
-  ActiveInterpolationsMap active_interpolations_for_animations_;
+  ActiveInterpolationsMap active_interpolations_for_custom_animations_;
+  ActiveInterpolationsMap active_interpolations_for_standard_animations_;
   ActiveInterpolationsMap active_interpolations_for_custom_transitions_;
   ActiveInterpolationsMap active_interpolations_for_standard_transitions_;
 
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
index f3a6055..6159cb5 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.cpp
@@ -73,7 +73,7 @@
 
 namespace {
 
-static StringKeyframeEffectModel* CreateKeyframeEffectModel(
+StringKeyframeEffectModel* CreateKeyframeEffectModel(
     StyleResolver* resolver,
     const Element* animating_element,
     Element& element,
@@ -210,7 +210,9 @@
   return false;
 }
 
-static const KeyframeEffectModelBase* GetKeyframeEffectModelBase(
+namespace {
+
+const KeyframeEffectModelBase* GetKeyframeEffectModelBase(
     const AnimationEffectReadOnly* effect) {
   if (!effect)
     return nullptr;
@@ -224,6 +226,8 @@
   return ToKeyframeEffectModelBase(model);
 }
 
+}  // namespace
+
 void CSSAnimations::CalculateCompositorAnimationUpdate(
     CSSAnimationUpdate& update,
     const Element* animating_element,
@@ -433,12 +437,15 @@
 }
 
 void CSSAnimations::MaybeApplyPendingUpdate(Element* element) {
-  previous_active_interpolations_for_animations_.clear();
+  previous_active_interpolations_for_custom_animations_.clear();
+  previous_active_interpolations_for_standard_animations_.clear();
   if (pending_update_.IsEmpty())
     return;
 
-  previous_active_interpolations_for_animations_.swap(
-      pending_update_.ActiveInterpolationsForAnimations());
+  previous_active_interpolations_for_custom_animations_.swap(
+      pending_update_.ActiveInterpolationsForCustomAnimations());
+  previous_active_interpolations_for_standard_animations_.swap(
+      pending_update_.ActiveInterpolationsForStandardAnimations());
 
   // FIXME: cancelling, pausing, unpausing animations all query
   // compositingState, which is not necessarily up to date here
@@ -636,12 +643,23 @@
   // FIXME: We should transition if an !important property changes even when an
   // animation is running, but this is a bit hard to do with the current
   // applyMatchedProperties system.
-  if (state.update.ActiveInterpolationsForAnimations().Contains(property) ||
-      (state.animating_element->GetElementAnimations() &&
-       state.animating_element->GetElementAnimations()
-           ->CssAnimations()
-           .previous_active_interpolations_for_animations_.Contains(
-               property))) {
+  if (property.IsCSSCustomProperty()) {
+    if (state.update.ActiveInterpolationsForCustomAnimations().Contains(
+            property) ||
+        (state.animating_element->GetElementAnimations() &&
+         state.animating_element->GetElementAnimations()
+             ->CssAnimations()
+             .previous_active_interpolations_for_custom_animations_.Contains(
+                 property))) {
+      return;
+    }
+  } else if (state.update.ActiveInterpolationsForStandardAnimations().Contains(
+                 property) ||
+             (state.animating_element->GetElementAnimations() &&
+              state.animating_element->GetElementAnimations()
+                  ->CssAnimations()
+                  .previous_active_interpolations_for_standard_animations_
+                  .Contains(property))) {
     return;
   }
 
@@ -935,6 +953,12 @@
   ClearPendingUpdate();
 }
 
+namespace {
+
+bool IsCustomPropertyHandle(const PropertyHandle& property) {
+  return property.IsCSSCustomProperty();
+}
+
 // TODO(alancutter): CSS properties and presentation attributes may have
 // identical effects. By grouping them in the same set we introduce a bug where
 // arbitrary hash iteration will determine the order the apply in and thus which
@@ -942,11 +966,32 @@
 // the case of effect collisions.
 // Example: Both 'color' and 'svg-color' set the color on ComputedStyle but are
 // considered distinct properties in the ActiveInterpolationsMap.
-static bool IsStylePropertyHandle(const PropertyHandle& property_handle) {
-  return property_handle.IsCSSProperty() ||
-         property_handle.IsPresentationAttribute();
+bool IsStandardPropertyHandle(const PropertyHandle& property) {
+  return (property.IsCSSProperty() && !property.IsCSSCustomProperty()) ||
+         property.IsPresentationAttribute();
 }
 
+void AdoptActiveAnimationInterpolations(
+    EffectStack* effect_stack,
+    CSSAnimationUpdate& update,
+    const HeapVector<Member<const InertEffect>>* new_animations,
+    const HeapHashSet<Member<const Animation>>* suppressed_animations) {
+  ActiveInterpolationsMap custom_interpolations(
+      EffectStack::ActiveInterpolations(
+          effect_stack, new_animations, suppressed_animations,
+          KeyframeEffectReadOnly::kDefaultPriority, IsCustomPropertyHandle));
+  update.AdoptActiveInterpolationsForCustomAnimations(custom_interpolations);
+
+  ActiveInterpolationsMap standard_interpolations(
+      EffectStack::ActiveInterpolations(
+          effect_stack, new_animations, suppressed_animations,
+          KeyframeEffectReadOnly::kDefaultPriority, IsStandardPropertyHandle));
+  update.AdoptActiveInterpolationsForStandardAnimations(
+      standard_interpolations);
+}
+
+}  // namespace
+
 void CSSAnimations::CalculateAnimationActiveInterpolations(
     CSSAnimationUpdate& update,
     const Element* animating_element) {
@@ -957,12 +1002,7 @@
 
   if (update.NewAnimations().IsEmpty() &&
       update.SuppressedAnimations().IsEmpty()) {
-    ActiveInterpolationsMap active_interpolations_for_animations(
-        EffectStack::ActiveInterpolations(
-            effect_stack, nullptr, nullptr,
-            KeyframeEffectReadOnly::kDefaultPriority, IsStylePropertyHandle));
-    update.AdoptActiveInterpolationsForAnimations(
-        active_interpolations_for_animations);
+    AdoptActiveAnimationInterpolations(effect_stack, update, nullptr, nullptr);
     return;
   }
 
@@ -974,31 +1014,23 @@
   for (const auto& updated_animation : update.AnimationsWithUpdates())
     new_effects.push_back(updated_animation.effect);
 
-  ActiveInterpolationsMap active_interpolations_for_animations(
-      EffectStack::ActiveInterpolations(
-          effect_stack, &new_effects, &update.SuppressedAnimations(),
-          KeyframeEffectReadOnly::kDefaultPriority, IsStylePropertyHandle));
-  update.AdoptActiveInterpolationsForAnimations(
-      active_interpolations_for_animations);
+  AdoptActiveAnimationInterpolations(effect_stack, update, &new_effects,
+                                     &update.SuppressedAnimations());
 }
 
-static bool IsCustomStylePropertyHandle(const PropertyHandle& property) {
-  return property.IsCSSCustomProperty();
-}
+namespace {
 
-static bool IsStandardStylePropertyHandle(const PropertyHandle& property) {
-  return IsStylePropertyHandle(property) && !property.IsCSSCustomProperty();
-}
-
-static EffectStack::PropertyHandleFilter StylePropertyFilter(
+EffectStack::PropertyHandleFilter PropertyFilter(
     CSSAnimations::PropertyPass property_pass) {
   if (property_pass == CSSAnimations::PropertyPass::kCustom) {
-    return IsCustomStylePropertyHandle;
+    return IsCustomPropertyHandle;
   }
   DCHECK_EQ(property_pass, CSSAnimations::PropertyPass::kStandard);
-  return IsStandardStylePropertyHandle;
+  return IsStandardPropertyHandle;
 }
 
+}  // namespace
+
 void CSSAnimations::CalculateTransitionActiveInterpolations(
     CSSAnimationUpdate& update,
     PropertyPass property_pass,
@@ -1014,7 +1046,7 @@
     active_interpolations_for_transitions = EffectStack::ActiveInterpolations(
         effect_stack, nullptr, nullptr,
         KeyframeEffectReadOnly::kTransitionPriority,
-        StylePropertyFilter(property_pass));
+        PropertyFilter(property_pass));
   } else {
     HeapVector<Member<const InertEffect>> new_transitions;
     for (const auto& entry : update.NewTransitions())
@@ -1035,14 +1067,18 @@
     active_interpolations_for_transitions = EffectStack::ActiveInterpolations(
         effect_stack, &new_transitions, &cancelled_animations,
         KeyframeEffectReadOnly::kTransitionPriority,
-        StylePropertyFilter(property_pass));
+        PropertyFilter(property_pass));
   }
 
+  const ActiveInterpolationsMap& animations =
+      property_pass == PropertyPass::kCustom
+          ? update.ActiveInterpolationsForCustomAnimations()
+          : update.ActiveInterpolationsForStandardAnimations();
   // Properties being animated by animations don't get values from transitions
   // applied.
-  if (!update.ActiveInterpolationsForAnimations().IsEmpty() &&
+  if (!animations.IsEmpty() &&
       !active_interpolations_for_transitions.IsEmpty()) {
-    for (const auto& entry : update.ActiveInterpolationsForAnimations())
+    for (const auto& entry : animations)
       active_interpolations_for_transitions.erase(entry.key);
   }
 
@@ -1218,11 +1254,6 @@
   return ToShadowRoot(tree_scope.RootNode()).host() == element;
 }
 
-bool CSSAnimations::IsCustomPropertyHandle(const PropertyHandle& property) {
-  return property.IsCSSProperty() &&
-         property.CssProperty() == CSSPropertyVariable;
-}
-
 bool CSSAnimations::IsAnimatingCustomProperties(
     const ElementAnimations* element_animations) {
   return element_animations &&
diff --git a/third_party/WebKit/Source/core/animation/css/CSSAnimations.h b/third_party/WebKit/Source/core/animation/css/CSSAnimations.h
index f47c4b2..11d98504 100644
--- a/third_party/WebKit/Source/core/animation/css/CSSAnimations.h
+++ b/third_party/WebKit/Source/core/animation/css/CSSAnimations.h
@@ -64,7 +64,6 @@
   static bool IsAnimationAffectingProperty(CSSPropertyID);
   static bool IsAffectedByKeyframesFromScope(const Element&, const TreeScope&);
   static bool IsAnimatingCustomProperties(const ElementAnimations*);
-  static bool IsCustomPropertyHandle(const PropertyHandle&);
   static void CalculateAnimationUpdate(CSSAnimationUpdate&,
                                        const Element* animating_element,
                                        Element&,
@@ -157,7 +156,9 @@
 
   CSSAnimationUpdate pending_update_;
 
-  ActiveInterpolationsMap previous_active_interpolations_for_animations_;
+  ActiveInterpolationsMap previous_active_interpolations_for_custom_animations_;
+  ActiveInterpolationsMap
+      previous_active_interpolations_for_standard_animations_;
 
   struct TransitionUpdateState {
     STACK_ALLOCATED();
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
index a33b5723a..46ca6234 100644
--- a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.cpp
@@ -202,21 +202,18 @@
 }
 
 const CSSValue* CSSVariableResolver::ResolveVariableReferences(
-    const StyleResolverState& state,
     CSSPropertyID id,
     const CSSValue& value,
     bool disallow_animation_tainted) {
   DCHECK(!isShorthandProperty(id));
 
   if (value.IsPendingSubstitutionValue()) {
-    return ResolvePendingSubstitutions(state, id,
-                                       ToCSSPendingSubstitutionValue(value),
+    return ResolvePendingSubstitutions(id, ToCSSPendingSubstitutionValue(value),
                                        disallow_animation_tainted);
   }
 
   if (value.IsVariableReferenceValue()) {
-    return ResolveVariableReferences(state, id,
-                                     ToCSSVariableReferenceValue(value),
+    return ResolveVariableReferences(id, ToCSSVariableReferenceValue(value),
                                      disallow_animation_tainted);
   }
 
@@ -225,18 +222,17 @@
 }
 
 const CSSValue* CSSVariableResolver::ResolveVariableReferences(
-    const StyleResolverState& state,
     CSSPropertyID id,
     const CSSVariableReferenceValue& value,
     bool disallow_animation_tainted) {
-  CSSVariableResolver resolver(state);
   Vector<CSSParserToken> tokens;
   Vector<String> backing_strings;
   bool is_animation_tainted = false;
-  if (!resolver.ResolveTokenRange(value.VariableDataValue()->Tokens(),
-                                  disallow_animation_tainted, tokens,
-                                  backing_strings, is_animation_tainted))
+  if (!ResolveTokenRange(value.VariableDataValue()->Tokens(),
+                         disallow_animation_tainted, tokens, backing_strings,
+                         is_animation_tainted)) {
     return CSSUnsetValue::Create();
+  }
   const CSSValue* result =
       CSSPropertyParser::ParseSingleValue(id, tokens, value.ParserContext());
   if (!result)
@@ -245,13 +241,12 @@
 }
 
 const CSSValue* CSSVariableResolver::ResolvePendingSubstitutions(
-    const StyleResolverState& state,
     CSSPropertyID id,
     const CSSPendingSubstitutionValue& pending_value,
     bool disallow_animation_tainted) {
   // Longhands from shorthand references follow this path.
   HeapHashMap<CSSPropertyID, Member<const CSSValue>>& property_cache =
-      state.ParsedPropertiesForPendingSubstitutionCache(pending_value);
+      state_.ParsedPropertiesForPendingSubstitutionCache(pending_value);
 
   const CSSValue* value = property_cache.at(id);
   if (!value) {
@@ -260,15 +255,12 @@
     CSSVariableReferenceValue* shorthand_value = pending_value.ShorthandValue();
     CSSPropertyID shorthand_property_id = pending_value.ShorthandPropertyId();
 
-    CSSVariableResolver resolver(state);
-
     Vector<CSSParserToken> tokens;
     Vector<String> backing_strings;
     bool is_animation_tainted = false;
-    if (resolver.ResolveTokenRange(
-            shorthand_value->VariableDataValue()->Tokens(),
-            disallow_animation_tainted, tokens, backing_strings,
-            is_animation_tainted)) {
+    if (ResolveTokenRange(shorthand_value->VariableDataValue()->Tokens(),
+                          disallow_animation_tainted, tokens, backing_strings,
+                          is_animation_tainted)) {
       HeapVector<CSSProperty, 256> parsed_properties;
 
       if (CSSPropertyParser::ParseValue(
@@ -291,62 +283,52 @@
   return CSSUnsetValue::Create();
 }
 
-void CSSVariableResolver::ResolveVariableDefinitions(
-    const StyleResolverState& state) {
-  StyleInheritedVariables* inherited_variables =
-      state.Style()->InheritedVariables();
-  StyleNonInheritedVariables* non_inherited_variables =
-      state.Style()->NonInheritedVariables();
-  if (!inherited_variables && !non_inherited_variables)
+void CSSVariableResolver::ResolveVariableDefinitions() {
+  if (!inherited_variables_ && !non_inherited_variables_)
     return;
 
-  CSSVariableResolver resolver(state);
   int variable_count = 0;
-  if (inherited_variables) {
-    for (auto& variable : inherited_variables->data_)
-      resolver.ValueForCustomProperty(variable.key);
-    variable_count += inherited_variables->data_.size();
+  if (inherited_variables_) {
+    for (auto& variable : inherited_variables_->data_)
+      ValueForCustomProperty(variable.key);
+    variable_count += inherited_variables_->data_.size();
   }
-  if (non_inherited_variables) {
-    for (auto& variable : non_inherited_variables->data_)
-      resolver.ValueForCustomProperty(variable.key);
-    variable_count += non_inherited_variables->data_.size();
+  if (non_inherited_variables_) {
+    for (auto& variable : non_inherited_variables_->data_)
+      ValueForCustomProperty(variable.key);
+    variable_count += non_inherited_variables_->data_.size();
   }
-  INCREMENT_STYLE_STATS_COUNTER(state.GetDocument().GetStyleEngine(),
+  INCREMENT_STYLE_STATS_COUNTER(state_.GetDocument().GetStyleEngine(),
                                 custom_properties_applied, variable_count);
 }
 
-void CSSVariableResolver::ComputeRegisteredVariables(
-    const StyleResolverState& state) {
+void CSSVariableResolver::ComputeRegisteredVariables() {
   // const_cast is needed because Persistent<const ...> doesn't work properly.
 
-  StyleInheritedVariables* inherited_variables =
-      state.Style()->InheritedVariables();
-  if (inherited_variables) {
-    for (auto& variable : inherited_variables->registered_data_) {
+  if (inherited_variables_) {
+    for (auto& variable : inherited_variables_->registered_data_) {
       if (variable.value) {
         variable.value = const_cast<CSSValue*>(
             &StyleBuilderConverter::ConvertRegisteredPropertyValue(
-                state, *variable.value));
+                state_, *variable.value));
       }
     }
   }
 
-  StyleNonInheritedVariables* non_inherited_variables =
-      state.Style()->NonInheritedVariables();
-  if (non_inherited_variables) {
-    for (auto& variable : non_inherited_variables->registered_data_) {
+  if (non_inherited_variables_) {
+    for (auto& variable : non_inherited_variables_->registered_data_) {
       if (variable.value) {
         variable.value = const_cast<CSSValue*>(
             &StyleBuilderConverter::ConvertRegisteredPropertyValue(
-                state, *variable.value));
+                state_, *variable.value));
       }
     }
   }
 }
 
 CSSVariableResolver::CSSVariableResolver(const StyleResolverState& state)
-    : inherited_variables_(state.Style()->InheritedVariables()),
+    : state_(state),
+      inherited_variables_(state.Style()->InheritedVariables()),
       non_inherited_variables_(state.Style()->NonInheritedVariables()),
       registry_(state.GetDocument().GetPropertyRegistry()) {}
 
diff --git a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h
index fe5baa0..dbb8a82 100644
--- a/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h
+++ b/third_party/WebKit/Source/core/css/resolver/CSSVariableResolver.h
@@ -26,30 +26,25 @@
   STACK_ALLOCATED();
 
  public:
-  static void ResolveVariableDefinitions(const StyleResolverState&);
-
-  // Shorthand properties are not supported.
-  static const CSSValue* ResolveVariableReferences(
-      const StyleResolverState&,
-      CSSPropertyID,
-      const CSSValue&,
-      bool disallow_animation_tainted);
-
-  static void ComputeRegisteredVariables(const StyleResolverState&);
-
- private:
   CSSVariableResolver(const StyleResolverState&);
 
-  static const CSSValue* ResolvePendingSubstitutions(
-      const StyleResolverState&,
+  void ResolveVariableDefinitions();
+
+  // Shorthand properties are not supported.
+  const CSSValue* ResolveVariableReferences(CSSPropertyID,
+                                            const CSSValue&,
+                                            bool disallow_animation_tainted);
+
+  void ComputeRegisteredVariables();
+
+ private:
+  const CSSValue* ResolvePendingSubstitutions(
       CSSPropertyID,
       const CSSPendingSubstitutionValue&,
       bool disallow_animation_tainted);
-  static const CSSValue* ResolveVariableReferences(
-      const StyleResolverState&,
-      CSSPropertyID,
-      const CSSVariableReferenceValue&,
-      bool disallow_animation_tainted);
+  const CSSValue* ResolveVariableReferences(CSSPropertyID,
+                                            const CSSVariableReferenceValue&,
+                                            bool disallow_animation_tainted);
 
   // These return false if we encounter a reference to an invalid variable with
   // no fallback.
@@ -87,6 +82,7 @@
   PassRefPtr<CSSVariableData> ResolveCustomProperty(AtomicString name,
                                                     const CSSVariableData&);
 
+  const StyleResolverState& state_;
   StyleInheritedVariables* inherited_variables_;
   StyleNonInheritedVariables* non_inherited_variables_;
   Member<const PropertyRegistry> registry_;
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
index 0ce638345..ba892c3 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleBuilderCustom.cpp
@@ -119,8 +119,8 @@
     bool omit_animation_tainted =
         CSSAnimations::IsAnimationAffectingProperty(id);
     const CSSValue* resolved_value =
-        CSSVariableResolver::ResolveVariableReferences(state, id, value,
-                                                       omit_animation_tainted);
+        CSSVariableResolver(state).ResolveVariableReferences(
+            id, value, omit_animation_tainted);
     ApplyProperty(id, state, *resolved_value);
 
     if (!state.Style()->HasVariableReferenceFromNonInheritedProperty() &&
diff --git a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
index 27323df..aa8564f5 100644
--- a/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
+++ b/third_party/WebKit/Source/core/css/resolver/StyleResolver.cpp
@@ -1170,21 +1170,22 @@
     state.SetApplyPropertyToVisitedLinkStyle(true);
   }
 
-  const ActiveInterpolationsMap& active_interpolations_map_for_animations =
-      state.AnimationUpdate().ActiveInterpolationsForAnimations();
+  const ActiveInterpolationsMap&
+      active_interpolations_map_for_standard_animations =
+          state.AnimationUpdate().ActiveInterpolationsForStandardAnimations();
   const ActiveInterpolationsMap&
       active_interpolations_map_for_standard_transitions =
           state.AnimationUpdate().ActiveInterpolationsForStandardTransitions();
   // TODO(crbug.com/644148): Apply animations on custom properties.
   ApplyAnimatedProperties<kHighPropertyPriority>(
-      state, active_interpolations_map_for_animations);
+      state, active_interpolations_map_for_standard_animations);
   ApplyAnimatedProperties<kHighPropertyPriority>(
       state, active_interpolations_map_for_standard_transitions);
 
   UpdateFont(state);
 
   ApplyAnimatedProperties<kLowPropertyPriority>(
-      state, active_interpolations_map_for_animations);
+      state, active_interpolations_map_for_standard_animations);
   ApplyAnimatedProperties<kLowPropertyPriority>(
       state, active_interpolations_map_for_standard_transitions);
 
@@ -1229,6 +1230,7 @@
     CSSPropertyID property = entry.key.IsCSSProperty()
                                  ? entry.key.CssProperty()
                                  : entry.key.PresentationAttribute();
+    DCHECK_EQ(entry.key.IsCSSCustomProperty(), priority == kResolveVariables);
     if (!CSSPropertyPriorityData<priority>::PropertyHasPriority(property))
       continue;
     const Interpolation& interpolation = *entry.value.front();
@@ -1751,13 +1753,14 @@
       needs_apply_pass);
   if (apply_animations == kIncludeAnimations) {
     ApplyAnimatedProperties<kResolveVariables>(
-        state, state.AnimationUpdate().ActiveInterpolationsForAnimations());
+        state,
+        state.AnimationUpdate().ActiveInterpolationsForCustomAnimations());
     ApplyAnimatedProperties<kResolveVariables>(
         state,
         state.AnimationUpdate().ActiveInterpolationsForCustomTransitions());
   }
   // TODO(leviw): stop recalculating every time
-  CSSVariableResolver::ResolveVariableDefinitions(state);
+  CSSVariableResolver(state).ResolveVariableDefinitions();
 
   if (RuntimeEnabledFeatures::cssApplyAtRulesEnabled()) {
     if (CacheCustomPropertiesForApplyAtRules(state,
@@ -1770,12 +1773,13 @@
           needs_apply_pass);
       if (apply_animations == kIncludeAnimations) {
         ApplyAnimatedProperties<kResolveVariables>(
-            state, state.AnimationUpdate().ActiveInterpolationsForAnimations());
+            state,
+            state.AnimationUpdate().ActiveInterpolationsForCustomAnimations());
         ApplyAnimatedProperties<kResolveVariables>(
             state,
             state.AnimationUpdate().ActiveInterpolationsForCustomTransitions());
       }
-      CSSVariableResolver::ResolveVariableDefinitions(state);
+      CSSVariableResolver(state).ResolveVariableDefinitions();
     }
   }
 }
@@ -1815,17 +1819,12 @@
     return;
   }
   if (!state.AnimationUpdate()
+           .ActiveInterpolationsForCustomAnimations()
+           .IsEmpty() ||
+      !state.AnimationUpdate()
            .ActiveInterpolationsForCustomTransitions()
            .IsEmpty()) {
     state.SetIsAnimatingCustomProperties(true);
-    return;
-  }
-  for (const auto& property_handle :
-       state.AnimationUpdate().ActiveInterpolationsForAnimations().Keys()) {
-    if (CSSAnimations::IsCustomPropertyHandle(property_handle)) {
-      state.SetIsAnimatingCustomProperties(true);
-      return;
-    }
   }
 }
 
@@ -1888,7 +1887,7 @@
     apply_inherited_only = false;
 
   // Registered custom properties are computed after high priority properties.
-  CSSVariableResolver::ComputeRegisteredVariables(state);
+  CSSVariableResolver(state).ComputeRegisteredVariables();
 
   // Now do the normal priority UA properties.
   ApplyMatchedProperties<kLowPropertyPriority, kCheckNeedsApplyPass>(
diff --git a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
index 35b734f74..33e3fa9 100644
--- a/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
+++ b/third_party/WebKit/Source/core/dom/ScriptLoader.cpp
@@ -429,8 +429,9 @@
       // scripts.
 
       DCHECK(RuntimeEnabledFeatures::moduleScriptsEnabled());
+
       Modulator* modulator = Modulator::From(
-          ToScriptStateForMainWorld(element_document.GetFrame()));
+          ToScriptStateForMainWorld(context_document->GetFrame()));
       FetchModuleScriptTree(url, modulator, nonce, parser_state,
                             credentials_mode);
 
@@ -486,7 +487,7 @@
         //     source text, settings, base URL, cryptographic nonce,
         //     parser state, and module script credentials mode."
         Modulator* modulator = Modulator::From(
-            ToScriptStateForMainWorld(element_document.GetFrame()));
+            ToScriptStateForMainWorld(context_document->GetFrame()));
         ModuleScript* module_script = ModuleScript::Create(
             ScriptContent(), modulator, base_url, nonce, parser_state,
             credentials_mode, kSharableCrossOrigin, position);
diff --git a/third_party/WebKit/Source/core/dom/custom/CustomElementTestHelpers.h b/third_party/WebKit/Source/core/dom/custom/CustomElementTestHelpers.h
index f710de0..7d5c9bb 100644
--- a/third_party/WebKit/Source/core/dom/custom/CustomElementTestHelpers.h
+++ b/third_party/WebKit/Source/core/dom/custom/CustomElementTestHelpers.h
@@ -46,8 +46,8 @@
       : CustomElementDefinition(descriptor) {}
 
   TestCustomElementDefinition(const CustomElementDescriptor& descriptor,
-                              const HashSet<AtomicString>& observed_attributes)
-      : CustomElementDefinition(descriptor, observed_attributes) {}
+                              HashSet<AtomicString>&& observed_attributes)
+      : CustomElementDefinition(descriptor, std::move(observed_attributes)) {}
 
   ~TestCustomElementDefinition() override = default;
 
diff --git a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
index a7e2d22f..3d6ac8c 100644
--- a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
@@ -1526,7 +1526,7 @@
   // Add marker under "Initial text"
   EphemeralRange marker_range = PlainTextRange(0, 12).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   // Replace "Initial" with "Original"
   Vector<CompositionUnderline> empty_underlines;
@@ -1546,7 +1546,7 @@
   // Add marker under "initial text"
   EphemeralRange marker_range = PlainTextRange(13, 25).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   // Replace "some initial" with "boring"
   Vector<CompositionUnderline> empty_underlines;
@@ -1564,7 +1564,7 @@
   // Add marker under "Initial text"
   EphemeralRange marker_range = PlainTextRange(0, 12).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   // Replace "text" with "string"
   Vector<CompositionUnderline> empty_underlines;
@@ -1584,7 +1584,7 @@
   // Add marker under "some initial"
   EphemeralRange marker_range = PlainTextRange(8, 20).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   // Replace "initial text" with "content"
   Vector<CompositionUnderline> empty_underlines;
@@ -1604,7 +1604,7 @@
   // Add marker under "text"
   EphemeralRange marker_range = PlainTextRange(8, 12).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   // Replace "text" with "string"
   Vector<CompositionUnderline> empty_underlines;
@@ -1623,7 +1623,7 @@
   // Add marker under "Initial"
   EphemeralRange marker_range = PlainTextRange(0, 7).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
 
@@ -1644,7 +1644,7 @@
   // Add marker under "text"
   EphemeralRange marker_range = PlainTextRange(8, 12).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
 
@@ -1664,23 +1664,23 @@
 
   EphemeralRange marker_range = PlainTextRange(0, 5).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   marker_range = PlainTextRange(5, 10).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   marker_range = PlainTextRange(10, 15).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   marker_range = PlainTextRange(15, 20).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   marker_range = PlainTextRange(20, 25).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   EXPECT_EQ(5u, GetDocument().Markers().Markers().size());
 
@@ -1707,7 +1707,7 @@
 
   EphemeralRange marker_range = PlainTextRange(5, 10).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   EXPECT_EQ(1u, GetDocument().Markers().Markers().size());
 
@@ -1725,7 +1725,7 @@
 
   EphemeralRange marker_range = PlainTextRange(5, 10).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   // Delete middle of marker
   Vector<CompositionUnderline> empty_underlines;
@@ -1744,15 +1744,15 @@
 
   EphemeralRange marker_range = PlainTextRange(0, 5).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   marker_range = PlainTextRange(5, 10).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   marker_range = PlainTextRange(10, 15).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   EXPECT_EQ(3u, GetDocument().Markers().Markers().size());
 
@@ -1777,15 +1777,15 @@
 
   EphemeralRange marker_range = PlainTextRange(0, 5).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   marker_range = PlainTextRange(5, 15).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   marker_range = PlainTextRange(15, 20).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   EXPECT_EQ(3u, GetDocument().Markers().Markers().size());
 
diff --git a/third_party/WebKit/Source/core/editing/commands/SplitTextNodeCommandTest.cpp b/third_party/WebKit/Source/core/editing/commands/SplitTextNodeCommandTest.cpp
index 7b79e69..0c810cc 100644
--- a/third_party/WebKit/Source/core/editing/commands/SplitTextNodeCommandTest.cpp
+++ b/third_party/WebKit/Source/core/editing/commands/SplitTextNodeCommandTest.cpp
@@ -20,15 +20,15 @@
 
   EphemeralRange range = PlainTextRange(0, 5).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      range, DocumentMarker::MatchStatus::kInactive);
+      range, TextMatchMarker::MatchStatus::kInactive);
 
   range = PlainTextRange(6, 11).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      range, DocumentMarker::MatchStatus::kInactive);
+      range, TextMatchMarker::MatchStatus::kInactive);
 
   range = PlainTextRange(12, 17).CreateRange(*div);
   GetDocument().Markers().AddTextMatchMarker(
-      range, DocumentMarker::MatchStatus::kInactive);
+      range, TextMatchMarker::MatchStatus::kInactive);
 
   SimpleEditCommand* command = SplitTextNodeCommand::Create(
       ToText(GetDocument().body()->firstChild()->firstChild()), 8);
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarker.h b/third_party/WebKit/Source/core/editing/markers/DocumentMarker.h
index c023c59..f0c8d38 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarker.h
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarker.h
@@ -128,8 +128,6 @@
     MisspellingMarkers() : MarkerTypes(kSpelling | kGrammar) {}
   };
 
-  enum class MatchStatus { kInactive, kActive };
-
   DocumentMarker(MarkerType,
                  unsigned start_offset,
                  unsigned end_offset,
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
index 5f387eb..5456789 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
@@ -146,7 +146,7 @@
 
 void DocumentMarkerController::AddTextMatchMarker(
     const EphemeralRange& range,
-    DocumentMarker::MatchStatus match_status) {
+    TextMatchMarker::MatchStatus match_status) {
   DCHECK(!document_->NeedsLayoutTreeUpdate());
   AddMarkerInternal(range, [match_status](int start_offset, int end_offset) {
     return new TextMatchMarker(start_offset, end_offset, match_status);
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.h b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.h
index a287b5a8..22ada19 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.h
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.h
@@ -33,6 +33,7 @@
 #include "core/dom/SynchronousMutationObserver.h"
 #include "core/editing/iterators/TextIterator.h"
 #include "core/editing/markers/DocumentMarker.h"
+#include "core/editing/markers/TextMatchMarker.h"
 #include "platform/geometry/IntRect.h"
 #include "platform/heap/Handle.h"
 #include "platform/wtf/HashMap.h"
@@ -57,7 +58,7 @@
                          const String& description = g_empty_string);
   void AddGrammarMarker(const EphemeralRange&,
                         const String& description = g_empty_string);
-  void AddTextMatchMarker(const EphemeralRange&, DocumentMarker::MatchStatus);
+  void AddTextMatchMarker(const EphemeralRange&, TextMatchMarker::MatchStatus);
   void AddCompositionMarker(const EphemeralRange&,
                             Color underline_color,
                             bool thick,
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp
index bde1c9d..c26976e2 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerControllerTest.cpp
@@ -81,7 +81,7 @@
   GetDocument().UpdateStyleAndLayout();
   auto range = EphemeralRange::RangeOfContents(*node);
   MarkerController().AddTextMatchMarker(range,
-                                        DocumentMarker::MatchStatus::kActive);
+                                        TextMatchMarker::MatchStatus::kActive);
 }
 
 void DocumentMarkerControllerTest::SetBodyInnerHTML(const char* body_content) {
@@ -241,8 +241,8 @@
   EXPECT_FALSE(MarkerController().SetTextMatchMarkersActive(range, true));
 
   // Add a marker and try it once more.
-  MarkerController().AddTextMatchMarker(range,
-                                        DocumentMarker::MatchStatus::kInactive);
+  MarkerController().AddTextMatchMarker(
+      range, TextMatchMarker::MatchStatus::kInactive);
   EXPECT_EQ(1u, MarkerController().Markers().size());
   EXPECT_TRUE(MarkerController().SetTextMatchMarkersActive(range, true));
 }
@@ -257,7 +257,7 @@
   EphemeralRange marker_range =
       EphemeralRange(Position(text, 0), Position(text, 3));
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   // Remove markers that overlap "a"
   marker_range = EphemeralRange(Position(text, 0), Position(text, 1));
@@ -277,7 +277,7 @@
   EphemeralRange marker_range =
       EphemeralRange(Position(text, 0), Position(text, 3));
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   // Remove markers that overlap "b"
   marker_range = EphemeralRange(Position(text, 1), Position(text, 2));
@@ -297,7 +297,7 @@
   EphemeralRange marker_range =
       EphemeralRange(Position(text, 0), Position(text, 3));
   GetDocument().Markers().AddTextMatchMarker(
-      marker_range, DocumentMarker::MatchStatus::kInactive);
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   // Remove markers that overlap "c"
   marker_range = EphemeralRange(Position(text, 2), Position(text, 3));
@@ -316,8 +316,8 @@
   // Add a spelling marker and a text match marker to "foo".
   const EphemeralRange marker_range(Position(text, 0), Position(text, 3));
   MarkerController().AddSpellingMarker(marker_range);
-  MarkerController().AddTextMatchMarker(marker_range,
-                                        DocumentMarker::MatchStatus::kInactive);
+  MarkerController().AddTextMatchMarker(
+      marker_range, TextMatchMarker::MatchStatus::kInactive);
 
   MarkerController().RemoveSpellingMarkersUnderWords({"foo"});
 
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerListEditorTest.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerListEditorTest.cpp
index a1976a15..2bf66f9 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerListEditorTest.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerListEditorTest.cpp
@@ -13,7 +13,7 @@
  protected:
   DocumentMarker* CreateMarker(unsigned startOffset, unsigned endOffset) {
     return new TextMatchMarker(startOffset, endOffset,
-                               DocumentMarker::MatchStatus::kInactive);
+                               TextMatchMarker::MatchStatus::kInactive);
   }
 };
 
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerTest.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerTest.cpp
index 1291ad2..4a9b876e 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerTest.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerTest.cpp
@@ -15,7 +15,7 @@
  protected:
   DocumentMarker* CreateMarker(unsigned startOffset, unsigned endOffset) {
     return new TextMatchMarker(startOffset, endOffset,
-                               DocumentMarker::MatchStatus::kInactive);
+                               TextMatchMarker::MatchStatus::kInactive);
   }
 };
 
diff --git a/third_party/WebKit/Source/core/editing/markers/TextMatchMarker.h b/third_party/WebKit/Source/core/editing/markers/TextMatchMarker.h
index 2c24521..4422679 100644
--- a/third_party/WebKit/Source/core/editing/markers/TextMatchMarker.h
+++ b/third_party/WebKit/Source/core/editing/markers/TextMatchMarker.h
@@ -41,6 +41,8 @@
   enum class State { kInvalid, kValidNull, kValidNotNull };
 
  public:
+  enum class MatchStatus { kInactive, kActive };
+
   TextMatchMarker(unsigned start_offset,
                   unsigned end_offset,
                   MatchStatus status)
diff --git a/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImplTest.cpp b/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImplTest.cpp
index ad26bac..61ecd714 100644
--- a/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImplTest.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/TextMatchMarkerListImplTest.cpp
@@ -15,7 +15,7 @@
 
   DocumentMarker* CreateMarker(unsigned start_offset, unsigned end_offset) {
     return new TextMatchMarker(start_offset, end_offset,
-                               DocumentMarker::MatchStatus::kInactive);
+                               TextMatchMarker::MatchStatus::kInactive);
   }
 
   Persistent<TextMatchMarkerListImpl> marker_list_;
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
index aaa69d2..0eacc963 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -1654,8 +1654,8 @@
     }
   }
 
-  if (frame_->IsMainFrame())
-    frame_->GetPage()->GlobalRootScrollerController().DidResizeViewport();
+  if (GetFrame().GetDocument())
+    GetFrame().GetDocument()->GetRootScrollerController().DidResizeFrameView();
 
   ShowOverlayScrollbars();
 
@@ -2000,6 +2000,15 @@
   SetLayoutSizeInternal(size);
 }
 
+void LocalFrameView::SetLayoutSizeFixedToFrameSize(bool is_fixed) {
+  if (layout_size_fixed_to_frame_size_ == is_fixed)
+    return;
+
+  layout_size_fixed_to_frame_size_ = is_fixed;
+  if (is_fixed)
+    SetLayoutSizeInternal(Size());
+}
+
 void LocalFrameView::DidScrollTimerFired(TimerBase*) {
   if (frame_->GetDocument() &&
       !frame_->GetDocument()->GetLayoutViewItem().IsNull())
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h
index 7c6e9386..130277f 100644
--- a/third_party/WebKit/Source/core/frame/LocalFrameView.h
+++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -189,9 +189,7 @@
 
   // If this is set to false, the layout size will need to be explicitly set by
   // the owner.  E.g. WebViewImpl sets its mainFrame's layout size manually
-  void SetLayoutSizeFixedToFrameSize(bool is_fixed) {
-    layout_size_fixed_to_frame_size_ = is_fixed;
-  }
+  void SetLayoutSizeFixedToFrameSize(bool);
   bool LayoutSizeFixedToFrameSize() { return layout_size_fixed_to_frame_size_; }
 
   void SetInitialViewportSize(const IntSize&);
diff --git a/third_party/WebKit/Source/core/layout/BUILD.gn b/third_party/WebKit/Source/core/layout/BUILD.gn
index 7f8d8e6..8bf30a1 100644
--- a/third_party/WebKit/Source/core/layout/BUILD.gn
+++ b/third_party/WebKit/Source/core/layout/BUILD.gn
@@ -323,6 +323,8 @@
     "line/TrailingObjects.cpp",
     "line/TrailingObjects.h",
     "line/WordMeasurement.h",
+    "ng/geometry/ng_border_edges.cc",
+    "ng/geometry/ng_border_edges.h",
     "ng/geometry/ng_box_strut.cc",
     "ng/geometry/ng_box_strut.h",
     "ng/geometry/ng_edge.h",
diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
index b649fd8..3d46733 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
@@ -1130,7 +1130,8 @@
   logical_offset += delta;
   line_box.SetPaginationStrut(LayoutUnit());
   line_box.SetIsFirstAfterPageBreak(false);
-  if (!View()->GetLayoutState()->IsPaginated())
+  LayoutState* layout_state = View()->GetLayoutState();
+  if (!layout_state->IsPaginated())
     return;
   LayoutUnit page_logical_height = PageLogicalHeightForOffset(logical_offset);
   if (!page_logical_height)
@@ -1194,14 +1195,22 @@
     // up in the next column or page. Setting a strut on the block is also
     // important when it comes to satisfying orphan requirements.
     if (ShouldSetStrutOnBlock(*this, line_box, logical_offset, line_index,
-                              page_logical_height))
-      strut_to_propagate = logical_offset;
+                              page_logical_height)) {
+      DCHECK(!IsTableCell());
+      strut_to_propagate =
+          logical_offset + layout_state->HeightOffsetForTableHeaders();
+    } else if (LayoutUnit pagination_strut =
+                   layout_state->HeightOffsetForTableHeaders()) {
+      delta += pagination_strut;
+      line_box.SetPaginationStrut(pagination_strut);
+    }
   } else if (line_box == FirstRootBox() && AllowsPaginationStrut()) {
     // This is the first line in the block. The block may still start in the
     // previous column or page, and if that's the case, attempt to pull it over
     // to where this line is, so that we don't split the top border or padding.
-    LayoutUnit strut =
-        remaining_logical_height + logical_offset - page_logical_height;
+    LayoutUnit strut = remaining_logical_height + logical_offset +
+                       layout_state->HeightOffsetForTableHeaders() -
+                       page_logical_height;
     if (strut > LayoutUnit()) {
       // The block starts in a previous column or page. Set a strut on the block
       // if there's room for the top border, padding and the line in one column
diff --git a/third_party/WebKit/Source/core/layout/LayoutBox.cpp b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
index baae320..1440fc9 100644
--- a/third_party/WebKit/Source/core/layout/LayoutBox.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutBox.cpp
@@ -58,6 +58,7 @@
 #include "core/page/AutoscrollController.h"
 #include "core/page/Page.h"
 #include "core/page/scrolling/RootScrollerController.h"
+#include "core/page/scrolling/RootScrollerUtil.h"
 #include "core/page/scrolling/ScrollingCoordinator.h"
 #include "core/page/scrolling/SnapCoordinator.h"
 #include "core/paint/BackgroundImageGeometry.h"
@@ -71,21 +72,6 @@
 #include "platform/geometry/FloatRoundedRect.h"
 #include "platform/wtf/PtrUtil.h"
 
-namespace {
-
-// Node that is currently being used as the scrolling root of a frame. See
-// |effective rootScroller| in core/page/scrolling/README.md.
-bool IsEffectiveRootScroller(const blink::LayoutBox* box) {
-  if (!box || !box->GetNode())
-    return false;
-
-  return box->GetNode() == &box->GetDocument()
-                                .GetRootScrollerController()
-                                .EffectiveRootScroller();
-}
-
-}  // namespace
-
 namespace blink {
 
 // Used by flexible boxes when flexing this element and by table cells.
@@ -126,7 +112,7 @@
       HasHiddenBackface() || HasReflection() || Style()->SpecifiesColumns() ||
       Style()->IsStackingContext() ||
       Style()->ShouldCompositeForCurrentAnimations() ||
-      IsEffectiveRootScroller(this))
+      RootScrollerUtil::IsEffective(*this))
     return kNormalPaintLayer;
 
   if (HasOverflowClip())
@@ -1509,7 +1495,7 @@
                             HitTestAction action) {
   LayoutPoint adjusted_location = accumulated_offset + Location();
 
-  if (!IsEffectiveRootScroller(this)) {
+  if (!RootScrollerUtil::IsEffective(*this)) {
     // Check if we need to do anything at all.
     // If we have clipping, then we can't have any spillout.
     LayoutRect overflow_box =
@@ -1905,7 +1891,7 @@
 LayoutRect LayoutBox::OverflowClipRect(
     const LayoutPoint& location,
     OverlayScrollbarClipBehavior overlay_scrollbar_clip_behavior) const {
-  if (IsEffectiveRootScroller(this))
+  if (RootScrollerUtil::IsEffective(*this))
     return View()->ViewRect();
 
   // FIXME: When overflow-clip (CSS3) is implemented, we'll obtain the property
@@ -5797,13 +5783,14 @@
     LayoutUnit content_logical_height) const {
   DCHECK_EQ(strut_to_next_page, PageRemainingLogicalHeightForOffset(
                                     offset, kAssociateWithLatterPage));
-  // If we're a cell in a row that straddles a page then avoid the repeating
-  // header group if necessary.
-  if (IsTableCell()) {
-    const LayoutTableCell* cell = ToLayoutTableCell(this);
-    if (!cell->Row()->IsFirstRowInSectionAfterHeader())
-      strut_to_next_page += cell->Table()->RowOffsetFromRepeatingHeader();
+  // If we're inside a cell in a row that straddles a page then avoid the
+  // repeating header group if necessary. If we're a table section we're
+  // already accounting for it.
+  if (!IsTableSection()) {
+    LayoutState* layout_state = View()->GetLayoutState();
+    strut_to_next_page += layout_state->HeightOffsetForTableHeaders();
   }
+
   LayoutUnit next_page_logical_top = offset + strut_to_next_page;
   if (PageLogicalHeightForOffset(next_page_logical_top) >=
       content_logical_height)
diff --git a/third_party/WebKit/Source/core/layout/LayoutPart.cpp b/third_party/WebKit/Source/core/layout/LayoutPart.cpp
index 631a87d5..39c73cb 100644
--- a/third_party/WebKit/Source/core/layout/LayoutPart.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutPart.cpp
@@ -36,6 +36,7 @@
 #include "core/layout/LayoutView.h"
 #include "core/layout/api/LayoutAPIShim.h"
 #include "core/layout/api/LayoutViewItem.h"
+#include "core/page/scrolling/RootScrollerUtil.h"
 #include "core/paint/PartPainter.h"
 #include "core/plugins/PluginView.h"
 
@@ -302,6 +303,11 @@
   // cause the sub-frame to layout due to the 1px snap difference. In order to
   // avoid that, the size of sub-frame is rounded in advance.
   LayoutRect size_rounded_rect = ContentBoxRect();
+
+  // IFrames set as the root scroller should get their size from their parent.
+  if (ChildFrameView() && View() && RootScrollerUtil::IsEffective(*this))
+    size_rounded_rect = LayoutRect(LayoutPoint(), View()->ViewRect().Size());
+
   size_rounded_rect.SetSize(
       LayoutSize(RoundedIntSize(size_rounded_rect.Size())));
   return size_rounded_rect;
diff --git a/third_party/WebKit/Source/core/layout/LayoutState.cpp b/third_party/WebKit/Source/core/layout/LayoutState.cpp
index da33c47..db9b1c5 100644
--- a/third_party/WebKit/Source/core/layout/LayoutState.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutState.cpp
@@ -53,6 +53,7 @@
   else
     flow_thread_ = next_->FlowThread();
   pagination_state_changed_ = next_->pagination_state_changed_;
+  height_offset_for_table_headers_ = next_->HeightOffsetForTableHeaders();
   layout_object.View()->PushLayoutState(*this);
 
   if (layout_object.IsLayoutFlowThread()) {
diff --git a/third_party/WebKit/Source/core/layout/LayoutState.h b/third_party/WebKit/Source/core/layout/LayoutState.h
index dbf781f..de1d2af 100644
--- a/third_party/WebKit/Source/core/layout/LayoutState.h
+++ b/third_party/WebKit/Source/core/layout/LayoutState.h
@@ -83,6 +83,13 @@
   LayoutUnit PageLogicalOffset(const LayoutBox&,
                                const LayoutUnit& child_logical_offset) const;
 
+  LayoutUnit HeightOffsetForTableHeaders() const {
+    return height_offset_for_table_headers_;
+  }
+  void SetHeightOffsetForTableHeaders(LayoutUnit offset) {
+    height_offset_for_table_headers_ = offset;
+  }
+
   const LayoutSize& PaginationOffset() const { return pagination_offset_; }
   bool ContainingBlockLogicalWidthChanged() const {
     return containing_block_logical_width_changed_;
@@ -113,6 +120,10 @@
   // relative positioning or scroll offsets.
   LayoutSize pagination_offset_;
 
+  // The height we need to make available for repeating table headers in
+  // paginated layout.
+  LayoutUnit height_offset_for_table_headers_;
+
   LayoutObject& layout_object_;
 };
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTable.cpp b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
index f50226b..3b8bdc8 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTable.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTable.cpp
@@ -470,8 +470,10 @@
   bool needed_layout = section.NeedsLayout();
   if (needed_layout)
     section.UpdateLayout();
-  if (needed_layout || table_height_changing == kTableHeightChanging)
+  if (needed_layout || table_height_changing == kTableHeightChanging) {
     section.SetLogicalHeight(LayoutUnit(section.CalcRowLogicalHeight()));
+    section.DetermineIfHeaderGroupShouldRepeat();
+  }
 
   if (View()->GetLayoutState()->IsPaginated())
     UpdateFragmentationInfoForChild(section);
@@ -661,15 +663,15 @@
         // If the repeating header group allows at least one row of content,
         // then store the offset for other sections to offset their rows
         // against.
-        LayoutUnit section_logical_height = section->LogicalHeight();
-        if (section_logical_height <
-                section->PageLogicalHeightForOffset(section->LogicalTop()) &&
-            section->GetPaginationBreakability() != kAllowAnyBreaks) {
+        if (section->IsRepeatingHeaderGroup()) {
+          LayoutUnit offset_for_table_headers =
+              state.HeightOffsetForTableHeaders();
+          offset_for_table_headers += section->LogicalHeight();
           // Don't include any strut in the header group - we only want the
           // height from its content.
-          LayoutUnit offset_for_table_headers = section_logical_height;
           if (LayoutTableRow* row = section->FirstRow())
             offset_for_table_headers -= row->PaginationStrut();
+          state.SetHeightOffsetForTableHeaders(offset_for_table_headers);
           SetRowOffsetFromRepeatingHeader(offset_for_table_headers);
         }
       }
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
index 9f89aaa..4b68ff6 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.cpp
@@ -333,18 +333,4 @@
   AddLayoutOverflow(cell_layout_overflow_rect);
 }
 
-bool LayoutTableRow::IsFirstRowInSectionAfterHeader() const {
-  // If there isn't room on the page for at least one content row after the
-  // header group, then we won't repeat the header on each page.
-  // https://drafts.csswg.org/css-tables-3/#repeated-headers reads like
-  // it wants us to drop headers on only the pages that a single row
-  // won't fit but we avoid the complexity of that reading until it
-  // is clarified. Tracked by crbug.com/675904
-  if (RowIndex())
-    return false;
-  LayoutTableSection* header = Table()->Header();
-  return header && Table()->SectionAbove(Section()) == header &&
-         header->GetPaginationBreakability() != kAllowAnyBreaks;
-}
-
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableRow.h b/third_party/WebKit/Source/core/layout/LayoutTableRow.h
index 7d6850eb..e9f841f 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableRow.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableRow.h
@@ -140,8 +140,6 @@
     return false;
   }
 
-  bool IsFirstRowInSectionAfterHeader() const;
-
  private:
   void AddOverflowFromCell(const LayoutTableCell*);
 
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
index 3c9f5ca..5191677 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.cpp
@@ -97,7 +97,8 @@
       needs_cell_recalc_(false),
       force_full_paint_(false),
       has_multiple_cell_levels_(false),
-      has_spanning_cells_(false) {
+      has_spanning_cells_(false),
+      is_repeating_header_group_(false) {
   // init LayoutObject attributes
   SetInline(false);  // our object is not Inline
 }
@@ -2088,9 +2089,6 @@
   // fragmentainer, above this row. Otherwise, this row will just go at the top
   // of the next fragmentainer.
 
-  LayoutTableSection* header = Table()->Header();
-  if (row_object.IsFirstRowInSectionAfterHeader())
-    Table()->SetRowOffsetFromRepeatingHeader(LayoutUnit());
   // Border spacing from the previous row has pushed this row just past the top
   // of the page, so we must reposition it to the top of the page and avoid any
   // repeating header.
@@ -2099,6 +2097,7 @@
 
   // If we have a header group we will paint it at the top of each page,
   // move the rows down to accomodate it.
+  LayoutTableSection* header = Table()->Header();
   if (header && header != this)
     pagination_strut += Table()->RowOffsetFromRepeatingHeader().ToInt();
   row_object.SetPaginationStrut(LayoutUnit(pagination_strut));
@@ -2116,30 +2115,27 @@
   row_object.SetLogicalHeight(LayoutUnit(LogicalHeightForRow(row_object)));
 }
 
-bool LayoutTableSection::IsRepeatingHeaderGroup() const {
-  if (GetPaginationBreakability() == LayoutBox::kAllowAnyBreaks)
+bool LayoutTableSection::HeaderGroupShouldRepeat() const {
+  if (Table()->Header() != this)
     return false;
-  // TODO(rhogan): Should we paint a header repeatedly if it's self-painting?
+
+  if (GetPaginationBreakability() == kAllowAnyBreaks)
+    return false;
+  // TODO(rhogan): Sections can be self-painting.
   if (HasSelfPaintingLayer())
     return false;
-  LayoutUnit page_height = Table()->PageLogicalHeightForOffset(LayoutUnit());
+  LayoutUnit page_height = PageLogicalHeightForOffset(LayoutUnit());
+  // If we don't know the page height yet, just assume we fit.
   if (!page_height)
-    return false;
+    return true;
 
   if (LogicalHeight() > page_height)
     return false;
 
-  // If the first row of the section after the header group doesn't fit on the
-  // page, then don't repeat the header on each page.
-  // See https://drafts.csswg.org/css-tables-3/#repeated-headers
-  LayoutTableSection* section_below = Table()->SectionBelow(this);
-  if (!section_below)
-    return true;
-  if (LayoutTableRow* first_row = section_below->FirstRow()) {
-    if (first_row->PaginationStrut() ||
-        first_row->LogicalHeight() > page_height)
-      return false;
-  }
+  // See https://drafts.csswg.org/css-tables-3/#repeated-headers which says
+  // a header/footer can repeat if it takes up less than a quarter of the page.
+  if (LogicalHeight() > 0 && page_height / LogicalHeight() < 4)
+    return false;
 
   return true;
 }
@@ -2156,7 +2152,7 @@
   // the header in all columns.
   // Note that this is in flow thread coordinates, not visual coordinates. The
   // enclosing LayoutFlowThread will convert to visual coordinates.
-  if (Table()->Header() == this && IsRepeatingHeaderGroup()) {
+  if (IsRepeatingHeaderGroup()) {
     transform_state.Flatten();
     FloatRect rect = transform_state.LastPlanarQuad().BoundingBox();
     rect.SetHeight(Table()->LogicalHeight());
diff --git a/third_party/WebKit/Source/core/layout/LayoutTableSection.h b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
index 8ff2023..4ba5d923 100644
--- a/third_party/WebKit/Source/core/layout/LayoutTableSection.h
+++ b/third_party/WebKit/Source/core/layout/LayoutTableSection.h
@@ -295,7 +295,7 @@
       TransformState&,
       VisualRectFlags = kDefaultVisualRectFlags) const override;
 
-  bool IsRepeatingHeaderGroup() const;
+  bool IsRepeatingHeaderGroup() const { return is_repeating_header_group_; };
 
   void UpdateLayout() override;
 
@@ -304,6 +304,10 @@
     return CellSpan(0, Table()->NumEffectiveColumns());
   }
 
+  void DetermineIfHeaderGroupShouldRepeat() {
+    is_repeating_header_group_ = HeaderGroupShouldRepeat();
+  }
+
  protected:
   void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override;
   bool NodeAtPoint(HitTestResult&,
@@ -393,6 +397,8 @@
 
   bool PaintedOutputOfObjectHasNoEffectRegardlessOfSize() const override;
 
+  bool HeaderGroupShouldRepeat() const;
+
   struct TableGridRow {
     DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
 
@@ -455,6 +461,9 @@
 
   // Whether any cell spans multiple rows or cols.
   bool has_spanning_cells_;
+
+  // Header group should be painted on every page.
+  bool is_repeating_header_group_;
 };
 
 DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutTableSection, IsTableSection());
diff --git a/third_party/WebKit/Source/core/layout/ng/geometry/ng_border_edges.cc b/third_party/WebKit/Source/core/layout/ng/geometry/ng_border_edges.cc
new file mode 100644
index 0000000..648f563
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/geometry/ng_border_edges.cc
@@ -0,0 +1,52 @@
+// Copyright 2017 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 "core/layout/ng/geometry/ng_border_edges.h"
+
+namespace blink {
+
+namespace NGBorderEdges {
+
+Physical ToPhysical(Logical logical_edges, NGWritingMode writing_mode) {
+  static_assert(kBlockStart == static_cast<Logical>(kTop) &&
+                    kBlockEnd == static_cast<Logical>(kBottom) &&
+                    kLineLeft == static_cast<Logical>(kLeft) &&
+                    kLineRight == static_cast<Logical>(kRight),
+                "Physical and Logical must match");
+
+  if (writing_mode == kHorizontalTopBottom || logical_edges == kAll)
+    return static_cast<Physical>(logical_edges);
+
+  if (writing_mode != kSidewaysLeftRight) {
+    return static_cast<Physical>((logical_edges & kBlockStart ? kRight : 0) |
+                                 (logical_edges & kBlockEnd ? kLeft : 0) |
+                                 (logical_edges & kLineLeft ? kTop : 0) |
+                                 (logical_edges & kLineRight ? kBottom : 0));
+  }
+  return static_cast<Physical>((logical_edges & kBlockStart ? kLeft : 0) |
+                               (logical_edges & kBlockEnd ? kRight : 0) |
+                               (logical_edges & kLineLeft ? kBottom : 0) |
+                               (logical_edges & kLineRight ? kTop : 0));
+}
+
+Logical ToLogical(Physical physical_edges, NGWritingMode writing_mode) {
+  if (writing_mode == kHorizontalTopBottom ||
+      physical_edges == static_cast<Physical>(kAll))
+    return static_cast<Logical>(physical_edges);
+
+  if (writing_mode != kSidewaysLeftRight) {
+    return static_cast<Logical>((physical_edges & kTop ? kLineLeft : 0) |
+                                (physical_edges & kBottom ? kLineRight : 0) |
+                                (physical_edges & kLeft ? kBlockEnd : 0) |
+                                (physical_edges & kRight ? kBlockStart : 0));
+  }
+  return static_cast<Logical>((physical_edges & kTop ? kLineRight : 0) |
+                              (physical_edges & kBottom ? kLineLeft : 0) |
+                              (physical_edges & kLeft ? kBlockStart : 0) |
+                              (physical_edges & kRight ? kBlockEnd : 0));
+}
+
+}  // namespace NGBorderEdges
+
+}  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/geometry/ng_border_edges.h b/third_party/WebKit/Source/core/layout/ng/geometry/ng_border_edges.h
new file mode 100644
index 0000000..db3e57b3
--- /dev/null
+++ b/third_party/WebKit/Source/core/layout/ng/geometry/ng_border_edges.h
@@ -0,0 +1,34 @@
+// Copyright 2017 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 NGBorderEdges_h
+#define NGBorderEdges_h
+
+#include "core/CoreExport.h"
+#include "core/layout/ng/ng_writing_mode.h"
+
+namespace blink {
+
+namespace NGBorderEdges {
+
+// Which border edges should be painted. Due to fragmentation one or more may
+// be skipped.
+enum Physical { kTop = 1, kRight = 2, kBottom = 4, kLeft = 8 };
+
+enum Logical {
+  kBlockStart = Physical::kTop,
+  kLineRight = Physical::kRight,
+  kBlockEnd = Physical::kBottom,
+  kLineLeft = Physical::kLeft,
+  kAll = kBlockStart | kLineRight | kBlockEnd | kLineLeft
+};
+
+CORE_EXPORT Physical ToPhysical(Logical, NGWritingMode);
+CORE_EXPORT Logical ToLogical(Physical, NGWritingMode);
+
+}  // namespace NGBorderEdges
+
+}  // namespace blink
+
+#endif  // NGBorderEdges_h
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment.cc b/third_party/WebKit/Source/core/layout/ng/ng_fragment.cc
index b1f8d45..7bbdf34 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment.cc
@@ -41,6 +41,11 @@
   return NGLogicalOffset(InlineOffset(), BlockOffset());
 }
 
+NGBorderEdges::Logical NGFragment::BorderEdges() const {
+  return NGBorderEdges::ToLogical(physical_fragment_->BorderEdges(),
+                                  WritingMode());
+}
+
 NGPhysicalFragment::NGFragmentType NGFragment::Type() const {
   return physical_fragment_->Type();
 }
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment.h b/third_party/WebKit/Source/core/layout/ng/ng_fragment.h
index 4c43104f..96d7a14 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment.h
@@ -34,6 +34,8 @@
   LayoutUnit BlockOffset() const;
   NGLogicalOffset Offset() const;
 
+  NGBorderEdges::Logical BorderEdges() const;
+
   NGPhysicalFragment::NGFragmentType Type() const;
 
  protected:
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
index baed4d6..7ccd659 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.cc
@@ -23,7 +23,8 @@
       direction_(TextDirection::kLtr),
       node_(node),
       layout_object_(node->GetLayoutObject()),
-      did_break_(false) {}
+      did_break_(false),
+      border_edges_(NGBorderEdges::kAll) {}
 
 NGFragmentBuilder::NGFragmentBuilder(NGPhysicalFragment::NGFragmentType type,
                                      LayoutObject* layout_object)
@@ -228,6 +229,7 @@
   RefPtr<NGPhysicalBoxFragment> fragment = AdoptRef(new NGPhysicalBoxFragment(
       layout_object_, physical_size, overflow_.ConvertToPhysical(writing_mode_),
       children_, positioned_floats_, bfc_offset_, end_margin_strut_,
+      NGBorderEdges::ToPhysical(border_edges_, writing_mode_),
       std::move(break_token)));
 
   return AdoptRef(
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
index 24f44a3..35882cb0 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_fragment_builder.h
@@ -129,6 +129,11 @@
 
   bool DidBreak() const { return did_break_; }
 
+  NGFragmentBuilder& SetBorderEdges(NGBorderEdges::Logical border_edges) {
+    border_edges_ = border_edges;
+    return *this;
+  }
+
  private:
   // Out-of-flow descendant placement information.
   // The generated fragment must compute NGStaticPosition for all
@@ -181,6 +186,8 @@
 
   WTF::Optional<NGLogicalOffset> bfc_offset_;
   NGMarginStrut end_margin_strut_;
+
+  NGBorderEdges::Logical border_edges_;
 };
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc
index ef247607..16e8108 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.cc
@@ -16,6 +16,7 @@
     Vector<NGPositionedFloat>& positioned_floats,
     const WTF::Optional<NGLogicalOffset>& bfc_offset,
     const NGMarginStrut& end_margin_strut,
+    NGBorderEdges::Physical border_edges,
     RefPtr<NGBreakToken> break_token)
     : NGPhysicalFragment(layout_object,
                          size,
@@ -26,6 +27,7 @@
       bfc_offset_(bfc_offset),
       end_margin_strut_(end_margin_strut) {
   children_.swap(children);
+  border_edge_ = border_edges;
 }
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h
index 02204cc7..09f736d 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_box_fragment.h
@@ -24,6 +24,7 @@
                         Vector<NGPositionedFloat>& positioned_floats,
                         const WTF::Optional<NGLogicalOffset>& bfc_offset,
                         const NGMarginStrut& end_margin_strut,
+                        NGBorderEdges::Physical,
                         RefPtr<NGBreakToken> break_token = nullptr);
 
   // Returns the total size, including the contents outside of the border-box.
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
index d10fbb7..4e1b702 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.cc
@@ -46,10 +46,14 @@
 NGPixelSnappedPhysicalBoxStrut NGPhysicalFragment::BorderWidths() const {
   unsigned edges = BorderEdges();
   NGPhysicalBoxStrut box_strut(
-      LayoutUnit((edges & kTopBorder) ? Style().BorderTopWidth() : .0f),
-      LayoutUnit((edges & kRightBorder) ? Style().BorderRightWidth() : .0f),
-      LayoutUnit((edges & kBottomBorder) ? Style().BorderBottomWidth() : .0f),
-      LayoutUnit((edges & kLeftBorder) ? Style().BorderLeftWidth() : .0f));
+      LayoutUnit((edges & NGBorderEdges::kTop) ? Style().BorderTopWidth()
+                                               : .0f),
+      LayoutUnit((edges & NGBorderEdges::kRight) ? Style().BorderRightWidth()
+                                                 : .0f),
+      LayoutUnit((edges & NGBorderEdges::kBottom) ? Style().BorderBottomWidth()
+                                                  : .0f),
+      LayoutUnit((edges & NGBorderEdges::kLeft) ? Style().BorderLeftWidth()
+                                                : .0f));
   return box_strut.SnapToDevicePixels();
 }
 
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
index bce1947..81ec470 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
+++ b/third_party/WebKit/Source/core/layout/ng/ng_physical_fragment.h
@@ -6,6 +6,7 @@
 #define NGPhysicalFragment_h
 
 #include "core/CoreExport.h"
+#include "core/layout/ng/geometry/ng_border_edges.h"
 #include "core/layout/ng/geometry/ng_box_strut.h"
 #include "core/layout/ng/geometry/ng_physical_offset.h"
 #include "core/layout/ng/geometry/ng_physical_size.h"
@@ -41,15 +42,6 @@
     // enough to store.
   };
 
-  // Which border edges should be painted. Due to fragmentation one or more may
-  // be skipped.
-  enum NGPaintBorderEdge {
-    kTopBorder = 1,
-    kRightBorder = 2,
-    kBottomBorder = 4,
-    kLeftBorder = 8
-  };
-
   NGFragmentType Type() const { return static_cast<NGFragmentType>(type_); }
   bool IsBox() const { return Type() == NGFragmentType::kFragmentBox; }
   bool IsText() const { return Type() == NGFragmentType::kFragmentText; }
@@ -63,7 +55,9 @@
   NGPhysicalSize Size() const { return size_; }
 
   // Bitmask for border edges, see NGPaintBorderEdge.
-  unsigned BorderEdges() const { return paint_border_edge_; }
+  NGBorderEdges::Physical BorderEdges() const {
+    return static_cast<NGBorderEdges::Physical>(border_edge_);
+  }
   NGPixelSnappedPhysicalBoxStrut BorderWidths() const;
 
   // Returns the offset relative to the parent fragment's content-box.
@@ -110,7 +104,7 @@
 
   unsigned type_ : 2;  // NGFragmentType
   unsigned is_placed_ : 1;
-  unsigned paint_border_edge_ : 4;  // NGPaintBorderEdge
+  unsigned border_edge_ : 4;  // NGPhysicalBorderEdges
 
  private:
   void Destroy() const;
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp
index 7921c18c..1085fe5 100644
--- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.cpp
@@ -7,7 +7,9 @@
 #include "core/dom/Document.h"
 #include "core/dom/Element.h"
 #include "core/frame/LocalFrameView.h"
+#include "core/html/HTMLFrameOwnerElement.h"
 #include "core/layout/LayoutBox.h"
+#include "core/layout/LayoutPart.h"
 #include "core/layout/api/LayoutViewItem.h"
 #include "core/layout/compositing/PaintLayerCompositor.h"
 #include "core/page/Page.h"
@@ -65,6 +67,9 @@
 }
 
 void RootScrollerController::Set(Element* new_root_scroller) {
+  if (root_scroller_ == new_root_scroller)
+    return;
+
   root_scroller_ = new_root_scroller;
   RecomputeEffectiveRootScroller();
 }
@@ -82,6 +87,22 @@
   RecomputeEffectiveRootScroller();
 }
 
+void RootScrollerController::DidResizeFrameView() {
+  DCHECK(document_);
+
+  Page* page = document_->GetPage();
+  if (document_->GetFrame() && document_->GetFrame()->IsMainFrame() && page)
+    page->GlobalRootScrollerController().DidResizeViewport();
+
+  // If the effective root scroller in this Document is a Frame, it'll match
+  // its parent's frame rect. We can't rely on layout to kick it to update its
+  // geometry so we do so explicitly here.
+  if (EffectiveRootScroller().IsFrameOwnerElement()) {
+    UpdateIFrameGeometryAndLayoutSize(
+        *ToHTMLFrameOwnerElement(&EffectiveRootScroller()));
+  }
+}
+
 void RootScrollerController::RecomputeEffectiveRootScroller() {
   bool root_scroller_valid =
       root_scroller_ && IsValidRootScroller(*root_scroller_);
@@ -105,8 +126,12 @@
       return;
   }
 
+  Node* old_effective_root_scroller = effective_root_scroller_;
   effective_root_scroller_ = new_effective_root_scroller;
 
+  ApplyRootScrollerProperties(*old_effective_root_scroller);
+  ApplyRootScrollerProperties(*effective_root_scroller_);
+
   if (Page* page = document_->GetPage())
     page->GlobalRootScrollerController().DidChangeRootScroller();
 }
@@ -128,6 +153,49 @@
   return true;
 }
 
+void RootScrollerController::ApplyRootScrollerProperties(Node& node) const {
+  DCHECK(document_->GetFrame());
+  DCHECK(document_->GetFrame()->View());
+
+  if (node.IsFrameOwnerElement()) {
+    HTMLFrameOwnerElement* frame_owner = ToHTMLFrameOwnerElement(&node);
+    DCHECK(frame_owner->ContentFrame());
+
+    if (frame_owner->ContentFrame()->IsLocalFrame()) {
+      LocalFrameView* frame_view =
+          ToLocalFrame(frame_owner->ContentFrame())->View();
+
+      bool is_root_scroller = &EffectiveRootScroller() == &node;
+
+      // If we're making the Frame the root scroller, it must have a FrameView
+      // by now.
+      DCHECK(frame_view || !is_root_scroller);
+      if (frame_view) {
+        frame_view->SetLayoutSizeFixedToFrameSize(!is_root_scroller);
+        UpdateIFrameGeometryAndLayoutSize(*frame_owner);
+      }
+    } else {
+      // TODO(bokan): Make work with OOPIF. crbug.com/642378.
+    }
+  }
+}
+
+void RootScrollerController::UpdateIFrameGeometryAndLayoutSize(
+    HTMLFrameOwnerElement& frame_owner) const {
+  LayoutPart* part = frame_owner.GetLayoutPart();
+  if (!part)
+    return;
+
+  part->UpdateGeometry();
+
+  if (!document_->GetFrame() || !document_->GetFrame()->View())
+    return;
+
+  LocalFrameView* frame_view = document_->GetFrame()->View();
+  if (part->ChildFrameView() && (&EffectiveRootScroller() == &frame_owner))
+    part->ChildFrameView()->SetLayoutSize(frame_view->GetLayoutSize());
+}
+
 PaintLayer* RootScrollerController::RootScrollerPaintLayer() const {
   return RootScrollerUtil::PaintLayerForRootScroller(effective_root_scroller_);
 }
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h
index e0ae595..106f5ae 100644
--- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h
+++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerController.h
@@ -12,6 +12,7 @@
 
 class Document;
 class Element;
+class HTMLFrameOwnerElement;
 class PaintLayer;
 
 // Manages the root scroller associated with a given document. The root
@@ -68,6 +69,11 @@
   // replaced by the default root scroller.
   void DidUpdateLayout();
 
+  // This class needs to be informed when the FrameView of its Document changes
+  // size. This may occur without a layout (e.g. URL bar hiding) so we can't
+  // rely on DidUpdateLayout.
+  void DidResizeFrameView();
+
   // Returns the PaintLayer associated with the currently effective root
   // scroller.
   PaintLayer* RootScrollerPaintLayer() const;
@@ -90,6 +96,12 @@
   // effective root scroller.
   bool IsValidRootScroller(const Element&) const;
 
+  // Set certain properties to the effective root scroller. Called when a Node
+  // becomes or unbecomes the effective root scroller.
+  void ApplyRootScrollerProperties(Node&) const;
+
+  void UpdateIFrameGeometryAndLayoutSize(HTMLFrameOwnerElement&) const;
+
   // The owning Document whose root scroller this object manages.
   WeakMember<Document> document_;
 
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerUtil.cpp b/third_party/WebKit/Source/core/page/scrolling/RootScrollerUtil.cpp
index e35ee64..1199f27 100644
--- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerUtil.cpp
+++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerUtil.cpp
@@ -11,6 +11,7 @@
 #include "core/layout/LayoutBox.h"
 #include "core/layout/LayoutBoxModelObject.h"
 #include "core/layout/LayoutView.h"
+#include "core/page/scrolling/RootScrollerController.h"
 #include "core/paint/PaintLayerScrollableArea.h"
 
 namespace blink {
@@ -62,6 +63,14 @@
   return box->Layer();
 }
 
+bool IsEffective(const LayoutBox& box) {
+  if (!box.GetNode())
+    return false;
+
+  return box.GetNode() ==
+         &box.GetDocument().GetRootScrollerController().EffectiveRootScroller();
+}
+
 }  // namespace RootScrollerUtil
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/page/scrolling/RootScrollerUtil.h b/third_party/WebKit/Source/core/page/scrolling/RootScrollerUtil.h
index 8c86dce5..673e844f 100644
--- a/third_party/WebKit/Source/core/page/scrolling/RootScrollerUtil.h
+++ b/third_party/WebKit/Source/core/page/scrolling/RootScrollerUtil.h
@@ -7,6 +7,7 @@
 
 namespace blink {
 
+class LayoutBox;
 class Node;
 class PaintLayer;
 class ScrollableArea;
@@ -23,6 +24,10 @@
 // rather than <html>'s since scrolling is handled by LayoutView.
 PaintLayer* PaintLayerForRootScroller(const Node*);
 
+// Returns true if the given LayoutBox is the effective root scroller in its
+// Document. See |effective root scroller| in README.md.
+bool IsEffective(const LayoutBox&);
+
 }  // namespace RootScrollerUtil
 
 }  // namespace blink
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
index 89f23b7..72fc292 100644
--- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.cpp
@@ -123,6 +123,14 @@
 
   DCHECK(border_box_changed);
 
+  if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
+    // Incremental invalidation is not applicable if there is border in the
+    // direction of border box size change because we don't know the border
+    // width when issuing incremental raster invalidations.
+    if (box_.BorderRight() || box_.BorderBottom())
+      return PaintInvalidationReason::kGeometry;
+  }
+
   if (style.HasVisualOverflowingEffect() || style.HasAppearance() ||
       style.HasFilterInducingProperty() || style.HasMask())
     return PaintInvalidationReason::kGeometry;
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.h b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.h
index 270f3c7c..7444337 100644
--- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.h
+++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidator.h
@@ -5,6 +5,7 @@
 #ifndef BoxPaintInvalidator_h
 #define BoxPaintInvalidator_h
 
+#include "core/CoreExport.h"
 #include "platform/graphics/PaintInvalidationReason.h"
 #include "platform/wtf/Allocator.h"
 
@@ -14,7 +15,7 @@
 class LayoutRect;
 struct PaintInvalidatorContext;
 
-class BoxPaintInvalidator {
+class CORE_EXPORT BoxPaintInvalidator {
   STACK_ALLOCATED();
 
  public:
@@ -27,6 +28,8 @@
   PaintInvalidationReason InvalidatePaint();
 
  private:
+  friend class BoxPaintInvalidatorTest;
+
   bool BackgroundGeometryDependsOnLayoutOverflowRect();
   bool BackgroundPaintsOntoScrollingContentsLayer();
   bool ShouldFullyInvalidateBackgroundOnLayoutOverflowChange(
diff --git a/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp b/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
index 28c6d2b..34bb698 100644
--- a/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
+++ b/third_party/WebKit/Source/core/paint/BoxPaintInvalidatorTest.cpp
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "core/paint/BoxPaintInvalidator.h"
+
 #include "core/HTMLNames.h"
 #include "core/frame/LocalFrameView.h"
 #include "core/layout/LayoutTestHelper.h"
@@ -30,6 +32,49 @@
         ->GetRasterInvalidationTracking();
   }
 
+  PaintInvalidationReason ComputePaintInvalidationReason(
+      const LayoutBox& box,
+      const LayoutRect& old_visual_rect,
+      const LayoutPoint& old_location,
+      const LayoutPoint& new_location) {
+    PaintInvalidatorContext context;
+    context.old_visual_rect = old_visual_rect;
+    context.old_location = old_location;
+    context.new_location = new_location;
+    return BoxPaintInvalidator(box, context).ComputePaintInvalidationReason();
+  }
+
+  // This applies when the target is set to meet conditions that we should do
+  // full paint invalidation instead of incremental invalidation on geometry
+  // change.
+  void ExpectFullPaintInvalidationOnGeometryChange(const char* test_title) {
+    SCOPED_TRACE(test_title);
+
+    GetDocument().View()->UpdateAllLifecyclePhases();
+    auto& target = *GetDocument().getElementById("target");
+    const auto& box = *ToLayoutBox(target.GetLayoutObject());
+    LayoutRect visual_rect = box.VisualRect();
+
+    // No geometry change.
+    EXPECT_EQ(
+        PaintInvalidationReason::kNone,
+        ComputePaintInvalidationReason(box, visual_rect, visual_rect.Location(),
+                                       visual_rect.Location()));
+
+    target.setAttribute(
+        HTMLNames::styleAttr,
+        target.getAttribute(HTMLNames::styleAttr) + "; width: 200px");
+    GetDocument().View()->UpdateLifecycleToLayoutClean();
+    // Simulate that PaintInvalidator updates visual rect.
+    box.GetMutableForPainting().SetVisualRect(
+        LayoutRect(visual_rect.Location(), box.Size()));
+
+    EXPECT_EQ(
+        PaintInvalidationReason::kGeometry,
+        ComputePaintInvalidationReason(box, visual_rect, visual_rect.Location(),
+                                       box.VisualRect().Location()));
+  }
+
  private:
   void SetUp() override {
     RenderingTest::SetUp();
@@ -69,6 +114,132 @@
 
 INSTANTIATE_TEST_CASE_P(All, BoxPaintInvalidatorTest, ::testing::Bool());
 
+TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonPaintingNothing) {
+  ScopedSlimmingPaintV2ForTest spv2(true);
+
+  auto& target = *GetDocument().getElementById("target");
+  auto& box = *ToLayoutBox(target.GetLayoutObject());
+  // Remove border.
+  target.setAttribute(HTMLNames::classAttr, "");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  EXPECT_TRUE(box.PaintedOutputOfObjectHasNoEffectRegardlessOfSize());
+  LayoutRect visual_rect = box.VisualRect();
+  EXPECT_EQ(LayoutRect(0, 0, 50, 100), visual_rect);
+
+  // No geometry change.
+  EXPECT_EQ(
+      PaintInvalidationReason::kNone,
+      ComputePaintInvalidationReason(box, visual_rect, visual_rect.Location(),
+                                     visual_rect.Location()));
+
+  // Location change.
+  EXPECT_EQ(PaintInvalidationReason::kNone,
+            ComputePaintInvalidationReason(
+                box, visual_rect, visual_rect.Location() + LayoutSize(10, 20),
+                visual_rect.Location()));
+
+  // Visual rect size change.
+  LayoutRect old_visual_rect = visual_rect;
+  LayoutRect new_visual_rect = box.VisualRect();
+  target.setAttribute(HTMLNames::styleAttr, "width: 200px");
+  GetDocument().View()->UpdateLifecycleToLayoutClean();
+  // Simulate that PaintInvalidator updates visual rect.
+  box.GetMutableForPainting().SetVisualRect(
+      LayoutRect(visual_rect.Location(), box.Size()));
+
+  EXPECT_EQ(PaintInvalidationReason::kNone,
+            ComputePaintInvalidationReason(box, old_visual_rect,
+                                           old_visual_rect.Location(),
+                                           new_visual_rect.Location()));
+}
+
+TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonBasic) {
+  ScopedSlimmingPaintV2ForTest spv2(true);
+
+  auto& target = *GetDocument().getElementById("target");
+  auto& box = *ToLayoutBox(target.GetLayoutObject());
+  // Remove border.
+  target.setAttribute(HTMLNames::classAttr, "");
+  target.setAttribute(HTMLNames::styleAttr, "background: blue");
+  GetDocument().View()->UpdateAllLifecyclePhases();
+
+  LayoutRect visual_rect = box.VisualRect();
+  EXPECT_EQ(LayoutRect(0, 0, 50, 100), visual_rect);
+
+  // No geometry change.
+  EXPECT_EQ(
+      PaintInvalidationReason::kNone,
+      ComputePaintInvalidationReason(box, visual_rect, visual_rect.Location(),
+                                     visual_rect.Location()));
+
+  // Location change.
+  EXPECT_EQ(PaintInvalidationReason::kGeometry,
+            ComputePaintInvalidationReason(
+                box, visual_rect, visual_rect.Location() + LayoutSize(10, 20),
+                visual_rect.Location()));
+
+  // Visual rect size change.
+  LayoutRect old_visual_rect = visual_rect;
+  LayoutRect new_visual_rect = box.VisualRect();
+  target.setAttribute(HTMLNames::styleAttr, "background: blue; width: 200px");
+  GetDocument().View()->UpdateLifecycleToLayoutClean();
+  // Simulate that PaintInvalidator updates visual rect.
+  box.GetMutableForPainting().SetVisualRect(
+      LayoutRect(visual_rect.Location(), box.Size()));
+  EXPECT_EQ(PaintInvalidationReason::kIncremental,
+            ComputePaintInvalidationReason(box, old_visual_rect,
+                                           old_visual_rect.Location(),
+                                           new_visual_rect.Location()));
+
+  // Visual rect size change, with location in backing different from location
+  // of visual rect.
+  LayoutPoint fake_location = visual_rect.Location() + LayoutSize(10, 20);
+  EXPECT_EQ(PaintInvalidationReason::kGeometry,
+            ComputePaintInvalidationReason(box, old_visual_rect, fake_location,
+                                           fake_location));
+
+  // Should use the existing full paint invalidation reason regardless of
+  // geometry change.
+  box.SetShouldDoFullPaintInvalidation(PaintInvalidationReason::kStyle);
+  EXPECT_EQ(
+      PaintInvalidationReason::kStyle,
+      ComputePaintInvalidationReason(box, visual_rect, visual_rect.Location(),
+                                     visual_rect.Location()));
+  EXPECT_EQ(PaintInvalidationReason::kStyle,
+            ComputePaintInvalidationReason(
+                box, visual_rect, visual_rect.Location() + LayoutSize(10, 20),
+                visual_rect.Location()));
+}
+
+TEST_P(BoxPaintInvalidatorTest, ComputePaintInvalidationReasonOtherCases) {
+  ScopedSlimmingPaintV2ForTest spv2(true);
+  auto& target = *GetDocument().getElementById("target");
+
+  // The target initially has border.
+  ExpectFullPaintInvalidationOnGeometryChange("With border");
+
+  // Clear border.
+  target.setAttribute(HTMLNames::classAttr, "");
+  target.setAttribute(HTMLNames::styleAttr, "border-radius: 5px");
+  ExpectFullPaintInvalidationOnGeometryChange("With border-radius");
+
+  target.setAttribute(HTMLNames::styleAttr, "-webkit-mask: url(#)");
+  ExpectFullPaintInvalidationOnGeometryChange("With mask");
+
+  target.setAttribute(HTMLNames::styleAttr, "filter: blur(5px)");
+  ExpectFullPaintInvalidationOnGeometryChange("With filter");
+
+  target.setAttribute(HTMLNames::styleAttr, "outline: 2px solid blue");
+  ExpectFullPaintInvalidationOnGeometryChange("With outline");
+
+  target.setAttribute(HTMLNames::styleAttr, "box-shadow: inset 3px 2px");
+  ExpectFullPaintInvalidationOnGeometryChange("With box-shadow");
+
+  target.setAttribute(HTMLNames::styleAttr, "-webkit-appearance: button");
+  ExpectFullPaintInvalidationOnGeometryChange("With appearance");
+}
+
 TEST_P(BoxPaintInvalidatorTest, IncrementalInvalidationExpand) {
   GetDocument().View()->SetTracksPaintInvalidations(true);
   Element* target = GetDocument().getElementById("target");
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidator.h b/third_party/WebKit/Source/core/paint/PaintInvalidator.h
index e53b399..b6f0e1d 100644
--- a/third_party/WebKit/Source/core/paint/PaintInvalidator.h
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidator.h
@@ -12,7 +12,7 @@
 
 namespace blink {
 
-struct PaintInvalidatorContext {
+struct CORE_EXPORT PaintInvalidatorContext {
   USING_FAST_MALLOC(PaintInvalidatorContext);
 
  public:
diff --git a/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp b/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp
index f1f68fd..bf76883 100644
--- a/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp
+++ b/third_party/WebKit/Source/core/paint/TableSectionPainter.cpp
@@ -33,8 +33,10 @@
   LayoutUnit header_group_offset = table->BlockOffsetToFirstRepeatableHeader();
   // The header may have a pagination strut before it so we need to account for
   // that when establishing its position.
+  LayoutUnit strut_on_first_row;
   if (LayoutTableRow* row = layout_table_section_.FirstRow())
-    header_group_offset += row->PaginationStrut();
+    strut_on_first_row = row->PaginationStrut();
+  header_group_offset += strut_on_first_row;
   LayoutUnit offset_to_next_page =
       page_height - IntMod(header_group_offset, page_height);
   // Move paginationOffset to the top of the next page.
@@ -59,11 +61,16 @@
                paint_offset.Y() + total_height_of_rows);
 
   while (pagination_offset.Y() < bottom_bound) {
+    LayoutPoint nested_offset = pagination_offset;
+    LayoutUnit height_of_previous_headers =
+        table->RowOffsetFromRepeatingHeader() -
+        layout_table_section_.LogicalHeight() + strut_on_first_row;
+    nested_offset.Move(LayoutUnit(), height_of_previous_headers);
     if (item_to_paint == kPaintCollapsedBorders) {
-      PaintCollapsedSectionBorders(paint_info, pagination_offset,
+      PaintCollapsedSectionBorders(paint_info, nested_offset,
                                    current_border_value);
     } else {
-      PaintSection(paint_info, pagination_offset);
+      PaintSection(paint_info, nested_offset);
     }
     pagination_offset.Move(0, page_height.ToInt());
   }
diff --git a/third_party/WebKit/Source/core/testing/Internals.cpp b/third_party/WebKit/Source/core/testing/Internals.cpp
index 10f2767..cdc6f2a 100644
--- a/third_party/WebKit/Source/core/testing/Internals.cpp
+++ b/third_party/WebKit/Source/core/testing/Internals.cpp
@@ -1015,12 +1015,12 @@
   return marker->Description();
 }
 
-static WTF::Optional<DocumentMarker::MatchStatus> MatchStatusFrom(
+static WTF::Optional<TextMatchMarker::MatchStatus> MatchStatusFrom(
     const String& match_status) {
   if (EqualIgnoringASCIICase(match_status, "kActive"))
-    return DocumentMarker::MatchStatus::kActive;
+    return TextMatchMarker::MatchStatus::kActive;
   if (EqualIgnoringASCIICase(match_status, "kInactive"))
-    return DocumentMarker::MatchStatus::kInactive;
+    return TextMatchMarker::MatchStatus::kInactive;
   return WTF::nullopt;
 }
 
@@ -1031,7 +1031,7 @@
   if (!range->OwnerDocument().View())
     return;
 
-  WTF::Optional<DocumentMarker::MatchStatus> match_status_enum =
+  WTF::Optional<TextMatchMarker::MatchStatus> match_status_enum =
       MatchStatusFrom(match_status);
   if (!match_status_enum) {
     exception_state.ThrowDOMException(
diff --git a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
index aa3070dc..a1490260 100644
--- a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
+++ b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.cpp
@@ -33,12 +33,20 @@
 namespace blink {
 
 std::unique_ptr<WebActiveGestureAnimation>
+WebActiveGestureAnimation::CreateAtAnimationStart(
+    std::unique_ptr<WebGestureCurve> curve,
+    WebGestureCurveTarget* target) {
+  return WTF::WrapUnique(
+      new WebActiveGestureAnimation(std::move(curve), target, 0, true));
+}
+
+std::unique_ptr<WebActiveGestureAnimation>
 WebActiveGestureAnimation::CreateWithTimeOffset(
     std::unique_ptr<WebGestureCurve> curve,
     WebGestureCurveTarget* target,
     double start_time) {
-  return WTF::WrapUnique(
-      new WebActiveGestureAnimation(std::move(curve), target, start_time));
+  return WTF::WrapUnique(new WebActiveGestureAnimation(std::move(curve), target,
+                                                       start_time, false));
 }
 
 WebActiveGestureAnimation::~WebActiveGestureAnimation() {}
@@ -46,10 +54,18 @@
 WebActiveGestureAnimation::WebActiveGestureAnimation(
     std::unique_ptr<WebGestureCurve> curve,
     WebGestureCurveTarget* target,
-    double start_time)
-    : start_time_(start_time), curve_(std::move(curve)), target_(target) {}
+    double start_time,
+    bool waiting_for_first_tick)
+    : start_time_(start_time),
+      waiting_for_first_tick_(waiting_for_first_tick),
+      curve_(std::move(curve)),
+      target_(target) {}
 
 bool WebActiveGestureAnimation::Animate(double time) {
+  if (waiting_for_first_tick_) {
+    start_time_ = time;
+    waiting_for_first_tick_ = false;
+  }
   // All WebGestureCurves assume zero-based time, so we subtract
   // the animation start time before passing to the curve.
   return curve_->Apply(time - start_time_, target_);
diff --git a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.h b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.h
index e1adc588..45b29d4f 100644
--- a/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.h
+++ b/third_party/WebKit/Source/platform/exported/WebActiveGestureAnimation.h
@@ -46,6 +46,9 @@
   WTF_MAKE_NONCOPYABLE(WebActiveGestureAnimation);
 
  public:
+  static std::unique_ptr<WebActiveGestureAnimation> CreateAtAnimationStart(
+      std::unique_ptr<WebGestureCurve>,
+      WebGestureCurveTarget*);
   static std::unique_ptr<WebActiveGestureAnimation> CreateWithTimeOffset(
       std::unique_ptr<WebGestureCurve>,
       WebGestureCurveTarget*,
@@ -58,9 +61,11 @@
   // Assumes a valid WebGestureCurveTarget that outlives the animation.
   WebActiveGestureAnimation(std::unique_ptr<WebGestureCurve>,
                             WebGestureCurveTarget*,
-                            double start_time);
+                            double start_time,
+                            bool waiting_for_first_tick);
 
   double start_time_;
+  bool waiting_for_first_tick_;
   std::unique_ptr<WebGestureCurve> curve_;
   WebGestureCurveTarget* target_;
 };
diff --git a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemClient.h b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemClient.h
index 21f3d4c..4b10024 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/DisplayItemClient.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/DisplayItemClient.h
@@ -141,9 +141,11 @@
     }
 
     PaintInvalidationReason GetPaintInvalidationReason() const {
-      return value_ < kJustCreated
-                 ? static_cast<PaintInvalidationReason>(value_)
-                 : PaintInvalidationReason::kNone;
+      if (value_ == kJustCreated)
+        return PaintInvalidationReason::kAppeared;
+      if (value_ < kJustCreated)
+        return static_cast<PaintInvalidationReason>(value_);
+      return PaintInvalidationReason::kNone;
     }
 
     bool IsJustCreated() const { return value_ == kJustCreated; }
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
index f05ac20e..5bb67b2 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.cpp
@@ -696,7 +696,7 @@
     // This chunk is not cacheable, so always invalidate the whole chunk.
     AddRasterInvalidation(
         new_display_item_list_[new_chunk.begin_index].Client(), new_chunk,
-        infinite_float_rect);
+        infinite_float_rect, PaintInvalidationReason::kFull);
     return;
   }
 
@@ -736,39 +736,44 @@
   }
 
   // We reach here because the chunk is new.
-  AddRasterInvalidation(new_display_item_list_[new_chunk.begin_index].Client(),
-                        new_chunk, infinite_float_rect);
+  AddRasterInvalidation(new_chunk.id->client, new_chunk, infinite_float_rect,
+                        PaintInvalidationReason::kAppeared);
 }
 
 void PaintController::AddRasterInvalidation(const DisplayItemClient& client,
                                             PaintChunk& chunk,
-                                            const FloatRect& rect) {
+                                            const FloatRect& rect,
+                                            PaintInvalidationReason reason) {
   chunk.raster_invalidation_rects.push_back(rect);
   if (raster_invalidation_tracking_info_)
-    TrackRasterInvalidation(client, chunk, rect);
+    TrackRasterInvalidation(client, chunk, rect, reason);
 }
 
 void PaintController::TrackRasterInvalidation(const DisplayItemClient& client,
                                               PaintChunk& chunk,
-                                              const FloatRect& rect) {
+                                              const FloatRect& rect,
+                                              PaintInvalidationReason reason) {
   DCHECK(raster_invalidation_tracking_info_);
 
   RasterInvalidationInfo info;
   info.rect = EnclosingIntRect(rect);
   info.client = &client;
-  auto it =
-      raster_invalidation_tracking_info_->new_client_debug_names.find(&client);
-  if (it == raster_invalidation_tracking_info_->new_client_debug_names.end()) {
-    it = raster_invalidation_tracking_info_->old_client_debug_names.find(
-        &client);
-    // The client should be either in new list or in old list.
-    DCHECK(it !=
-           raster_invalidation_tracking_info_->old_client_debug_names.end());
-    info.reason = PaintInvalidationReason::kDisappeared;
+  if (reason == PaintInvalidationReason::kNone) {
+    // The client was validated by another PaintController, but not valid in
+    // this PaintController.
+    DCHECK(!ClientCacheIsValid(client));
+    info.reason = PaintInvalidationReason::kFull;
   } else {
-    info.reason = client.GetPaintInvalidationReason();
+    info.reason = reason;
   }
-  info.client_debug_name = it->value;
+
+  if (reason == PaintInvalidationReason::kDisappeared) {
+    info.client_debug_name =
+        raster_invalidation_tracking_info_->old_client_debug_names.at(&client);
+  } else {
+    info.client_debug_name = client.DebugName();
+  }
+
   raster_invalidation_tracking_info_->map.Add(&chunk).invalidations.push_back(
       info);
 }
@@ -778,63 +783,189 @@
     const PaintChunk& old_chunk) {
   DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
 
-  // TODO(wangxianzhu): Handle PaintInvalidationIncremental.
   // TODO(wangxianzhu): Optimize paint offset change.
 
-  HashSet<const DisplayItemClient*> invalidated_clients_in_old_chunk;
+  struct OldAndNewDisplayItems {
+    const DisplayItem* old_item = nullptr;
+    const DisplayItem* new_item = nullptr;
+  };
+  HashMap<const DisplayItemClient*, OldAndNewDisplayItems>
+      clients_to_invalidate;
+
   size_t highest_moved_to_index = 0;
+  // Find clients to invalidate the old visual rects from the old chunk.
   for (size_t old_index = old_chunk.begin_index;
        old_index < old_chunk.end_index; ++old_index) {
     const DisplayItem& old_item =
         current_paint_artifact_.GetDisplayItemList()[old_index];
-    const DisplayItemClient* client_to_invalidate = nullptr;
+    const DisplayItemClient* client_to_invalidate_old_visual_rect = nullptr;
 
     if (!old_item.HasValidClient()) {
+      // old_item has been moved into new_display_item_list_ as a cached item.
       size_t moved_to_index = items_moved_into_new_list_[old_index];
       if (new_display_item_list_[moved_to_index].DrawsContent()) {
         if (moved_to_index < new_chunk.begin_index ||
             moved_to_index >= new_chunk.end_index) {
           // The item has been moved into another chunk, so need to invalidate
-          // it in the old chunk.
+          // it in the chunk into which the item was moved.
           const auto& new_item = new_display_item_list_[moved_to_index];
-          client_to_invalidate = &new_item.Client();
-          // And invalidate in the new chunk into which the item was moved.
           PaintChunk& moved_to_chunk =
               new_paint_chunks_.FindChunkByDisplayItemIndex(moved_to_index);
-          AddRasterInvalidation(*client_to_invalidate, moved_to_chunk,
-                                FloatRect(new_item.VisualRect()));
+          AddRasterInvalidation(new_item.Client(), moved_to_chunk,
+                                FloatRect(new_item.VisualRect()),
+                                PaintInvalidationReason::kAppeared);
+          // And invalidate the old visual rect in this chunk.
+          client_to_invalidate_old_visual_rect = &new_item.Client();
         } else if (moved_to_index < highest_moved_to_index) {
           // The item has been moved behind other cached items, so need to
           // invalidate the area that is probably exposed by the item moved
           // earlier.
-          client_to_invalidate =
+          client_to_invalidate_old_visual_rect =
               &new_display_item_list_[moved_to_index].Client();
         } else {
           highest_moved_to_index = moved_to_index;
         }
       }
     } else if (old_item.DrawsContent()) {
-      client_to_invalidate = &old_item.Client();
+      // old_item has either changed or disappeared.
+      client_to_invalidate_old_visual_rect = &old_item.Client();
     }
-    if (client_to_invalidate &&
-        invalidated_clients_in_old_chunk.insert(client_to_invalidate)
-            .is_new_entry) {
-      AddRasterInvalidation(*client_to_invalidate, new_chunk,
-                            FloatRect(old_item.VisualRect()));
+
+    if (client_to_invalidate_old_visual_rect) {
+      clients_to_invalidate
+          .insert(client_to_invalidate_old_visual_rect, OldAndNewDisplayItems())
+          .stored_value->value.old_item = &old_item;
     }
   }
 
-  HashSet<const DisplayItemClient*> invalidated_clients_in_new_chunk;
+  // Find clients to invalidate the new visual rects from the new chunk.
   for (size_t new_index = new_chunk.begin_index;
        new_index < new_chunk.end_index; ++new_index) {
     const DisplayItem& new_item = new_display_item_list_[new_index];
-    if (new_item.DrawsContent() && !ClientCacheIsValid(new_item.Client()) &&
-        invalidated_clients_in_new_chunk.insert(&new_item.Client())
-            .is_new_entry) {
-      AddRasterInvalidation(new_item.Client(), new_chunk,
-                            FloatRect(new_item.VisualRect()));
+    if (new_item.DrawsContent() && !ClientCacheIsValid(new_item.Client())) {
+      clients_to_invalidate.insert(&new_item.Client(), OldAndNewDisplayItems())
+          .stored_value->value.new_item = &new_item;
     }
   }
+
+  for (const auto& item : clients_to_invalidate) {
+    GenerateRasterInvalidation(*item.key, new_chunk, item.value.old_item,
+                               item.value.new_item);
+  }
+}
+
+void PaintController::GenerateRasterInvalidation(
+    const DisplayItemClient& client,
+    PaintChunk& chunk,
+    const DisplayItem* old_item,
+    const DisplayItem* new_item) {
+  if (!new_item || new_item->VisualRect().IsEmpty()) {
+    if (old_item && !old_item->VisualRect().IsEmpty()) {
+      AddRasterInvalidation(client, chunk, FloatRect(old_item->VisualRect()),
+                            PaintInvalidationReason::kDisappeared);
+    }
+    return;
+  }
+
+  DCHECK(&client == &new_item->Client());
+  if (!old_item || old_item->VisualRect().IsEmpty()) {
+    AddRasterInvalidation(client, chunk, FloatRect(new_item->VisualRect()),
+                          PaintInvalidationReason::kAppeared);
+    return;
+  }
+
+  if (client.IsJustCreated()) {
+    // The old client has been deleted and the new client happens to be at the
+    // same address. They have no relationship.
+    AddRasterInvalidation(client, chunk, FloatRect(old_item->VisualRect()),
+                          PaintInvalidationReason::kDisappeared);
+    AddRasterInvalidation(client, chunk, FloatRect(new_item->VisualRect()),
+                          PaintInvalidationReason::kAppeared);
+    return;
+  }
+
+  if (client.GetPaintInvalidationReason() ==
+      PaintInvalidationReason::kIncremental) {
+    GenerateIncrementalRasterInvalidation(chunk, *old_item, *new_item);
+    return;
+  }
+
+  GenerateFullRasterInvalidation(chunk, *old_item, *new_item);
+}
+
+static FloatRect ComputeRightDelta(const FloatPoint& location,
+                                   const FloatSize& old_size,
+                                   const FloatSize& new_size) {
+  float delta = new_size.Width() - old_size.Width();
+  if (delta > 0) {
+    return FloatRect(location.X() + old_size.Width(), location.Y(), delta,
+                     new_size.Height());
+  }
+  if (delta < 0) {
+    return FloatRect(location.X() + new_size.Width(), location.Y(), -delta,
+                     old_size.Height());
+  }
+  return FloatRect();
+}
+
+static FloatRect ComputeBottomDelta(const FloatPoint& location,
+                                    const FloatSize& old_size,
+                                    const FloatSize& new_size) {
+  float delta = new_size.Height() - old_size.Height();
+  if (delta > 0) {
+    return FloatRect(location.X(), location.Y() + old_size.Height(),
+                     new_size.Width(), delta);
+  }
+  if (delta < 0) {
+    return FloatRect(location.X(), location.Y() + new_size.Height(),
+                     old_size.Width(), -delta);
+  }
+  return FloatRect();
+}
+
+void PaintController::GenerateIncrementalRasterInvalidation(
+    PaintChunk& chunk,
+    const DisplayItem& old_item,
+    const DisplayItem& new_item) {
+  DCHECK(&old_item.Client() == &new_item.Client());
+  FloatRect old_visual_rect(old_item.VisualRect());
+  FloatRect new_visual_rect(new_item.VisualRect());
+  DCHECK(old_visual_rect.Location() == new_visual_rect.Location());
+
+  FloatRect right_delta =
+      ComputeRightDelta(new_visual_rect.Location(), old_visual_rect.Size(),
+                        new_visual_rect.Size());
+  if (!right_delta.IsEmpty()) {
+    AddRasterInvalidation(new_item.Client(), chunk, right_delta,
+                          PaintInvalidationReason::kIncremental);
+  }
+
+  FloatRect bottom_delta =
+      ComputeBottomDelta(new_visual_rect.Location(), old_visual_rect.Size(),
+                         new_visual_rect.Size());
+  if (!bottom_delta.IsEmpty()) {
+    AddRasterInvalidation(new_item.Client(), chunk, bottom_delta,
+                          PaintInvalidationReason::kIncremental);
+  }
+}
+
+void PaintController::GenerateFullRasterInvalidation(
+    PaintChunk& chunk,
+    const DisplayItem& old_item,
+    const DisplayItem& new_item) {
+  DCHECK(&old_item.Client() == &new_item.Client());
+  FloatRect old_visual_rect(old_item.VisualRect());
+  FloatRect new_visual_rect(new_item.VisualRect());
+
+  if (!new_visual_rect.Contains(old_visual_rect)) {
+    AddRasterInvalidation(new_item.Client(), chunk, old_visual_rect,
+                          new_item.Client().GetPaintInvalidationReason());
+    if (old_visual_rect.Contains(new_visual_rect))
+      return;
+  }
+
+  AddRasterInvalidation(new_item.Client(), chunk, new_visual_rect,
+                        new_item.Client().GetPaintInvalidationReason());
 }
 
 void PaintController::ShowUnderInvalidationError(
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintController.h b/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
index d186158..285034b8 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintController.h
@@ -301,12 +301,25 @@
   void GenerateRasterInvalidations(PaintChunk& new_chunk);
   void GenerateRasterInvalidationsComparingChunks(PaintChunk& new_chunk,
                                                   const PaintChunk& old_chunk);
+  inline void GenerateRasterInvalidation(const DisplayItemClient&,
+                                         PaintChunk&,
+                                         const DisplayItem* old_item,
+                                         const DisplayItem* new_item);
+  inline void GenerateIncrementalRasterInvalidation(
+      PaintChunk&,
+      const DisplayItem& old_item,
+      const DisplayItem& new_item);
+  inline void GenerateFullRasterInvalidation(PaintChunk&,
+                                             const DisplayItem& old_item,
+                                             const DisplayItem& new_item);
   inline void AddRasterInvalidation(const DisplayItemClient&,
                                     PaintChunk&,
-                                    const FloatRect&);
+                                    const FloatRect&,
+                                    PaintInvalidationReason);
   void TrackRasterInvalidation(const DisplayItemClient&,
                                PaintChunk&,
-                               const FloatRect&);
+                               const FloatRect&,
+                               PaintInvalidationReason);
 
   // The following two methods are for checking under-invalidations
   // (when RuntimeEnabledFeatures::paintUnderInvalidationCheckingEnabled).
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
index 19ac3e00c..51e2f29 100644
--- a/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
+++ b/third_party/WebKit/Source/platform/graphics/paint/PaintControllerTest.cpp
@@ -224,10 +224,9 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
-    EXPECT_THAT(
-        GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-        UnorderedElementsAre(FloatRect(
-            100, 100, 200, 200)));  // |second| disappeared from the chunk.
+    EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+                // |second| disappeared from the chunk.
+                UnorderedElementsAre(FloatRect(100, 100, 200, 200)));
   }
 }
 
@@ -300,8 +299,8 @@
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
     EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-                UnorderedElementsAre(
-                    FloatRect(100, 100, 50, 200)));  // Bounds of |second|.
+                // Bounds of |second| (old and new are the same).
+                UnorderedElementsAre(FloatRect(100, 100, 50, 200)));
   }
 }
 
@@ -376,9 +375,8 @@
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
     EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-                UnorderedElementsAre(
-                    FloatRect(100, 100, 100, 100),    // Old bounds of |first|.
-                    FloatRect(100, 100, 100, 100)));  // New bounds of |first|.
+                // Bounds of |first| (old and new are the same).
+                UnorderedElementsAre(FloatRect(100, 100, 100, 100)));
     // No need to invalidate raster of |second|, because the client (|first|)
     // which swapped order with it has been invalidated.
   }
@@ -432,10 +430,9 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
-    EXPECT_THAT(
-        GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-        UnorderedElementsAre(FloatRect(
-            125, 100, 200, 50)));  // |third| newly appeared in the chunk.
+    EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+                // |third| newly appeared in the chunk.
+                UnorderedElementsAre(FloatRect(125, 100, 200, 50)));
   }
 }
 
@@ -506,12 +503,59 @@
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
     EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-                UnorderedElementsAre(
-                    FloatRect(100, 100, 50, 200),    // Old bounds of |second|.
-                    FloatRect(100, 100, 50, 200)));  // New bounds of |second|.
+                // Bounds of |second| (old and new are the same).
+                UnorderedElementsAre(FloatRect(100, 100, 50, 200)));
   }
 }
 
+TEST_P(PaintControllerTest, IncrementalRasterInvalidation) {
+  if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled())
+    return;
+
+  LayoutRect initial_rect(100, 100, 100, 100);
+  std::unique_ptr<FakeDisplayItemClient> clients[6];
+  for (auto& client : clients)
+    client = WTF::MakeUnique<FakeDisplayItemClient>("", initial_rect);
+  GraphicsContext context(GetPaintController());
+
+  GetPaintController().UpdateCurrentPaintChunkProperties(
+      &root_paint_chunk_id_, DefaultPaintChunkProperties());
+  for (auto& client : clients)
+    DrawRect(context, *client, kBackgroundDrawingType, FloatRect(initial_rect));
+  GetPaintController().CommitNewDisplayItems();
+
+  GetPaintController().UpdateCurrentPaintChunkProperties(
+      &root_paint_chunk_id_, DefaultPaintChunkProperties());
+  clients[0]->SetVisualRect(LayoutRect(100, 100, 150, 100));
+  clients[1]->SetVisualRect(LayoutRect(100, 100, 100, 150));
+  clients[2]->SetVisualRect(LayoutRect(100, 100, 150, 80));
+  clients[3]->SetVisualRect(LayoutRect(100, 100, 80, 150));
+  clients[4]->SetVisualRect(LayoutRect(100, 100, 150, 150));
+  clients[5]->SetVisualRect(LayoutRect(100, 100, 80, 80));
+  for (auto& client : clients) {
+    client->SetDisplayItemsUncached(PaintInvalidationReason::kIncremental);
+    DrawRect(context, *client, kBackgroundDrawingType,
+             FloatRect(client->VisualRect()));
+  }
+  GetPaintController().CommitNewDisplayItems();
+
+  EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
+  EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+              UnorderedElementsAre(FloatRect(200, 100, 50, 100),    // 0: right
+                                   FloatRect(100, 200, 100, 50),    // 1: bottom
+                                   FloatRect(200, 100, 50, 80),     // 2: right
+                                   FloatRect(100, 180, 100, 20),    // 2: bottom
+                                   FloatRect(180, 100, 20, 100),    // 3: right
+                                   FloatRect(100, 200, 80, 50),     // 3: bottom
+                                   FloatRect(200, 100, 50, 150),    // 4: right
+                                   FloatRect(100, 200, 150, 50),    // 4: bottom
+                                   FloatRect(180, 100, 20, 100),    // 5: right
+                                   FloatRect(100, 180, 100, 20)));  // 5: bottom
+
+  GetPaintController().UpdateCurrentPaintChunkProperties(
+      &root_paint_chunk_id_, DefaultPaintChunkProperties());
+}
+
 TEST_P(PaintControllerTest, UpdateAddFirstOverlap) {
   FakeDisplayItemClient first("first", LayoutRect(100, 100, 150, 150));
   FakeDisplayItemClient second("second", LayoutRect(200, 200, 50, 50));
@@ -538,15 +582,15 @@
 
   first.SetDisplayItemsUncached();
   second.SetDisplayItemsUncached();
-  second.SetVisualRect(LayoutRect(150, 150, 100, 100));
+  second.SetVisualRect(LayoutRect(150, 250, 100, 100));
   DrawRect(context, first, kBackgroundDrawingType,
            FloatRect(100, 100, 150, 150));
   DrawRect(context, first, kForegroundDrawingType,
            FloatRect(100, 100, 150, 150));
   DrawRect(context, second, kBackgroundDrawingType,
-           FloatRect(150, 150, 100, 100));
+           FloatRect(150, 250, 100, 100));
   DrawRect(context, second, kForegroundDrawingType,
-           FloatRect(150, 150, 100, 100));
+           FloatRect(150, 250, 100, 100));
   EXPECT_EQ(0, NumCachedNewItems());
   GetPaintController().CommitNewDisplayItems();
 
@@ -558,21 +602,22 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
-    EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-                UnorderedElementsAre(
-                    FloatRect(100, 100, 150,
-                              150),  // |first| newly appeared in the chunk.
-                    FloatRect(200, 200, 50, 50),      // Old bounds of |second|.
-                    FloatRect(150, 150, 100, 100)));  // New bounds of |second|.
+    EXPECT_THAT(
+        GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+        UnorderedElementsAre(
+            // |first| newly appeared in the chunk.
+            FloatRect(100, 100, 150, 150),
+            // Old and new bounds of |second|.
+            FloatRect(200, 200, 50, 50), FloatRect(150, 250, 100, 100)));
 
     GetPaintController().UpdateCurrentPaintChunkProperties(
         &root_paint_chunk_id_, DefaultPaintChunkProperties());
   }
 
   DrawRect(context, second, kBackgroundDrawingType,
-           FloatRect(150, 150, 100, 100));
+           FloatRect(150, 250, 100, 100));
   DrawRect(context, second, kForegroundDrawingType,
-           FloatRect(150, 150, 100, 100));
+           FloatRect(150, 250, 100, 100));
 
   EXPECT_EQ(2, NumCachedNewItems());
 #ifndef NDEBUG
@@ -589,10 +634,9 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
-    EXPECT_THAT(
-        GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-        UnorderedElementsAre(FloatRect(
-            100, 100, 150, 150)));  // |first| disappeared from the chunk.
+    EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+                // |first| disappeared from the chunk.
+                UnorderedElementsAre(FloatRect(100, 100, 150, 150)));
   }
 }
 
@@ -644,10 +688,10 @@
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
     EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
                 UnorderedElementsAre(
-                    FloatRect(100, 100, 150, 150),  // Old bounds of |first|.
-                    FloatRect(150, 150, 100, 100),  // New bounds of |first|.
-                    FloatRect(200, 200, 50,
-                              50)));  // |second| newly appeared in the chunk.
+                    // The bigger of old and new bounds of |first|.
+                    FloatRect(100, 100, 150, 150),
+                    // |second| newly appeared in the chunk.
+                    FloatRect(200, 200, 50, 50)));
 
     GetPaintController().UpdateCurrentPaintChunkProperties(
         &root_paint_chunk_id_, DefaultPaintChunkProperties());
@@ -671,10 +715,10 @@
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
     EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
                 UnorderedElementsAre(
-                    FloatRect(150, 150, 100, 100),  // Old bounds of |first|.
-                    FloatRect(100, 100, 150, 150),  // New bounds of |first|.
-                    FloatRect(200, 200, 50,
-                              50)));  // |second| disappeared from the chunk.
+                    // The bigger of old and new bounds of |first|.
+                    FloatRect(100, 100, 150, 150),
+                    // |second| disappeared from the chunk.
+                    FloatRect(200, 200, 50, 50)));
   }
 }
 
@@ -739,8 +783,8 @@
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
     EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-                UnorderedElementsAre(FloatRect(
-                    LayoutRect::InfiniteIntRect())));  // This is a new chunk.
+                // This is a new chunk.
+                UnorderedElementsAre(FloatRect(LayoutRect::InfiniteIntRect())));
 
     GetPaintController().UpdateCurrentPaintChunkProperties(
         &root_paint_chunk_id_, DefaultPaintChunkProperties());
@@ -774,12 +818,11 @@
 
     EXPECT_EQ(2u, GetPaintController().PaintChunks().size());
     EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-                UnorderedElementsAre(FloatRect(
-                    100, 100, 200,
-                    200)));  // |second| disappeared from the first chunk.
+                // |second| disappeared from the first chunk.
+                UnorderedElementsAre(FloatRect(100, 100, 200, 200)));
     EXPECT_THAT(GetPaintController().PaintChunks()[1].raster_invalidation_rects,
-                UnorderedElementsAre(FloatRect(
-                    LayoutRect::InfiniteIntRect())));  // This is a new chunk.
+                // This is a new chunk.
+                UnorderedElementsAre(FloatRect(LayoutRect::InfiniteIntRect())));
   } else {
     EXPECT_DISPLAY_LIST(
         GetPaintController().GetDisplayItemList(), 4,
@@ -937,10 +980,10 @@
     EXPECT_THAT(
         GetPaintController().PaintChunks()[0].raster_invalidation_rects,
         UnorderedElementsAre(
-            FloatRect(100, 200, 100, 100),   // Bounds of |container2| which was
-                                             // moved behind |container1|.
-            FloatRect(100, 200, 50, 200)));  // Bounds of |content2| which was
-                                             // moved along with |container2|.
+            // Bounds of |container2| which was moved behind |container1|.
+            FloatRect(100, 200, 100, 100),
+            // Bounds of |content2| which was moved along with |container2|.
+            FloatRect(100, 200, 50, 200)));
   }
 }
 
@@ -1026,12 +1069,12 @@
     EXPECT_THAT(
         GetPaintController().PaintChunks()[0].raster_invalidation_rects,
         UnorderedElementsAre(
-            FloatRect(100, 100, 100, 100),   // Old bounds of |container1|.
-            FloatRect(100, 100, 100, 100),   // New bounds of |container1|.
-            FloatRect(100, 200, 100, 100),   // Bounds of |container2| which was
-                                             // moved behind |container1|.
-            FloatRect(100, 200, 50, 200)));  // Bounds of |content2| which was
-                                             // moved along with |container2|.
+            // Bounds of |container1| (old and new are the same).
+            FloatRect(100, 100, 100, 100),
+            // Bounds of |container2| which was moved behind |container1|.
+            FloatRect(100, 200, 100, 100),
+            // Bounds of |content2| which was moved along with |container2|.
+            FloatRect(100, 200, 50, 200)));
   }
 }
 
@@ -1594,11 +1637,8 @@
     EXPECT_THAT(GetPaintController().PaintChunks()[1].raster_invalidation_rects,
                 UnorderedElementsAre());
     // |container1| is invalidated.
-    EXPECT_THAT(
-        GetPaintController().PaintChunks()[2].raster_invalidation_rects,
-        UnorderedElementsAre(
-            FloatRect(100, 100, 100, 100),    // Old bounds of |container1|.
-            FloatRect(100, 100, 100, 100)));  // New bounds of |container1|.
+    EXPECT_THAT(GetPaintController().PaintChunks()[2].raster_invalidation_rects,
+                UnorderedElementsAre(FloatRect(100, 100, 100, 100)));
   }
 
 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
@@ -1684,11 +1724,9 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
-    EXPECT_THAT(
-        GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-        UnorderedElementsAre(
-            FloatRect(100, 100, 100, 100),    // Old bounds of |content|.
-            FloatRect(100, 100, 100, 100)));  // New bounds of |content|.
+    EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+                // Bounds of |content| (old and new are the same);
+                UnorderedElementsAre(FloatRect(100, 100, 100, 100)));
 
     GetPaintController().UpdateCurrentPaintChunkProperties(
         &root_paint_chunk_id_, DefaultPaintChunkProperties());
@@ -1722,13 +1760,12 @@
 
   if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
     EXPECT_EQ(1u, GetPaintController().PaintChunks().size());
-    EXPECT_THAT(
-        GetPaintController().PaintChunks()[0].raster_invalidation_rects,
-        UnorderedElementsAre(
-            FloatRect(100, 100, 200, 200),    // Old bounds of |multicol|.
-            FloatRect(100, 100, 200, 200),    // New bounds of |multicol|.
-            FloatRect(100, 100, 100, 100),    // Old bounds of |content|.
-            FloatRect(100, 100, 100, 100)));  // New bounds of |content|.
+    EXPECT_THAT(GetPaintController().PaintChunks()[0].raster_invalidation_rects,
+                UnorderedElementsAre(
+                    // Bounds of |multicol| (old and new are the same);
+                    FloatRect(100, 100, 200, 200),
+                    // Bounds of |content| (old and new are the same);
+                    FloatRect(100, 100, 100, 100)));
   }
 }
 
diff --git a/third_party/WebKit/Source/web/TextFinder.cpp b/third_party/WebKit/Source/web/TextFinder.cpp
index 3dbb692..7032e85e 100644
--- a/third_party/WebKit/Source/web/TextFinder.cpp
+++ b/third_party/WebKit/Source/web/TextFinder.cpp
@@ -403,8 +403,8 @@
 
     OwnerFrame().GetFrame()->GetDocument()->Markers().AddTextMatchMarker(
         EphemeralRange(result_range),
-        found_active_match ? DocumentMarker::MatchStatus::kActive
-                           : DocumentMarker::MatchStatus::kInactive);
+        found_active_match ? TextMatchMarker::MatchStatus::kActive
+                           : TextMatchMarker::MatchStatus::kInactive);
 
     find_matches_cache_.push_back(
         FindMatch(result_range, last_match_count_ + match_count));
diff --git a/third_party/WebKit/Source/web/WebViewImpl.cpp b/third_party/WebKit/Source/web/WebViewImpl.cpp
index e1f737d7..b802dab 100644
--- a/third_party/WebKit/Source/web/WebViewImpl.cpp
+++ b/third_party/WebKit/Source/web/WebViewImpl.cpp
@@ -698,8 +698,8 @@
                             event.data.fling_start.velocity_y),
               WebSize());
       DCHECK(fling_curve);
-      gesture_animation_ = WebActiveGestureAnimation::CreateWithTimeOffset(
-          std::move(fling_curve), this, event.TimeStampSeconds());
+      gesture_animation_ = WebActiveGestureAnimation::CreateAtAnimationStart(
+          std::move(fling_curve), this);
       MainFrameImpl()->FrameWidget()->ScheduleAnimation();
       event_result = WebInputEventResult::kHandledSystem;
 
diff --git a/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp b/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp
index 353fb56..fb58878c 100644
--- a/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp
+++ b/third_party/WebKit/Source/web/tests/RootScrollerTest.cpp
@@ -973,6 +973,78 @@
   MainFrameView()->UpdateAllLifecyclePhases();
 }
 
+// Makes sure that when an iframe becomes the effective root scroller, its
+// FrameView stops sizing layout to the frame rect and uses its parent's layout
+// size instead. This allows matching the layout size semantics of the root
+// FrameView since its layout size can differ from the frame rect due to
+// resizes by the URL bar.
+TEST_F(RootScrollerTest, IFrameRootScrollerGetsNonFixedLayoutSize) {
+  Initialize("root-scroller-iframe.html");
+  MainFrameView()->UpdateAllLifecyclePhases();
+
+  Document* document = MainFrame()->GetDocument();
+  HTMLFrameOwnerElement* iframe = ToHTMLFrameOwnerElement(
+      MainFrame()->GetDocument()->getElementById("iframe"));
+  LocalFrameView* iframe_view = ToLocalFrame(iframe->ContentFrame())->View();
+
+  ASSERT_EQ(IntSize(400, 400), iframe_view->GetLayoutSize());
+  ASSERT_EQ(IntSize(400, 400), iframe_view->Size());
+  ASSERT_TRUE(iframe_view->LayoutSizeFixedToFrameSize());
+
+  // Make the iframe the rootscroller. This should cause the iframe's layout
+  // size to be manually controlled.
+  {
+    document->setRootScroller(iframe);
+    EXPECT_FALSE(iframe_view->LayoutSizeFixedToFrameSize());
+    MainFrameView()->UpdateAllLifecyclePhases();
+    EXPECT_EQ(IntSize(400, 400), iframe_view->GetLayoutSize());
+    EXPECT_EQ(IntSize(400, 400), iframe_view->Size());
+  }
+
+  // Hide the URL bar, the iframe's frame rect should expand but the layout
+  // size should remain the same.
+  {
+    GetWebView()->ResizeWithBrowserControls(IntSize(400, 450), 50, false);
+    MainFrameView()->UpdateAllLifecyclePhases();
+    EXPECT_EQ(IntSize(400, 400), iframe_view->GetLayoutSize());
+    EXPECT_EQ(IntSize(400, 450), iframe_view->Size());
+  }
+
+  // Simulate a rotation. This time the layout size should reflect the resize.
+  {
+    GetWebView()->ResizeWithBrowserControls(IntSize(450, 400), 50, false);
+    MainFrameView()->UpdateAllLifecyclePhases();
+    EXPECT_EQ(IntSize(450, 350), iframe_view->GetLayoutSize());
+    EXPECT_EQ(IntSize(450, 400), iframe_view->Size());
+
+    // "Un-rotate" for following tests.
+    GetWebView()->ResizeWithBrowserControls(IntSize(400, 450), 50, false);
+    MainFrameView()->UpdateAllLifecyclePhases();
+  }
+
+  // Show the URL bar again. The frame rect should match the viewport.
+  {
+    GetWebView()->ResizeWithBrowserControls(IntSize(400, 400), 50, true);
+    MainFrameView()->UpdateAllLifecyclePhases();
+    EXPECT_EQ(IntSize(400, 400), iframe_view->GetLayoutSize());
+    EXPECT_EQ(IntSize(400, 400), iframe_view->Size());
+  }
+
+  // Hide the URL bar and reset the rootScroller. The iframe should go back to
+  // tracking layout size by frame rect.
+  {
+    GetWebView()->ResizeWithBrowserControls(IntSize(400, 450), 50, false);
+    MainFrameView()->UpdateAllLifecyclePhases();
+    EXPECT_EQ(IntSize(400, 400), iframe_view->GetLayoutSize());
+    EXPECT_EQ(IntSize(400, 450), iframe_view->Size());
+    document->setRootScroller(nullptr);
+    EXPECT_TRUE(iframe_view->LayoutSizeFixedToFrameSize());
+    MainFrameView()->UpdateAllLifecyclePhases();
+    EXPECT_EQ(IntSize(400, 400), iframe_view->GetLayoutSize());
+    EXPECT_EQ(IntSize(400, 400), iframe_view->Size());
+  }
+}
+
 // Ensure that removing the root scroller element causes an update to the RFV's
 // layout viewport immediately since old layout viewport is now part of a
 // detached layout hierarchy.
diff --git a/third_party/openvr/BUILD.gn b/third_party/openvr/BUILD.gn
new file mode 100644
index 0000000..6df6499
--- /dev/null
+++ b/third_party/openvr/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright 2017 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.
+
+loadable_module("openvr") {
+  output_name = "openvr_api"
+
+  # Some ascii versions of Windows APIs are used in this code.
+  configs -= [ "//build/config/win:unicode" ]
+
+  # This code can be built using internal OpenVR functionality, but the internal
+  # dependencies aren't available to us.
+  defines = [ "VR_API_PUBLIC" ]
+
+  sources = [
+    "src/src/jsoncpp.cpp",
+    "src/src/openvr_api_public.cpp",
+    "src/src/vrcommon/dirtools_public.cpp",
+    "src/src/vrcommon/envvartools_public.cpp",
+    "src/src/vrcommon/hmderrors_public.cpp",
+    "src/src/vrcommon/pathtools_public.cpp",
+    "src/src/vrcommon/sharedlibtools_public.cpp",
+    "src/src/vrcommon/strtools_public.cpp",
+    "src/src/vrcommon/vrpathregistry_public.cpp",
+  ]
+
+  include_dirs = [
+    "src/headers",
+    "src/src",
+    "src/src/json",
+    "src/src/vrcommon",
+  ]
+}
diff --git a/third_party/openvr/DEPS b/third_party/openvr/DEPS
new file mode 100644
index 0000000..2a8f720
--- /dev/null
+++ b/third_party/openvr/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+json",
+]
diff --git a/third_party/openvr/OWNERS b/third_party/openvr/OWNERS
new file mode 100644
index 0000000..87d9ce0
--- /dev/null
+++ b/third_party/openvr/OWNERS
@@ -0,0 +1,2 @@
+bajones@chromium.org
+ddorwin@chromium.org
diff --git a/third_party/openvr/README.chromium b/third_party/openvr/README.chromium
new file mode 100644
index 0000000..936f6cb
--- /dev/null
+++ b/third_party/openvr/README.chromium
@@ -0,0 +1,21 @@
+Name: OpenVR SDK
+Short Name: OpenVR
+URL: https://github.com/ValveSoftware/openvr
+Version: 1.0.4
+Date: 2 Feb 2017
+Revision: 7fa6470f2972970859f2395f1390f6d87d4b0fc3
+License: MIT
+License File: src\LICENSE
+Security Critical: yes
+
+Description:
+The OpenVR API supports HTC Vive and other headsets for VR.
+
+Local Modifications:
+Only contains a subset of the git repo necessary to build Chromium.
+
+Copy the correct files with these commands:
+copy %openvrsdk%\README.md %chromium%\src\third_party\openvr\src
+copy %openvrsdk%\LICENSE %chromium%\src\third_party\openvr\src
+xcopy /S %openvrsdk%\src %chromium%\src\third_party\openvr\src\src
+xcopy /S %openvrsdk%\headers %chromium%\src\third_party\openvr\src\headers
diff --git a/third_party/openvr/src/LICENSE b/third_party/openvr/src/LICENSE
new file mode 100644
index 0000000..ee83337
--- /dev/null
+++ b/third_party/openvr/src/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2015, Valve Corporation
+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. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT HOLDER 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.
diff --git a/third_party/openvr/src/README.md b/third_party/openvr/src/README.md
new file mode 100644
index 0000000..5976d622
--- /dev/null
+++ b/third_party/openvr/src/README.md
@@ -0,0 +1,13 @@
+OpenVR SDK
+---
+
+OpenVR is an API and runtime that allows access to VR hardware from multiple 
+vendors without requiring that applications have specific knowledge of the 
+hardware they are targeting. This repository is an SDK that contains the API 
+and samples. The runtime is under SteamVR in Tools on Steam. 
+
+### Documentation
+
+Documentation for the API is available on the [Github Wiki](https://github.com/ValveSoftware/openvr/wiki/API-Documentation)
+
+More information on OpenVR and SteamVR can be found on http://steamvr.com
diff --git a/third_party/openvr/src/headers/openvr.h b/third_party/openvr/src/headers/openvr.h
new file mode 100644
index 0000000..19f2a0b
--- /dev/null
+++ b/third_party/openvr/src/headers/openvr.h
@@ -0,0 +1,3643 @@
+#pragma once
+
+// openvr.h
+//========= Copyright Valve Corporation ============//
+// Dynamically generated file. Do not modify this file directly.
+
+#ifndef _OPENVR_API
+#define _OPENVR_API
+
+#include <stdint.h>
+
+
+
+// vrtypes.h
+#ifndef _INCLUDE_VRTYPES_H
+#define _INCLUDE_VRTYPES_H
+
+// Forward declarations to avoid requiring vulkan.h
+struct VkDevice_T;
+struct VkPhysicalDevice_T;
+struct VkInstance_T;
+struct VkQueue_T;
+
+// Forward declarations to avoid requiring d3d12.h
+struct ID3D12Resource;
+struct ID3D12CommandQueue;
+
+namespace vr
+{
+
+#if defined(__linux__) || defined(__APPLE__) 
+	// The 32-bit version of gcc has the alignment requirement for uint64 and double set to
+	// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned.
+	// The 64-bit version of gcc has the alignment requirement for these types set to
+	// 8 meaning that unless we use #pragma pack(4) our structures will get bigger.
+	// The 64-bit structure packing has to match the 32-bit structure packing for each platform.
+	#pragma pack( push, 4 )
+#else
+	#pragma pack( push, 8 )
+#endif
+
+typedef void* glSharedTextureHandle_t;
+typedef int32_t glInt_t;
+typedef uint32_t glUInt_t;
+
+// right-handed system
+// +y is up
+// +x is to the right
+// -z is going away from you
+// Distance unit is  meters
+struct HmdMatrix34_t
+{
+	float m[3][4];
+};
+
+struct HmdMatrix44_t
+{
+	float m[4][4];
+};
+
+struct HmdVector3_t
+{
+	float v[3];
+};
+
+struct HmdVector4_t
+{
+	float v[4];
+};
+
+struct HmdVector3d_t
+{
+	double v[3];
+};
+
+struct HmdVector2_t
+{
+	float v[2];
+};
+
+struct HmdQuaternion_t
+{
+	double w, x, y, z;
+};
+
+struct HmdColor_t
+{
+	float r, g, b, a;
+};
+
+struct HmdQuad_t
+{
+	HmdVector3_t vCorners[ 4 ];
+};
+
+struct HmdRect2_t
+{
+	HmdVector2_t vTopLeft;
+	HmdVector2_t vBottomRight;
+};
+
+/** Used to return the post-distortion UVs for each color channel. 
+* UVs range from 0 to 1 with 0,0 in the upper left corner of the 
+* source render target. The 0,0 to 1,1 range covers a single eye. */
+struct DistortionCoordinates_t
+{
+	float rfRed[2];
+	float rfGreen[2];
+	float rfBlue[2];
+};
+
+enum EVREye
+{
+	Eye_Left = 0,
+	Eye_Right = 1
+};
+
+enum ETextureType
+{
+	TextureType_DirectX = 0, // Handle is an ID3D11Texture
+	TextureType_OpenGL = 1,  // Handle is an OpenGL texture name or an OpenGL render buffer name, depending on submit flags
+	TextureType_Vulkan = 2, // Handle is a pointer to a VRVulkanTextureData_t structure
+	TextureType_IOSurface = 3, // Handle is a macOS cross-process-sharable IOSurface
+	TextureType_DirectX12 = 4, // Handle is a pointer to a D3D12TextureData_t structure
+};
+
+enum EColorSpace
+{
+	ColorSpace_Auto = 0,	// Assumes 'gamma' for 8-bit per component formats, otherwise 'linear'.  This mirrors the DXGI formats which have _SRGB variants.
+	ColorSpace_Gamma = 1,	// Texture data can be displayed directly on the display without any conversion (a.k.a. display native format).
+	ColorSpace_Linear = 2,	// Same as gamma but has been converted to a linear representation using DXGI's sRGB conversion algorithm.
+};
+
+struct Texture_t
+{
+	void* handle; // See ETextureType definition above
+	ETextureType eType;
+	EColorSpace eColorSpace;
+};
+
+// Handle to a shared texture (HANDLE on Windows obtained using OpenSharedResource).
+typedef uint64_t SharedTextureHandle_t;
+#define INVALID_SHARED_TEXTURE_HANDLE	((vr::SharedTextureHandle_t)0)
+
+enum ETrackingResult
+{
+	TrackingResult_Uninitialized			= 1,
+
+	TrackingResult_Calibrating_InProgress	= 100,
+	TrackingResult_Calibrating_OutOfRange	= 101,
+
+	TrackingResult_Running_OK				= 200,
+	TrackingResult_Running_OutOfRange		= 201,
+};
+
+static const uint32_t k_unMaxDriverDebugResponseSize = 32768;
+
+/** Used to pass device IDs to API calls */
+typedef uint32_t TrackedDeviceIndex_t;
+static const uint32_t k_unTrackedDeviceIndex_Hmd = 0;
+static const uint32_t k_unMaxTrackedDeviceCount = 16;
+static const uint32_t k_unTrackedDeviceIndexOther = 0xFFFFFFFE;
+static const uint32_t k_unTrackedDeviceIndexInvalid = 0xFFFFFFFF;
+
+/** Describes what kind of object is being tracked at a given ID */
+enum ETrackedDeviceClass
+{
+	TrackedDeviceClass_Invalid = 0,				// the ID was not valid.
+	TrackedDeviceClass_HMD = 1,					// Head-Mounted Displays
+	TrackedDeviceClass_Controller = 2,			// Tracked controllers
+	TrackedDeviceClass_GenericTracker = 3,		// Generic trackers, similar to controllers
+	TrackedDeviceClass_TrackingReference = 4,	// Camera and base stations that serve as tracking reference points
+};
+
+
+/** Describes what specific role associated with a tracked device */
+enum ETrackedControllerRole
+{
+	TrackedControllerRole_Invalid = 0,					// Invalid value for controller type
+	TrackedControllerRole_LeftHand = 1,					// Tracked device associated with the left hand
+	TrackedControllerRole_RightHand = 2,				// Tracked device associated with the right hand
+};
+
+
+/** describes a single pose for a tracked object */
+struct TrackedDevicePose_t
+{
+	HmdMatrix34_t mDeviceToAbsoluteTracking;
+	HmdVector3_t vVelocity;				// velocity in tracker space in m/s
+	HmdVector3_t vAngularVelocity;		// angular velocity in radians/s (?)
+	ETrackingResult eTrackingResult;
+	bool bPoseIsValid;
+
+	// This indicates that there is a device connected for this spot in the pose array.
+	// It could go from true to false if the user unplugs the device.
+	bool bDeviceIsConnected;
+};
+
+/** Identifies which style of tracking origin the application wants to use
+* for the poses it is requesting */
+enum ETrackingUniverseOrigin
+{
+	TrackingUniverseSeated = 0,		// Poses are provided relative to the seated zero pose
+	TrackingUniverseStanding = 1,	// Poses are provided relative to the safe bounds configured by the user
+	TrackingUniverseRawAndUncalibrated = 2,	// Poses are provided in the coordinate system defined by the driver.  It has Y up and is unified for devices of the same driver. You usually don't want this one.
+};
+
+// Refers to a single container of properties
+typedef uint64_t PropertyContainerHandle_t;
+typedef uint32_t PropertyTypeTag_t;
+
+static const PropertyContainerHandle_t k_ulInvalidPropertyContainer = 0;
+static const PropertyTypeTag_t k_unInvalidPropertyTag = 0;
+
+// Use these tags to set/get common types as struct properties
+static const PropertyTypeTag_t k_unFloatPropertyTag = 1;
+static const PropertyTypeTag_t k_unInt32PropertyTag = 2;
+static const PropertyTypeTag_t k_unUint64PropertyTag = 3;
+static const PropertyTypeTag_t k_unBoolPropertyTag = 4;
+static const PropertyTypeTag_t k_unStringPropertyTag = 5;
+
+static const PropertyTypeTag_t k_unHmdMatrix34PropertyTag = 20;
+static const PropertyTypeTag_t k_unHmdMatrix44PropertyTag = 21;
+static const PropertyTypeTag_t k_unHmdVector3PropertyTag = 22;
+static const PropertyTypeTag_t k_unHmdVector4PropertyTag = 23;
+
+static const PropertyTypeTag_t k_unHiddenAreaPropertyTag = 30;
+
+static const PropertyTypeTag_t k_unOpenVRInternalReserved_Start = 1000;
+static const PropertyTypeTag_t k_unOpenVRInternalReserved_End = 10000;
+
+
+/** Each entry in this enum represents a property that can be retrieved about a
+* tracked device. Many fields are only valid for one ETrackedDeviceClass. */
+enum ETrackedDeviceProperty
+{
+	Prop_Invalid								= 0,
+
+	// general properties that apply to all device classes
+	Prop_TrackingSystemName_String				= 1000,
+	Prop_ModelNumber_String						= 1001,
+	Prop_SerialNumber_String					= 1002,
+	Prop_RenderModelName_String					= 1003,
+	Prop_WillDriftInYaw_Bool					= 1004,
+	Prop_ManufacturerName_String				= 1005,
+	Prop_TrackingFirmwareVersion_String			= 1006,
+	Prop_HardwareRevision_String				= 1007,
+	Prop_AllWirelessDongleDescriptions_String	= 1008,
+	Prop_ConnectedWirelessDongle_String			= 1009,
+	Prop_DeviceIsWireless_Bool					= 1010,
+	Prop_DeviceIsCharging_Bool					= 1011,
+	Prop_DeviceBatteryPercentage_Float			= 1012, // 0 is empty, 1 is full
+	Prop_StatusDisplayTransform_Matrix34		= 1013,
+	Prop_Firmware_UpdateAvailable_Bool			= 1014,
+	Prop_Firmware_ManualUpdate_Bool				= 1015,
+	Prop_Firmware_ManualUpdateURL_String		= 1016,
+	Prop_HardwareRevision_Uint64				= 1017,
+	Prop_FirmwareVersion_Uint64					= 1018,
+	Prop_FPGAVersion_Uint64						= 1019,
+	Prop_VRCVersion_Uint64						= 1020,
+	Prop_RadioVersion_Uint64					= 1021,
+	Prop_DongleVersion_Uint64					= 1022,
+	Prop_BlockServerShutdown_Bool				= 1023,
+	Prop_CanUnifyCoordinateSystemWithHmd_Bool	= 1024,
+	Prop_ContainsProximitySensor_Bool			= 1025,
+	Prop_DeviceProvidesBatteryStatus_Bool		= 1026,
+	Prop_DeviceCanPowerOff_Bool					= 1027,
+	Prop_Firmware_ProgrammingTarget_String		= 1028,
+	Prop_DeviceClass_Int32						= 1029,
+	Prop_HasCamera_Bool							= 1030,
+	Prop_DriverVersion_String                   = 1031,
+	Prop_Firmware_ForceUpdateRequired_Bool      = 1032,
+	Prop_ViveSystemButtonFixRequired_Bool		= 1033,
+	Prop_ParentDriver_Uint64					= 1034,
+
+
+	// Properties that are unique to TrackedDeviceClass_HMD
+	Prop_ReportsTimeSinceVSync_Bool				= 2000,
+	Prop_SecondsFromVsyncToPhotons_Float		= 2001,
+	Prop_DisplayFrequency_Float					= 2002,
+	Prop_UserIpdMeters_Float					= 2003,
+	Prop_CurrentUniverseId_Uint64				= 2004, 
+	Prop_PreviousUniverseId_Uint64				= 2005, 
+	Prop_DisplayFirmwareVersion_Uint64			= 2006,
+	Prop_IsOnDesktop_Bool						= 2007,
+	Prop_DisplayMCType_Int32					= 2008,
+	Prop_DisplayMCOffset_Float					= 2009,
+	Prop_DisplayMCScale_Float					= 2010,
+	Prop_EdidVendorID_Int32						= 2011,
+	Prop_DisplayMCImageLeft_String              = 2012,
+	Prop_DisplayMCImageRight_String             = 2013,
+	Prop_DisplayGCBlackClamp_Float				= 2014,
+	Prop_EdidProductID_Int32					= 2015,
+	Prop_CameraToHeadTransform_Matrix34			= 2016,
+	Prop_DisplayGCType_Int32					= 2017,
+	Prop_DisplayGCOffset_Float					= 2018,
+	Prop_DisplayGCScale_Float					= 2019,
+	Prop_DisplayGCPrescale_Float				= 2020,
+	Prop_DisplayGCImage_String					= 2021,
+	Prop_LensCenterLeftU_Float					= 2022,
+	Prop_LensCenterLeftV_Float					= 2023,
+	Prop_LensCenterRightU_Float					= 2024,
+	Prop_LensCenterRightV_Float					= 2025,
+	Prop_UserHeadToEyeDepthMeters_Float			= 2026,
+	Prop_CameraFirmwareVersion_Uint64			= 2027,
+	Prop_CameraFirmwareDescription_String		= 2028,
+	Prop_DisplayFPGAVersion_Uint64				= 2029,
+	Prop_DisplayBootloaderVersion_Uint64		= 2030,
+	Prop_DisplayHardwareVersion_Uint64			= 2031,
+	Prop_AudioFirmwareVersion_Uint64			= 2032,
+	Prop_CameraCompatibilityMode_Int32			= 2033,
+	Prop_ScreenshotHorizontalFieldOfViewDegrees_Float = 2034,
+	Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035,
+	Prop_DisplaySuppressed_Bool					= 2036,
+	Prop_DisplayAllowNightMode_Bool				= 2037,
+	Prop_DisplayMCImageWidth_Int32				= 2038,
+	Prop_DisplayMCImageHeight_Int32				= 2039,
+	Prop_DisplayMCImageNumChannels_Int32		= 2040,
+	Prop_DisplayMCImageData_Binary				= 2041,
+	Prop_UsesDriverDirectMode_Bool				= 2042,
+
+	// Properties that are unique to TrackedDeviceClass_Controller
+	Prop_AttachedDeviceId_String				= 3000,
+	Prop_SupportedButtons_Uint64				= 3001,
+	Prop_Axis0Type_Int32						= 3002, // Return value is of type EVRControllerAxisType
+	Prop_Axis1Type_Int32						= 3003, // Return value is of type EVRControllerAxisType
+	Prop_Axis2Type_Int32						= 3004, // Return value is of type EVRControllerAxisType
+	Prop_Axis3Type_Int32						= 3005, // Return value is of type EVRControllerAxisType
+	Prop_Axis4Type_Int32						= 3006, // Return value is of type EVRControllerAxisType
+	Prop_ControllerRoleHint_Int32				= 3007, // Return value is of type ETrackedControllerRole
+
+	// Properties that are unique to TrackedDeviceClass_TrackingReference
+	Prop_FieldOfViewLeftDegrees_Float			= 4000,
+	Prop_FieldOfViewRightDegrees_Float			= 4001,
+	Prop_FieldOfViewTopDegrees_Float			= 4002,
+	Prop_FieldOfViewBottomDegrees_Float			= 4003,
+	Prop_TrackingRangeMinimumMeters_Float		= 4004,
+	Prop_TrackingRangeMaximumMeters_Float		= 4005,
+	Prop_ModeLabel_String						= 4006,
+
+	// Properties that are used for user interface like icons names
+	Prop_IconPathName_String						= 5000, // usually a directory named "icons"
+	Prop_NamedIconPathDeviceOff_String				= 5001, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceSearching_String		= 5002, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceSearchingAlert_String	= 5003, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceReady_String			= 5004, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceReadyAlert_String		= 5005, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceNotReady_String			= 5006, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceStandby_String			= 5007, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceAlertLow_String			= 5008, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+
+	// Properties that are used by helpers, but are opaque to applications
+	Prop_DisplayHiddenArea_Binary_Start				= 5100,
+	Prop_DisplayHiddenArea_Binary_End				= 5150,
+
+	// Properties that are unique to drivers
+	Prop_UserConfigPath_String					= 6000,
+	Prop_InstallPath_String						= 6001,
+
+	// Vendors are free to expose private debug data in this reserved region
+	Prop_VendorSpecific_Reserved_Start			= 10000,
+	Prop_VendorSpecific_Reserved_End			= 10999,
+};
+
+/** No string property will ever be longer than this length */
+static const uint32_t k_unMaxPropertyStringSize = 32 * 1024;
+
+/** Used to return errors that occur when reading properties. */
+enum ETrackedPropertyError
+{
+	TrackedProp_Success						= 0,
+	TrackedProp_WrongDataType				= 1,
+	TrackedProp_WrongDeviceClass			= 2,
+	TrackedProp_BufferTooSmall				= 3,
+	TrackedProp_UnknownProperty				= 4, // Driver has not set the property (and may not ever).
+	TrackedProp_InvalidDevice				= 5,
+	TrackedProp_CouldNotContactServer		= 6,
+	TrackedProp_ValueNotProvidedByDevice	= 7,
+	TrackedProp_StringExceedsMaximumLength	= 8,
+	TrackedProp_NotYetAvailable				= 9, // The property value isn't known yet, but is expected soon. Call again later.
+	TrackedProp_PermissionDenied			= 10,
+	TrackedProp_InvalidOperation			= 11,
+};
+
+/** Allows the application to control what part of the provided texture will be used in the
+* frame buffer. */
+struct VRTextureBounds_t
+{
+	float uMin, vMin;
+	float uMax, vMax;
+};
+
+
+/** Allows the application to control how scene textures are used by the compositor when calling Submit. */
+enum EVRSubmitFlags
+{
+	// Simple render path. App submits rendered left and right eye images with no lens distortion correction applied.
+	Submit_Default = 0x00,
+
+	// App submits final left and right eye images with lens distortion already applied (lens distortion makes the images appear
+	// barrel distorted with chromatic aberration correction applied). The app would have used the data returned by
+	// vr::IVRSystem::ComputeDistortion() to apply the correct distortion to the rendered images before calling Submit().
+	Submit_LensDistortionAlreadyApplied = 0x01,
+
+	// If the texture pointer passed in is actually a renderbuffer (e.g. for MSAA in OpenGL) then set this flag.
+	Submit_GlRenderBuffer = 0x02,
+
+	// Do not use
+	Submit_Reserved = 0x04,
+};
+
+/** Data required for passing Vulkan textures to IVRCompositor::Submit.
+* Be sure to call OpenVR_Shutdown before destroying these resources. */
+struct VRVulkanTextureData_t
+{
+	uint64_t m_nImage; // VkImage
+	VkDevice_T *m_pDevice;
+	VkPhysicalDevice_T *m_pPhysicalDevice;
+	VkInstance_T *m_pInstance;
+	VkQueue_T *m_pQueue;
+	uint32_t m_nQueueFamilyIndex;
+	uint32_t m_nWidth, m_nHeight, m_nFormat, m_nSampleCount;
+};
+
+/** Data required for passing D3D12 textures to IVRCompositor::Submit.
+* Be sure to call OpenVR_Shutdown before destroying these resources. */
+struct D3D12TextureData_t
+{
+	ID3D12Resource *m_pResource;
+	ID3D12CommandQueue *m_pCommandQueue;
+	uint32_t m_nNodeMask;
+};
+
+/** Status of the overall system or tracked objects */
+enum EVRState
+{
+	VRState_Undefined = -1,
+	VRState_Off = 0,
+	VRState_Searching = 1,
+	VRState_Searching_Alert = 2,
+	VRState_Ready = 3,
+	VRState_Ready_Alert = 4,
+	VRState_NotReady = 5,
+	VRState_Standby = 6,
+	VRState_Ready_Alert_Low = 7,
+};
+
+/** The types of events that could be posted (and what the parameters mean for each event type) */
+enum EVREventType
+{
+	VREvent_None = 0,
+
+	VREvent_TrackedDeviceActivated		= 100,
+	VREvent_TrackedDeviceDeactivated	= 101,
+	VREvent_TrackedDeviceUpdated		= 102,
+	VREvent_TrackedDeviceUserInteractionStarted	= 103,
+	VREvent_TrackedDeviceUserInteractionEnded	= 104,
+	VREvent_IpdChanged					= 105,
+	VREvent_EnterStandbyMode			= 106,
+	VREvent_LeaveStandbyMode			= 107,
+	VREvent_TrackedDeviceRoleChanged	= 108,
+	VREvent_WatchdogWakeUpRequested		= 109,
+	VREvent_LensDistortionChanged		= 110,
+	VREvent_PropertyChanged				= 111,
+
+	VREvent_ButtonPress					= 200, // data is controller
+	VREvent_ButtonUnpress				= 201, // data is controller
+	VREvent_ButtonTouch					= 202, // data is controller
+	VREvent_ButtonUntouch				= 203, // data is controller
+
+	VREvent_MouseMove					= 300, // data is mouse
+	VREvent_MouseButtonDown				= 301, // data is mouse
+	VREvent_MouseButtonUp				= 302, // data is mouse
+	VREvent_FocusEnter					= 303, // data is overlay
+	VREvent_FocusLeave					= 304, // data is overlay
+	VREvent_Scroll						= 305, // data is mouse
+	VREvent_TouchPadMove				= 306, // data is mouse
+	VREvent_OverlayFocusChanged			= 307, // data is overlay, global event
+
+	VREvent_InputFocusCaptured			= 400, // data is process DEPRECATED
+	VREvent_InputFocusReleased			= 401, // data is process DEPRECATED
+	VREvent_SceneFocusLost				= 402, // data is process
+	VREvent_SceneFocusGained			= 403, // data is process
+	VREvent_SceneApplicationChanged		= 404, // data is process - The App actually drawing the scene changed (usually to or from the compositor)
+	VREvent_SceneFocusChanged			= 405, // data is process - New app got access to draw the scene
+	VREvent_InputFocusChanged			= 406, // data is process
+	VREvent_SceneApplicationSecondaryRenderingStarted = 407, // data is process
+
+	VREvent_HideRenderModels			= 410, // Sent to the scene application to request hiding render models temporarily
+	VREvent_ShowRenderModels			= 411, // Sent to the scene application to request restoring render model visibility
+
+	VREvent_OverlayShown				= 500,
+	VREvent_OverlayHidden				= 501,
+	VREvent_DashboardActivated			= 502,
+	VREvent_DashboardDeactivated		= 503,
+	VREvent_DashboardThumbSelected		= 504, // Sent to the overlay manager - data is overlay
+	VREvent_DashboardRequested			= 505, // Sent to the overlay manager - data is overlay
+	VREvent_ResetDashboard				= 506, // Send to the overlay manager
+	VREvent_RenderToast					= 507, // Send to the dashboard to render a toast - data is the notification ID
+	VREvent_ImageLoaded					= 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading
+	VREvent_ShowKeyboard				= 509, // Sent to keyboard renderer in the dashboard to invoke it
+	VREvent_HideKeyboard				= 510, // Sent to keyboard renderer in the dashboard to hide it
+	VREvent_OverlayGamepadFocusGained	= 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it
+	VREvent_OverlayGamepadFocusLost		= 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else
+	VREvent_OverlaySharedTextureChanged = 513,
+	VREvent_DashboardGuideButtonDown	= 514,
+	VREvent_DashboardGuideButtonUp		= 515,
+	VREvent_ScreenshotTriggered			= 516, // Screenshot button combo was pressed, Dashboard should request a screenshot
+	VREvent_ImageFailed					= 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load
+	VREvent_DashboardOverlayCreated		= 518,
+
+	// Screenshot API
+	VREvent_RequestScreenshot				= 520, // Sent by vrclient application to compositor to take a screenshot
+	VREvent_ScreenshotTaken					= 521, // Sent by compositor to the application that the screenshot has been taken
+	VREvent_ScreenshotFailed				= 522, // Sent by compositor to the application that the screenshot failed to be taken
+	VREvent_SubmitScreenshotToDashboard		= 523, // Sent by compositor to the dashboard that a completed screenshot was submitted
+	VREvent_ScreenshotProgressToDashboard	= 524, // Sent by compositor to the dashboard that a completed screenshot was submitted
+
+	VREvent_PrimaryDashboardDeviceChanged	= 525,
+
+	VREvent_Notification_Shown				= 600,
+	VREvent_Notification_Hidden				= 601,
+	VREvent_Notification_BeginInteraction	= 602,
+	VREvent_Notification_Destroyed			= 603,
+
+	VREvent_Quit							= 700, // data is process
+	VREvent_ProcessQuit						= 701, // data is process
+	VREvent_QuitAborted_UserPrompt			= 702, // data is process
+	VREvent_QuitAcknowledged				= 703, // data is process
+	VREvent_DriverRequestedQuit				= 704, // The driver has requested that SteamVR shut down
+
+	VREvent_ChaperoneDataHasChanged			= 800,
+	VREvent_ChaperoneUniverseHasChanged		= 801,
+	VREvent_ChaperoneTempDataHasChanged		= 802,
+	VREvent_ChaperoneSettingsHaveChanged	= 803,
+	VREvent_SeatedZeroPoseReset				= 804,
+
+	VREvent_AudioSettingsHaveChanged		= 820,
+
+	VREvent_BackgroundSettingHasChanged		= 850,
+	VREvent_CameraSettingsHaveChanged		= 851,
+	VREvent_ReprojectionSettingHasChanged	= 852,
+	VREvent_ModelSkinSettingsHaveChanged	= 853,
+	VREvent_EnvironmentSettingsHaveChanged	= 854,
+	VREvent_PowerSettingsHaveChanged		= 855,
+
+	VREvent_StatusUpdate					= 900,
+
+	VREvent_MCImageUpdated					= 1000,
+
+	VREvent_FirmwareUpdateStarted			= 1100,
+	VREvent_FirmwareUpdateFinished			= 1101,
+
+	VREvent_KeyboardClosed					= 1200,
+	VREvent_KeyboardCharInput				= 1201,
+	VREvent_KeyboardDone					= 1202, // Sent when DONE button clicked on keyboard
+
+	VREvent_ApplicationTransitionStarted		= 1300,
+	VREvent_ApplicationTransitionAborted		= 1301,
+	VREvent_ApplicationTransitionNewAppStarted	= 1302,
+	VREvent_ApplicationListUpdated				= 1303,
+	VREvent_ApplicationMimeTypeLoad				= 1304,
+	VREvent_ApplicationTransitionNewAppLaunchComplete = 1305,
+
+	VREvent_Compositor_MirrorWindowShown		= 1400,
+	VREvent_Compositor_MirrorWindowHidden		= 1401,
+	VREvent_Compositor_ChaperoneBoundsShown		= 1410,
+	VREvent_Compositor_ChaperoneBoundsHidden	= 1411,
+
+	VREvent_TrackedCamera_StartVideoStream  = 1500,
+	VREvent_TrackedCamera_StopVideoStream   = 1501,
+	VREvent_TrackedCamera_PauseVideoStream  = 1502,
+	VREvent_TrackedCamera_ResumeVideoStream = 1503,
+	VREvent_TrackedCamera_EditingSurface    = 1550,
+
+	VREvent_PerformanceTest_EnableCapture	= 1600,
+	VREvent_PerformanceTest_DisableCapture	= 1601,
+	VREvent_PerformanceTest_FidelityLevel	= 1602,
+
+	VREvent_MessageOverlay_Closed			= 1650,
+	
+	// Vendors are free to expose private events in this reserved region
+	VREvent_VendorSpecific_Reserved_Start	= 10000,
+	VREvent_VendorSpecific_Reserved_End		= 19999,
+};
+
+
+/** Level of Hmd activity */
+enum EDeviceActivityLevel
+{
+	k_EDeviceActivityLevel_Unknown = -1,
+	k_EDeviceActivityLevel_Idle = 0,
+	k_EDeviceActivityLevel_UserInteraction = 1,
+	k_EDeviceActivityLevel_UserInteraction_Timeout = 2,
+	k_EDeviceActivityLevel_Standby = 3,
+};
+
+
+/** VR controller button and axis IDs */
+enum EVRButtonId
+{
+	k_EButton_System			= 0,
+	k_EButton_ApplicationMenu	= 1,
+	k_EButton_Grip				= 2,
+	k_EButton_DPad_Left			= 3,
+	k_EButton_DPad_Up			= 4,
+	k_EButton_DPad_Right		= 5,
+	k_EButton_DPad_Down			= 6,
+	k_EButton_A					= 7,
+	
+	k_EButton_ProximitySensor   = 31,
+
+	k_EButton_Axis0				= 32,
+	k_EButton_Axis1				= 33,
+	k_EButton_Axis2				= 34,
+	k_EButton_Axis3				= 35,
+	k_EButton_Axis4				= 36,
+
+	// aliases for well known controllers
+	k_EButton_SteamVR_Touchpad	= k_EButton_Axis0,
+	k_EButton_SteamVR_Trigger	= k_EButton_Axis1,
+
+	k_EButton_Dashboard_Back	= k_EButton_Grip,
+
+	k_EButton_Max				= 64
+};
+
+inline uint64_t ButtonMaskFromId( EVRButtonId id ) { return 1ull << id; }
+
+/** used for controller button events */
+struct VREvent_Controller_t
+{
+	uint32_t button; // EVRButtonId enum
+};
+
+
+/** used for simulated mouse events in overlay space */
+enum EVRMouseButton
+{
+	VRMouseButton_Left					= 0x0001,
+	VRMouseButton_Right					= 0x0002,
+	VRMouseButton_Middle				= 0x0004,
+};
+
+
+/** used for simulated mouse events in overlay space */
+struct VREvent_Mouse_t
+{
+	float x, y; // co-ords are in GL space, bottom left of the texture is 0,0
+	uint32_t button; // EVRMouseButton enum
+};
+
+/** used for simulated mouse wheel scroll in overlay space */
+struct VREvent_Scroll_t
+{
+	float xdelta, ydelta; // movement in fraction of the pad traversed since last delta, 1.0 for a full swipe
+	uint32_t repeatCount;
+};
+
+/** when in mouse input mode you can receive data from the touchpad, these events are only sent if the users finger
+   is on the touchpad (or just released from it) 
+**/
+struct VREvent_TouchPadMove_t
+{
+	// true if the users finger is detected on the touch pad
+	bool bFingerDown;
+
+	// How long the finger has been down in seconds
+	float flSecondsFingerDown;
+
+	// These values indicate the starting finger position (so you can do some basic swipe stuff)
+	float fValueXFirst;
+	float fValueYFirst;
+
+	// This is the raw sampled coordinate without deadzoning
+	float fValueXRaw;
+	float fValueYRaw;
+};
+
+/** notification related events. Details will still change at this point */
+struct VREvent_Notification_t
+{
+	uint64_t ulUserValue;
+	uint32_t notificationId;
+};
+
+/** Used for events about processes */
+struct VREvent_Process_t
+{
+	uint32_t pid;
+	uint32_t oldPid;
+	bool bForced;
+};
+
+
+/** Used for a few events about overlays */
+struct VREvent_Overlay_t
+{
+	uint64_t overlayHandle;
+};
+
+
+/** Used for a few events about overlays */
+struct VREvent_Status_t
+{
+	uint32_t statusState; // EVRState enum
+};
+
+/** Used for keyboard events **/
+struct VREvent_Keyboard_t
+{
+	char cNewInput[8];	// Up to 11 bytes of new input
+	uint64_t uUserValue;	// Possible flags about the new input
+};
+
+struct VREvent_Ipd_t
+{
+	float ipdMeters;
+};
+
+struct VREvent_Chaperone_t
+{
+	uint64_t m_nPreviousUniverse;
+	uint64_t m_nCurrentUniverse;
+};
+
+/** Not actually used for any events */
+struct VREvent_Reserved_t
+{
+	uint64_t reserved0;
+	uint64_t reserved1;
+};
+
+struct VREvent_PerformanceTest_t
+{
+	uint32_t m_nFidelityLevel;
+};
+
+struct VREvent_SeatedZeroPoseReset_t
+{
+	bool bResetBySystemMenu;
+};
+
+struct VREvent_Screenshot_t
+{
+	uint32_t handle;
+	uint32_t type;
+};
+
+struct VREvent_ScreenshotProgress_t
+{
+	float progress;
+};
+
+struct VREvent_ApplicationLaunch_t
+{
+	uint32_t pid;
+	uint32_t unArgsHandle;
+};
+
+struct VREvent_EditingCameraSurface_t
+{
+	uint64_t overlayHandle;
+	uint32_t nVisualMode;
+};
+
+struct VREvent_MessageOverlay_t
+{
+	uint32_t unVRMessageOverlayResponse; // vr::VRMessageOverlayResponse enum
+};
+
+struct VREvent_Property_t
+{
+	PropertyContainerHandle_t container;
+	ETrackedDeviceProperty prop;
+};
+
+/** NOTE!!! If you change this you MUST manually update openvr_interop.cs.py */
+typedef union
+{
+	VREvent_Reserved_t reserved;
+	VREvent_Controller_t controller;
+	VREvent_Mouse_t mouse;
+	VREvent_Scroll_t scroll;
+	VREvent_Process_t process;
+	VREvent_Notification_t notification;
+	VREvent_Overlay_t overlay;
+	VREvent_Status_t status;
+	VREvent_Keyboard_t keyboard;
+	VREvent_Ipd_t ipd;
+	VREvent_Chaperone_t chaperone;
+	VREvent_PerformanceTest_t performanceTest;
+	VREvent_TouchPadMove_t touchPadMove;
+	VREvent_SeatedZeroPoseReset_t seatedZeroPoseReset;
+	VREvent_Screenshot_t screenshot;
+	VREvent_ScreenshotProgress_t screenshotProgress;
+	VREvent_ApplicationLaunch_t applicationLaunch;
+	VREvent_EditingCameraSurface_t cameraSurface;
+	VREvent_MessageOverlay_t messageOverlay;
+	VREvent_Property_t property;
+} VREvent_Data_t;
+
+/** An event posted by the server to all running applications */
+struct VREvent_t
+{
+	uint32_t eventType; // EVREventType enum
+	TrackedDeviceIndex_t trackedDeviceIndex;
+	float eventAgeSeconds;
+	// event data must be the end of the struct as its size is variable
+	VREvent_Data_t data;
+};
+
+
+/** The mesh to draw into the stencil (or depth) buffer to perform 
+* early stencil (or depth) kills of pixels that will never appear on the HMD.
+* This mesh draws on all the pixels that will be hidden after distortion. 
+*
+* If the HMD does not provide a visible area mesh pVertexData will be
+* NULL and unTriangleCount will be 0. */
+struct HiddenAreaMesh_t
+{
+	const HmdVector2_t *pVertexData;
+	uint32_t unTriangleCount;
+};
+
+
+enum EHiddenAreaMeshType
+{
+	k_eHiddenAreaMesh_Standard = 0,
+	k_eHiddenAreaMesh_Inverse = 1,
+	k_eHiddenAreaMesh_LineLoop = 2,
+
+	k_eHiddenAreaMesh_Max = 3,
+};
+
+
+/** Identifies what kind of axis is on the controller at index n. Read this type 
+* with pVRSystem->Get( nControllerDeviceIndex, Prop_Axis0Type_Int32 + n );
+*/
+enum EVRControllerAxisType
+{
+	k_eControllerAxis_None = 0,
+	k_eControllerAxis_TrackPad = 1,
+	k_eControllerAxis_Joystick = 2,
+	k_eControllerAxis_Trigger = 3, // Analog trigger data is in the X axis
+};
+
+
+/** contains information about one axis on the controller */
+struct VRControllerAxis_t
+{
+	float x; // Ranges from -1.0 to 1.0 for joysticks and track pads. Ranges from 0.0 to 1.0 for triggers were 0 is fully released.
+	float y; // Ranges from -1.0 to 1.0 for joysticks and track pads. Is always 0.0 for triggers.
+};
+
+
+/** the number of axes in the controller state */
+static const uint32_t k_unControllerStateAxisCount = 5;
+
+
+/** Holds all the state of a controller at one moment in time. */
+struct VRControllerState001_t
+{
+	// If packet num matches that on your prior call, then the controller state hasn't been changed since 
+	// your last call and there is no need to process it
+	uint32_t unPacketNum;
+
+	// bit flags for each of the buttons. Use ButtonMaskFromId to turn an ID into a mask
+	uint64_t ulButtonPressed;
+	uint64_t ulButtonTouched;
+
+	// Axis data for the controller's analog inputs
+	VRControllerAxis_t rAxis[ k_unControllerStateAxisCount ];
+};
+
+
+typedef VRControllerState001_t VRControllerState_t;
+
+
+/** determines how to provide output to the application of various event processing functions. */
+enum EVRControllerEventOutputType
+{
+	ControllerEventOutput_OSEvents = 0,
+	ControllerEventOutput_VREvents = 1,
+};
+
+
+
+/** Collision Bounds Style */
+enum ECollisionBoundsStyle
+{
+	COLLISION_BOUNDS_STYLE_BEGINNER = 0,
+	COLLISION_BOUNDS_STYLE_INTERMEDIATE,
+	COLLISION_BOUNDS_STYLE_SQUARES,
+	COLLISION_BOUNDS_STYLE_ADVANCED,
+	COLLISION_BOUNDS_STYLE_NONE,
+
+	COLLISION_BOUNDS_STYLE_COUNT
+};
+
+/** Allows the application to customize how the overlay appears in the compositor */
+struct Compositor_OverlaySettings
+{
+	uint32_t size; // sizeof(Compositor_OverlaySettings)
+	bool curved, antialias;
+	float scale, distance, alpha;
+	float uOffset, vOffset, uScale, vScale;
+	float gridDivs, gridWidth, gridScale;
+	HmdMatrix44_t transform;
+};
+
+/** used to refer to a single VR overlay */
+typedef uint64_t VROverlayHandle_t;
+
+static const VROverlayHandle_t k_ulOverlayHandleInvalid = 0;
+
+/** Errors that can occur around VR overlays */
+enum EVROverlayError
+{
+	VROverlayError_None						= 0,
+
+	VROverlayError_UnknownOverlay			= 10,
+	VROverlayError_InvalidHandle			= 11,
+	VROverlayError_PermissionDenied			= 12,
+	VROverlayError_OverlayLimitExceeded		= 13, // No more overlays could be created because the maximum number already exist
+	VROverlayError_WrongVisibilityType		= 14,
+	VROverlayError_KeyTooLong				= 15,
+	VROverlayError_NameTooLong				= 16,
+	VROverlayError_KeyInUse					= 17,
+	VROverlayError_WrongTransformType		= 18,
+	VROverlayError_InvalidTrackedDevice		= 19,
+	VROverlayError_InvalidParameter			= 20,
+	VROverlayError_ThumbnailCantBeDestroyed	= 21,
+	VROverlayError_ArrayTooSmall			= 22,
+	VROverlayError_RequestFailed			= 23,
+	VROverlayError_InvalidTexture			= 24,
+	VROverlayError_UnableToLoadFile			= 25,
+	VROverlayError_KeyboardAlreadyInUse		= 26,
+	VROverlayError_NoNeighbor				= 27,
+	VROverlayError_TooManyMaskPrimitives	= 29,
+	VROverlayError_BadMaskPrimitive			= 30,
+};
+
+/** enum values to pass in to VR_Init to identify whether the application will 
+* draw a 3D scene. */
+enum EVRApplicationType
+{
+	VRApplication_Other = 0,		// Some other kind of application that isn't covered by the other entries 
+	VRApplication_Scene	= 1,		// Application will submit 3D frames 
+	VRApplication_Overlay = 2,		// Application only interacts with overlays
+	VRApplication_Background = 3,	// Application should not start SteamVR if it's not already running, and should not
+									// keep it running if everything else quits.
+	VRApplication_Utility = 4,		// Init should not try to load any drivers. The application needs access to utility
+									// interfaces (like IVRSettings and IVRApplications) but not hardware.
+	VRApplication_VRMonitor = 5,	// Reserved for vrmonitor
+	VRApplication_SteamWatchdog = 6,// Reserved for Steam
+
+	VRApplication_Max
+};
+
+
+/** error codes for firmware */
+enum EVRFirmwareError
+{
+	VRFirmwareError_None = 0,
+	VRFirmwareError_Success = 1,
+	VRFirmwareError_Fail = 2,
+};
+
+
+/** error codes for notifications */
+enum EVRNotificationError
+{
+	VRNotificationError_OK = 0,
+	VRNotificationError_InvalidNotificationId = 100,
+	VRNotificationError_NotificationQueueFull = 101,
+	VRNotificationError_InvalidOverlayHandle = 102,
+	VRNotificationError_SystemWithUserValueAlreadyExists = 103,
+};
+
+
+/** error codes returned by Vr_Init */
+
+// Please add adequate error description to https://developer.valvesoftware.com/w/index.php?title=Category:SteamVRHelp
+enum EVRInitError
+{
+	VRInitError_None	= 0,
+	VRInitError_Unknown = 1,
+
+	VRInitError_Init_InstallationNotFound		= 100,
+	VRInitError_Init_InstallationCorrupt		= 101,
+	VRInitError_Init_VRClientDLLNotFound		= 102,
+	VRInitError_Init_FileNotFound				= 103,
+	VRInitError_Init_FactoryNotFound			= 104,
+	VRInitError_Init_InterfaceNotFound			= 105,
+	VRInitError_Init_InvalidInterface			= 106,
+	VRInitError_Init_UserConfigDirectoryInvalid = 107,
+	VRInitError_Init_HmdNotFound				= 108,
+	VRInitError_Init_NotInitialized				= 109,
+	VRInitError_Init_PathRegistryNotFound		= 110,
+	VRInitError_Init_NoConfigPath				= 111,
+	VRInitError_Init_NoLogPath					= 112,
+	VRInitError_Init_PathRegistryNotWritable	= 113,
+	VRInitError_Init_AppInfoInitFailed			= 114,
+	VRInitError_Init_Retry						= 115, // Used internally to cause retries to vrserver
+	VRInitError_Init_InitCanceledByUser			= 116, // The calling application should silently exit. The user canceled app startup
+	VRInitError_Init_AnotherAppLaunching		= 117, 
+	VRInitError_Init_SettingsInitFailed			= 118, 
+	VRInitError_Init_ShuttingDown				= 119,
+	VRInitError_Init_TooManyObjects				= 120,
+	VRInitError_Init_NoServerForBackgroundApp	= 121,
+	VRInitError_Init_NotSupportedWithCompositor	= 122,
+	VRInitError_Init_NotAvailableToUtilityApps	= 123,
+	VRInitError_Init_Internal				 	= 124,
+	VRInitError_Init_HmdDriverIdIsNone		 	= 125,
+	VRInitError_Init_HmdNotFoundPresenceFailed 	= 126,
+	VRInitError_Init_VRMonitorNotFound			= 127,
+	VRInitError_Init_VRMonitorStartupFailed		= 128,
+	VRInitError_Init_LowPowerWatchdogNotSupported = 129, 
+	VRInitError_Init_InvalidApplicationType		= 130,
+	VRInitError_Init_NotAvailableToWatchdogApps = 131,
+	VRInitError_Init_WatchdogDisabledInSettings = 132,
+	VRInitError_Init_VRDashboardNotFound		= 133,
+	VRInitError_Init_VRDashboardStartupFailed	= 134,
+
+	VRInitError_Driver_Failed				= 200,
+	VRInitError_Driver_Unknown				= 201,
+	VRInitError_Driver_HmdUnknown			= 202,
+	VRInitError_Driver_NotLoaded			= 203,
+	VRInitError_Driver_RuntimeOutOfDate		= 204,
+	VRInitError_Driver_HmdInUse				= 205,
+	VRInitError_Driver_NotCalibrated		= 206,
+	VRInitError_Driver_CalibrationInvalid	= 207,
+	VRInitError_Driver_HmdDisplayNotFound	= 208,
+	VRInitError_Driver_TrackedDeviceInterfaceUnknown = 209,
+	// VRInitError_Driver_HmdDisplayNotFoundAfterFix	 = 210, // not needed: here for historic reasons
+	VRInitError_Driver_HmdDriverIdOutOfBounds = 211,
+	VRInitError_Driver_HmdDisplayMirrored  = 212,
+
+	VRInitError_IPC_ServerInitFailed		= 300,
+	VRInitError_IPC_ConnectFailed			= 301,
+	VRInitError_IPC_SharedStateInitFailed	= 302,
+	VRInitError_IPC_CompositorInitFailed	= 303,
+	VRInitError_IPC_MutexInitFailed			= 304,
+	VRInitError_IPC_Failed					= 305,
+	VRInitError_IPC_CompositorConnectFailed	= 306,
+	VRInitError_IPC_CompositorInvalidConnectResponse = 307,
+	VRInitError_IPC_ConnectFailedAfterMultipleAttempts = 308,
+
+	VRInitError_Compositor_Failed					= 400,
+	VRInitError_Compositor_D3D11HardwareRequired	= 401,
+	VRInitError_Compositor_FirmwareRequiresUpdate	= 402,
+	VRInitError_Compositor_OverlayInitFailed		= 403,
+	VRInitError_Compositor_ScreenshotsInitFailed	= 404,
+
+	VRInitError_VendorSpecific_UnableToConnectToOculusRuntime = 1000,
+
+	VRInitError_VendorSpecific_HmdFound_CantOpenDevice 				= 1101,
+	VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart	= 1102,
+	VRInitError_VendorSpecific_HmdFound_NoStoredConfig 				= 1103,
+	VRInitError_VendorSpecific_HmdFound_ConfigTooBig 				= 1104,
+	VRInitError_VendorSpecific_HmdFound_ConfigTooSmall 				= 1105,
+	VRInitError_VendorSpecific_HmdFound_UnableToInitZLib 			= 1106,
+	VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion 	= 1107,
+	VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart	= 1108,
+	VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart	= 1109,
+	VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext		= 1110,
+	VRInitError_VendorSpecific_HmdFound_UserDataAddressRange		= 1111,
+	VRInitError_VendorSpecific_HmdFound_UserDataError				= 1112,
+	VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck		= 1113,
+
+	VRInitError_Steam_SteamInstallationNotFound = 2000,
+};
+
+enum EVRScreenshotType
+{
+	VRScreenshotType_None = 0,
+	VRScreenshotType_Mono = 1, // left eye only
+	VRScreenshotType_Stereo = 2,
+	VRScreenshotType_Cubemap = 3,
+	VRScreenshotType_MonoPanorama = 4,
+	VRScreenshotType_StereoPanorama = 5
+};
+
+enum EVRScreenshotPropertyFilenames
+{
+	VRScreenshotPropertyFilenames_Preview = 0,
+	VRScreenshotPropertyFilenames_VR = 1,
+};
+
+enum EVRTrackedCameraError
+{
+	VRTrackedCameraError_None                       = 0,
+	VRTrackedCameraError_OperationFailed            = 100,
+	VRTrackedCameraError_InvalidHandle              = 101,	
+	VRTrackedCameraError_InvalidFrameHeaderVersion  = 102,
+	VRTrackedCameraError_OutOfHandles               = 103,
+	VRTrackedCameraError_IPCFailure                 = 104,
+	VRTrackedCameraError_NotSupportedForThisDevice  = 105,
+	VRTrackedCameraError_SharedMemoryFailure        = 106,
+	VRTrackedCameraError_FrameBufferingFailure      = 107,
+	VRTrackedCameraError_StreamSetupFailure         = 108,
+	VRTrackedCameraError_InvalidGLTextureId         = 109,
+	VRTrackedCameraError_InvalidSharedTextureHandle = 110,
+	VRTrackedCameraError_FailedToGetGLTextureId     = 111,
+	VRTrackedCameraError_SharedTextureFailure       = 112,
+	VRTrackedCameraError_NoFrameAvailable           = 113,
+	VRTrackedCameraError_InvalidArgument            = 114,
+	VRTrackedCameraError_InvalidFrameBufferSize     = 115,
+};
+
+enum EVRTrackedCameraFrameType
+{
+	VRTrackedCameraFrameType_Distorted = 0,			// This is the camera video frame size in pixels, still distorted.
+	VRTrackedCameraFrameType_Undistorted,			// In pixels, an undistorted inscribed rectangle region without invalid regions. This size is subject to changes shortly.
+	VRTrackedCameraFrameType_MaximumUndistorted,	// In pixels, maximum undistorted with invalid regions. Non zero alpha component identifies valid regions.
+	MAX_CAMERA_FRAME_TYPES
+};
+
+typedef uint64_t TrackedCameraHandle_t;
+#define INVALID_TRACKED_CAMERA_HANDLE	((vr::TrackedCameraHandle_t)0)
+
+struct CameraVideoStreamFrameHeader_t
+{
+	EVRTrackedCameraFrameType eFrameType;
+
+	uint32_t nWidth;
+	uint32_t nHeight;
+	uint32_t nBytesPerPixel;
+
+	uint32_t nFrameSequence;
+
+	TrackedDevicePose_t standingTrackedDevicePose;
+};
+
+// Screenshot types
+typedef uint32_t ScreenshotHandle_t;
+
+static const uint32_t k_unScreenshotHandleInvalid = 0;
+
+#pragma pack( pop )
+
+// figure out how to import from the VR API dll
+#if defined(_WIN32)
+
+#ifdef VR_API_EXPORT
+#define VR_INTERFACE extern "C" __declspec( dllexport )
+#else
+#define VR_INTERFACE extern "C" __declspec( dllimport )
+#endif
+
+#elif defined(__GNUC__) || defined(COMPILER_GCC) || defined(__APPLE__)
+
+#ifdef VR_API_EXPORT
+#define VR_INTERFACE extern "C" __attribute__((visibility("default")))
+#else
+#define VR_INTERFACE extern "C" 
+#endif
+
+#else
+#error "Unsupported Platform."
+#endif
+
+
+#if defined( _WIN32 )
+#define VR_CALLTYPE __cdecl
+#else
+#define VR_CALLTYPE 
+#endif
+
+} // namespace vr
+
+#endif // _INCLUDE_VRTYPES_H
+
+
+// vrannotation.h
+#ifdef API_GEN
+# define VR_CLANG_ATTR(ATTR) __attribute__((annotate( ATTR )))
+#else
+# define VR_CLANG_ATTR(ATTR)
+#endif
+
+#define VR_METHOD_DESC(DESC) VR_CLANG_ATTR( "desc:" #DESC ";" )
+#define VR_IGNOREATTR() VR_CLANG_ATTR( "ignore" )
+#define VR_OUT_STRUCT() VR_CLANG_ATTR( "out_struct: ;" )
+#define VR_OUT_STRING() VR_CLANG_ATTR( "out_string: ;" )
+#define VR_OUT_ARRAY_CALL(COUNTER,FUNCTION,PARAMS) VR_CLANG_ATTR( "out_array_call:" #COUNTER "," #FUNCTION "," #PARAMS ";" )
+#define VR_OUT_ARRAY_COUNT(COUNTER) VR_CLANG_ATTR( "out_array_count:" #COUNTER ";" )
+#define VR_ARRAY_COUNT(COUNTER) VR_CLANG_ATTR( "array_count:" #COUNTER ";" )
+#define VR_ARRAY_COUNT_D(COUNTER, DESC) VR_CLANG_ATTR( "array_count:" #COUNTER ";desc:" #DESC )
+#define VR_BUFFER_COUNT(COUNTER) VR_CLANG_ATTR( "buffer_count:" #COUNTER ";" )
+#define VR_OUT_BUFFER_COUNT(COUNTER) VR_CLANG_ATTR( "out_buffer_count:" #COUNTER ";" )
+#define VR_OUT_STRING_COUNT(COUNTER) VR_CLANG_ATTR( "out_string_count:" #COUNTER ";" )
+
+// ivrsystem.h
+namespace vr
+{
+
+class IVRSystem
+{
+public:
+
+
+	// ------------------------------------
+	// Display Methods
+	// ------------------------------------
+
+	/** Suggested size for the intermediate render target that the distortion pulls from. */
+	virtual void GetRecommendedRenderTargetSize( uint32_t *pnWidth, uint32_t *pnHeight ) = 0;
+
+	/** The projection matrix for the specified eye */
+	virtual HmdMatrix44_t GetProjectionMatrix( EVREye eEye, float fNearZ, float fFarZ ) = 0;
+
+	/** The components necessary to build your own projection matrix in case your
+	* application is doing something fancy like infinite Z */
+	virtual void GetProjectionRaw( EVREye eEye, float *pfLeft, float *pfRight, float *pfTop, float *pfBottom ) = 0;
+
+	/** Gets the result of the distortion function for the specified eye and input UVs. UVs go from 0,0 in 
+	* the upper left of that eye's viewport and 1,1 in the lower right of that eye's viewport.
+	* Returns true for success. Otherwise, returns false, and distortion coordinates are not suitable. */
+	virtual bool ComputeDistortion( EVREye eEye, float fU, float fV, DistortionCoordinates_t *pDistortionCoordinates ) = 0;
+
+	/** Returns the transform from eye space to the head space. Eye space is the per-eye flavor of head
+	* space that provides stereo disparity. Instead of Model * View * Projection the sequence is Model * View * Eye^-1 * Projection. 
+	* Normally View and Eye^-1 will be multiplied together and treated as View in your application. 
+	*/
+	virtual HmdMatrix34_t GetEyeToHeadTransform( EVREye eEye ) = 0;
+
+	/** Returns the number of elapsed seconds since the last recorded vsync event. This 
+	*	will come from a vsync timer event in the timer if possible or from the application-reported
+	*   time if that is not available. If no vsync times are available the function will 
+	*   return zero for vsync time and frame counter and return false from the method. */
+	virtual bool GetTimeSinceLastVsync( float *pfSecondsSinceLastVsync, uint64_t *pulFrameCounter ) = 0;
+
+	/** [D3D9 Only]
+	* Returns the adapter index that the user should pass into CreateDevice to set up D3D9 in such
+	* a way that it can go full screen exclusive on the HMD. Returns -1 if there was an error.
+	*/
+	virtual int32_t GetD3D9AdapterIndex() = 0;
+
+	/** [D3D10/11 Only]
+	* Returns the adapter index that the user should pass into EnumAdapters to create the device 
+	* and swap chain in DX10 and DX11. If an error occurs the index will be set to -1.
+	*/
+	virtual void GetDXGIOutputInfo( int32_t *pnAdapterIndex ) = 0;
+
+	// ------------------------------------
+	// Display Mode methods
+	// ------------------------------------
+
+	/** Use to determine if the headset display is part of the desktop (i.e. extended) or hidden (i.e. direct mode). */
+	virtual bool IsDisplayOnDesktop() = 0;
+
+	/** Set the display visibility (true = extended, false = direct mode).  Return value of true indicates that the change was successful. */
+	virtual bool SetDisplayVisibility( bool bIsVisibleOnDesktop ) = 0;
+
+	// ------------------------------------
+	// Tracking Methods
+	// ------------------------------------
+
+	/** The pose that the tracker thinks that the HMD will be in at the specified number of seconds into the 
+	* future. Pass 0 to get the state at the instant the method is called. Most of the time the application should
+	* calculate the time until the photons will be emitted from the display and pass that time into the method.
+	*
+	* This is roughly analogous to the inverse of the view matrix in most applications, though 
+	* many games will need to do some additional rotation or translation on top of the rotation
+	* and translation provided by the head pose.
+	*
+	* For devices where bPoseIsValid is true the application can use the pose to position the device
+	* in question. The provided array can be any size up to k_unMaxTrackedDeviceCount. 
+	*
+	* Seated experiences should call this method with TrackingUniverseSeated and receive poses relative
+	* to the seated zero pose. Standing experiences should call this method with TrackingUniverseStanding 
+	* and receive poses relative to the Chaperone Play Area. TrackingUniverseRawAndUncalibrated should 
+	* probably not be used unless the application is the Chaperone calibration tool itself, but will provide
+	* poses relative to the hardware-specific coordinate system in the driver.
+	*/
+	virtual void GetDeviceToAbsoluteTrackingPose( ETrackingUniverseOrigin eOrigin, float fPredictedSecondsToPhotonsFromNow, VR_ARRAY_COUNT(unTrackedDevicePoseArrayCount) TrackedDevicePose_t *pTrackedDevicePoseArray, uint32_t unTrackedDevicePoseArrayCount ) = 0;
+
+	/** Sets the zero pose for the seated tracker coordinate system to the current position and yaw of the HMD. After 
+	* ResetSeatedZeroPose all GetDeviceToAbsoluteTrackingPose calls that pass TrackingUniverseSeated as the origin 
+	* will be relative to this new zero pose. The new zero coordinate system will not change the fact that the Y axis 
+	* is up in the real world, so the next pose returned from GetDeviceToAbsoluteTrackingPose after a call to 
+	* ResetSeatedZeroPose may not be exactly an identity matrix.
+	*
+	* NOTE: This function overrides the user's previously saved seated zero pose and should only be called as the result of a user action. 
+	* Users are also able to set their seated zero pose via the OpenVR Dashboard.
+	**/
+	virtual void ResetSeatedZeroPose() = 0;
+
+	/** Returns the transform from the seated zero pose to the standing absolute tracking system. This allows 
+	* applications to represent the seated origin to used or transform object positions from one coordinate
+	* system to the other. 
+	*
+	* The seated origin may or may not be inside the Play Area or Collision Bounds returned by IVRChaperone. Its position 
+	* depends on what the user has set from the Dashboard settings and previous calls to ResetSeatedZeroPose. */
+	virtual HmdMatrix34_t GetSeatedZeroPoseToStandingAbsoluteTrackingPose() = 0;
+
+	/** Returns the transform from the tracking origin to the standing absolute tracking system. This allows
+	* applications to convert from raw tracking space to the calibrated standing coordinate system. */
+	virtual HmdMatrix34_t GetRawZeroPoseToStandingAbsoluteTrackingPose() = 0;
+
+	/** Get a sorted array of device indices of a given class of tracked devices (e.g. controllers).  Devices are sorted right to left
+	* relative to the specified tracked device (default: hmd -- pass in -1 for absolute tracking space).  Returns the number of devices
+	* in the list, or the size of the array needed if not large enough. */
+	virtual uint32_t GetSortedTrackedDeviceIndicesOfClass( ETrackedDeviceClass eTrackedDeviceClass, VR_ARRAY_COUNT(unTrackedDeviceIndexArrayCount) vr::TrackedDeviceIndex_t *punTrackedDeviceIndexArray, uint32_t unTrackedDeviceIndexArrayCount, vr::TrackedDeviceIndex_t unRelativeToTrackedDeviceIndex = k_unTrackedDeviceIndex_Hmd ) = 0;
+
+	/** Returns the level of activity on the device. */
+	virtual EDeviceActivityLevel GetTrackedDeviceActivityLevel( vr::TrackedDeviceIndex_t unDeviceId ) = 0;
+
+	/** Convenience utility to apply the specified transform to the specified pose.
+	*   This properly transforms all pose components, including velocity and angular velocity
+	*/
+	virtual void ApplyTransform( TrackedDevicePose_t *pOutputPose, const TrackedDevicePose_t *pTrackedDevicePose, const HmdMatrix34_t *pTransform ) = 0;
+
+	/** Returns the device index associated with a specific role, for example the left hand or the right hand. */
+	virtual vr::TrackedDeviceIndex_t GetTrackedDeviceIndexForControllerRole( vr::ETrackedControllerRole unDeviceType ) = 0;
+
+	/** Returns the controller type associated with a device index. */
+	virtual vr::ETrackedControllerRole GetControllerRoleForTrackedDeviceIndex( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0;
+
+	// ------------------------------------
+	// Property methods
+	// ------------------------------------
+
+	/** Returns the device class of a tracked device. If there has not been a device connected in this slot
+	* since the application started this function will return TrackedDevice_Invalid. For previous detected
+	* devices the function will return the previously observed device class. 
+	*
+	* To determine which devices exist on the system, just loop from 0 to k_unMaxTrackedDeviceCount and check
+	* the device class. Every device with something other than TrackedDevice_Invalid is associated with an 
+	* actual tracked device. */
+	virtual ETrackedDeviceClass GetTrackedDeviceClass( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0;
+
+	/** Returns true if there is a device connected in this slot. */
+	virtual bool IsTrackedDeviceConnected( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0;
+
+	/** Returns a bool property. If the device index is not valid or the property is not a bool type this function will return false. */
+	virtual bool GetBoolTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0;
+
+	/** Returns a float property. If the device index is not valid or the property is not a float type this function will return 0. */
+	virtual float GetFloatTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0;
+
+	/** Returns an int property. If the device index is not valid or the property is not a int type this function will return 0. */
+	virtual int32_t GetInt32TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0;
+
+	/** Returns a uint64 property. If the device index is not valid or the property is not a uint64 type this function will return 0. */
+	virtual uint64_t GetUint64TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0;
+
+	/** Returns a matrix property. If the device index is not valid or the property is not a matrix type, this function will return identity. */
+	virtual HmdMatrix34_t GetMatrix34TrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L ) = 0;
+
+	/** Returns a string property. If the device index is not valid or the property is not a string type this function will 
+	* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing
+	* null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */
+	virtual uint32_t GetStringTrackedDeviceProperty( vr::TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L ) = 0;
+
+	/** returns a string that corresponds with the specified property error. The string will be the name 
+	* of the error enum value for all valid error codes */
+	virtual const char *GetPropErrorNameFromEnum( ETrackedPropertyError error ) = 0;
+
+	// ------------------------------------
+	// Event methods
+	// ------------------------------------
+
+	/** Returns true and fills the event with the next event on the queue if there is one. If there are no events
+	* this method returns false. uncbVREvent should be the size in bytes of the VREvent_t struct */
+	virtual bool PollNextEvent( VREvent_t *pEvent, uint32_t uncbVREvent ) = 0;
+
+	/** Returns true and fills the event with the next event on the queue if there is one. If there are no events
+	* this method returns false. Fills in the pose of the associated tracked device in the provided pose struct. 
+	* This pose will always be older than the call to this function and should not be used to render the device. 
+	uncbVREvent should be the size in bytes of the VREvent_t struct */
+	virtual bool PollNextEventWithPose( ETrackingUniverseOrigin eOrigin, VREvent_t *pEvent, uint32_t uncbVREvent, vr::TrackedDevicePose_t *pTrackedDevicePose ) = 0;
+
+	/** returns the name of an EVREvent enum value */
+	virtual const char *GetEventTypeNameFromEnum( EVREventType eType ) = 0;
+
+	// ------------------------------------
+	// Rendering helper methods
+	// ------------------------------------
+
+	/** Returns the hidden area mesh for the current HMD. The pixels covered by this mesh will never be seen by the user after the lens distortion is
+	* applied based on visibility to the panels. If this HMD does not have a hidden area mesh, the vertex data and count will be NULL and 0 respectively.
+	* This mesh is meant to be rendered into the stencil buffer (or into the depth buffer setting nearz) before rendering each eye's view. 
+	* This will improve performance by letting the GPU early-reject pixels the user will never see before running the pixel shader.
+	* NOTE: Render this mesh with backface culling disabled since the winding order of the vertices can be different per-HMD or per-eye.
+	* Setting the bInverse argument to true will produce the visible area mesh that is commonly used in place of full-screen quads. The visible area mesh covers all of the pixels the hidden area mesh does not cover.
+	* Setting the bLineLoop argument will return a line loop of vertices in HiddenAreaMesh_t->pVertexData with HiddenAreaMesh_t->unTriangleCount set to the number of vertices.
+	*/
+	virtual HiddenAreaMesh_t GetHiddenAreaMesh( EVREye eEye, EHiddenAreaMeshType type = k_eHiddenAreaMesh_Standard ) = 0;
+
+	// ------------------------------------
+	// Controller methods
+	// ------------------------------------
+
+	/** Fills the supplied struct with the current state of the controller. Returns false if the controller index
+	* is invalid. */
+	virtual bool GetControllerState( vr::TrackedDeviceIndex_t unControllerDeviceIndex, vr::VRControllerState_t *pControllerState, uint32_t unControllerStateSize ) = 0;
+
+	/** fills the supplied struct with the current state of the controller and the provided pose with the pose of 
+	* the controller when the controller state was updated most recently. Use this form if you need a precise controller
+	* pose as input to your application when the user presses or releases a button. */
+	virtual bool GetControllerStateWithPose( ETrackingUniverseOrigin eOrigin, vr::TrackedDeviceIndex_t unControllerDeviceIndex, vr::VRControllerState_t *pControllerState, uint32_t unControllerStateSize, TrackedDevicePose_t *pTrackedDevicePose ) = 0;
+
+	/** Trigger a single haptic pulse on a controller. After this call the application may not trigger another haptic pulse on this controller
+	* and axis combination for 5ms. */
+	virtual void TriggerHapticPulse( vr::TrackedDeviceIndex_t unControllerDeviceIndex, uint32_t unAxisId, unsigned short usDurationMicroSec ) = 0;
+
+	/** returns the name of an EVRButtonId enum value */
+	virtual const char *GetButtonIdNameFromEnum( EVRButtonId eButtonId ) = 0;
+
+	/** returns the name of an EVRControllerAxisType enum value */
+	virtual const char *GetControllerAxisTypeNameFromEnum( EVRControllerAxisType eAxisType ) = 0;
+
+	/** Tells OpenVR that this process wants exclusive access to controller button states and button events. Other apps will be notified that 
+	* they have lost input focus with a VREvent_InputFocusCaptured event. Returns false if input focus could not be captured for
+	* some reason. */
+	virtual bool CaptureInputFocus() = 0;
+
+	/** Tells OpenVR that this process no longer wants exclusive access to button states and button events. Other apps will be notified 
+	* that input focus has been released with a VREvent_InputFocusReleased event. */
+	virtual void ReleaseInputFocus() = 0;
+
+	/** Returns true if input focus is captured by another process. */
+	virtual bool IsInputFocusCapturedByAnotherProcess() = 0;
+
+	// ------------------------------------
+	// Debug Methods
+	// ------------------------------------
+
+	/** Sends a request to the driver for the specified device and returns the response. The maximum response size is 32k,
+	* but this method can be called with a smaller buffer. If the response exceeds the size of the buffer, it is truncated. 
+	* The size of the response including its terminating null is returned. */
+	virtual uint32_t DriverDebugRequest( vr::TrackedDeviceIndex_t unDeviceIndex, const char *pchRequest, char *pchResponseBuffer, uint32_t unResponseBufferSize ) = 0;
+
+	// ------------------------------------
+	// Firmware methods
+	// ------------------------------------
+	
+	/** Performs the actual firmware update if applicable. 
+	 * The following events will be sent, if VRFirmwareError_None was returned: VREvent_FirmwareUpdateStarted, VREvent_FirmwareUpdateFinished 
+	 * Use the properties Prop_Firmware_UpdateAvailable_Bool, Prop_Firmware_ManualUpdate_Bool, and Prop_Firmware_ManualUpdateURL_String
+	 * to figure our whether a firmware update is available, and to figure out whether its a manual update 
+	 * Prop_Firmware_ManualUpdateURL_String should point to an URL describing the manual update process */
+	virtual vr::EVRFirmwareError PerformFirmwareUpdate( vr::TrackedDeviceIndex_t unDeviceIndex ) = 0;
+
+	// ------------------------------------
+	// Application life cycle methods
+	// ------------------------------------
+
+	/** Call this to acknowledge to the system that VREvent_Quit has been received and that the process is exiting.
+	* This extends the timeout until the process is killed. */
+	virtual void AcknowledgeQuit_Exiting() = 0;
+
+	/** Call this to tell the system that the user is being prompted to save data. This
+	* halts the timeout and dismisses the dashboard (if it was up). Applications should be sure to actually 
+	* prompt the user to save and then exit afterward, otherwise the user will be left in a confusing state. */
+	virtual void AcknowledgeQuit_UserPrompt() = 0;
+
+};
+
+static const char * const IVRSystem_Version = "IVRSystem_015";
+
+}
+
+
+// ivrapplications.h
+namespace vr
+{
+
+	/** Used for all errors reported by the IVRApplications interface */
+	enum EVRApplicationError
+	{
+		VRApplicationError_None = 0,
+
+		VRApplicationError_AppKeyAlreadyExists = 100,	// Only one application can use any given key
+		VRApplicationError_NoManifest = 101,			// the running application does not have a manifest
+		VRApplicationError_NoApplication = 102,			// No application is running
+		VRApplicationError_InvalidIndex = 103,
+		VRApplicationError_UnknownApplication = 104,	// the application could not be found
+		VRApplicationError_IPCFailed = 105,				// An IPC failure caused the request to fail
+		VRApplicationError_ApplicationAlreadyRunning = 106, 
+		VRApplicationError_InvalidManifest = 107,
+		VRApplicationError_InvalidApplication = 108,
+		VRApplicationError_LaunchFailed = 109,			// the process didn't start
+		VRApplicationError_ApplicationAlreadyStarting = 110, // the system was already starting the same application
+		VRApplicationError_LaunchInProgress = 111,		// The system was already starting a different application
+		VRApplicationError_OldApplicationQuitting = 112, 
+		VRApplicationError_TransitionAborted = 113,
+		VRApplicationError_IsTemplate = 114, // error when you try to call LaunchApplication() on a template type app (use LaunchTemplateApplication)
+
+		VRApplicationError_BufferTooSmall = 200,		// The provided buffer was too small to fit the requested data
+		VRApplicationError_PropertyNotSet = 201,		// The requested property was not set
+		VRApplicationError_UnknownProperty = 202,
+		VRApplicationError_InvalidParameter = 203,
+	};
+
+	/** The maximum length of an application key */
+	static const uint32_t k_unMaxApplicationKeyLength = 128;
+
+	/** these are the properties available on applications. */
+	enum EVRApplicationProperty
+	{
+		VRApplicationProperty_Name_String				= 0,
+
+		VRApplicationProperty_LaunchType_String			= 11,
+		VRApplicationProperty_WorkingDirectory_String	= 12,
+		VRApplicationProperty_BinaryPath_String			= 13,
+		VRApplicationProperty_Arguments_String			= 14,
+		VRApplicationProperty_URL_String				= 15,
+
+		VRApplicationProperty_Description_String		= 50,
+		VRApplicationProperty_NewsURL_String			= 51,
+		VRApplicationProperty_ImagePath_String			= 52,
+		VRApplicationProperty_Source_String				= 53,
+
+		VRApplicationProperty_IsDashboardOverlay_Bool	= 60,
+		VRApplicationProperty_IsTemplate_Bool			= 61,
+		VRApplicationProperty_IsInstanced_Bool			= 62,
+		VRApplicationProperty_IsInternal_Bool			= 63,
+
+		VRApplicationProperty_LastLaunchTime_Uint64		= 70,
+	};
+
+	/** These are states the scene application startup process will go through. */
+	enum EVRApplicationTransitionState
+	{
+		VRApplicationTransition_None = 0,
+
+		VRApplicationTransition_OldAppQuitSent = 10,
+		VRApplicationTransition_WaitingForExternalLaunch = 11,
+		
+		VRApplicationTransition_NewAppLaunched = 20,
+	};
+
+	struct AppOverrideKeys_t
+	{
+		const char *pchKey;
+		const char *pchValue;
+	};
+
+	/** Currently recognized mime types */
+	static const char * const k_pch_MimeType_HomeApp		= "vr/home";
+	static const char * const k_pch_MimeType_GameTheater	= "vr/game_theater";
+
+	class IVRApplications
+	{
+	public:
+
+		// ---------------  Application management  --------------- //
+
+		/** Adds an application manifest to the list to load when building the list of installed applications. 
+		* Temporary manifests are not automatically loaded */
+		virtual EVRApplicationError AddApplicationManifest( const char *pchApplicationManifestFullPath, bool bTemporary = false ) = 0;
+
+		/** Removes an application manifest from the list to load when building the list of installed applications. */
+		virtual EVRApplicationError RemoveApplicationManifest( const char *pchApplicationManifestFullPath ) = 0;
+
+		/** Returns true if an application is installed */
+		virtual bool IsApplicationInstalled( const char *pchAppKey ) = 0;
+
+		/** Returns the number of applications available in the list */
+		virtual uint32_t GetApplicationCount() = 0;
+
+		/** Returns the key of the specified application. The index is at least 0 and is less than the return 
+		* value of GetApplicationCount(). The buffer should be at least k_unMaxApplicationKeyLength in order to 
+		* fit the key. */
+		virtual EVRApplicationError GetApplicationKeyByIndex( uint32_t unApplicationIndex, VR_OUT_STRING() char *pchAppKeyBuffer, uint32_t unAppKeyBufferLen ) = 0;
+
+		/** Returns the key of the application for the specified Process Id. The buffer should be at least 
+		* k_unMaxApplicationKeyLength in order to fit the key. */
+		virtual EVRApplicationError GetApplicationKeyByProcessId( uint32_t unProcessId, char *pchAppKeyBuffer, uint32_t unAppKeyBufferLen ) = 0;
+
+		/** Launches the application. The existing scene application will exit and then the new application will start.
+		* This call is not valid for dashboard overlay applications. */
+		virtual EVRApplicationError LaunchApplication( const char *pchAppKey ) = 0;
+
+		/** Launches an instance of an application of type template, with its app key being pchNewAppKey (which must be unique) and optionally override sections
+		* from the manifest file via AppOverrideKeys_t
+		*/
+		virtual EVRApplicationError LaunchTemplateApplication( const char *pchTemplateAppKey, const char *pchNewAppKey, VR_ARRAY_COUNT( unKeys ) const AppOverrideKeys_t *pKeys, uint32_t unKeys ) = 0;
+
+		/** launches the application currently associated with this mime type and passes it the option args, typically the filename or object name of the item being launched */
+		virtual vr::EVRApplicationError LaunchApplicationFromMimeType( const char *pchMimeType, const char *pchArgs ) = 0;
+
+		/** Launches the dashboard overlay application if it is not already running. This call is only valid for 
+		* dashboard overlay applications. */
+		virtual EVRApplicationError LaunchDashboardOverlay( const char *pchAppKey ) = 0;
+
+		/** Cancel a pending launch for an application */
+		virtual bool CancelApplicationLaunch( const char *pchAppKey ) = 0;
+
+		/** Identifies a running application. OpenVR can't always tell which process started in response
+		* to a URL. This function allows a URL handler (or the process itself) to identify the app key 
+		* for the now running application. Passing a process ID of 0 identifies the calling process. 
+		* The application must be one that's known to the system via a call to AddApplicationManifest. */
+		virtual EVRApplicationError IdentifyApplication( uint32_t unProcessId, const char *pchAppKey ) = 0;
+
+		/** Returns the process ID for an application. Return 0 if the application was not found or is not running. */
+		virtual uint32_t GetApplicationProcessId( const char *pchAppKey ) = 0;
+
+		/** Returns a string for an applications error */
+		virtual const char *GetApplicationsErrorNameFromEnum( EVRApplicationError error ) = 0;
+
+		// ---------------  Application properties  --------------- //
+
+		/** Returns a value for an application property. The required buffer size to fit this value will be returned. */
+		virtual uint32_t GetApplicationPropertyString( const char *pchAppKey, EVRApplicationProperty eProperty, VR_OUT_STRING() char *pchPropertyValueBuffer, uint32_t unPropertyValueBufferLen, EVRApplicationError *peError = nullptr ) = 0;
+
+		/** Returns a bool value for an application property. Returns false in all error cases. */
+		virtual bool GetApplicationPropertyBool( const char *pchAppKey, EVRApplicationProperty eProperty, EVRApplicationError *peError = nullptr ) = 0;
+
+		/** Returns a uint64 value for an application property. Returns 0 in all error cases. */
+		virtual uint64_t GetApplicationPropertyUint64( const char *pchAppKey, EVRApplicationProperty eProperty, EVRApplicationError *peError = nullptr ) = 0;
+
+		/** Sets the application auto-launch flag. This is only valid for applications which return true for VRApplicationProperty_IsDashboardOverlay_Bool. */
+		virtual EVRApplicationError SetApplicationAutoLaunch( const char *pchAppKey, bool bAutoLaunch ) = 0;
+
+		/** Gets the application auto-launch flag. This is only valid for applications which return true for VRApplicationProperty_IsDashboardOverlay_Bool. */
+		virtual bool GetApplicationAutoLaunch( const char *pchAppKey ) = 0;
+
+		/** Adds this mime-type to the list of supported mime types for this application*/
+		virtual EVRApplicationError SetDefaultApplicationForMimeType( const char *pchAppKey, const char *pchMimeType ) = 0;
+
+		/** return the app key that will open this mime type */
+		virtual bool GetDefaultApplicationForMimeType( const char *pchMimeType, char *pchAppKeyBuffer, uint32_t unAppKeyBufferLen ) = 0;
+
+		/** Get the list of supported mime types for this application, comma-delimited */
+		virtual bool GetApplicationSupportedMimeTypes( const char *pchAppKey, char *pchMimeTypesBuffer, uint32_t unMimeTypesBuffer ) = 0;
+
+		/** Get the list of app-keys that support this mime type, comma-delimited, the return value is number of bytes you need to return the full string */
+		virtual uint32_t GetApplicationsThatSupportMimeType( const char *pchMimeType, char *pchAppKeysThatSupportBuffer, uint32_t unAppKeysThatSupportBuffer ) = 0;
+
+		/** Get the args list from an app launch that had the process already running, you call this when you get a VREvent_ApplicationMimeTypeLoad */
+		virtual uint32_t GetApplicationLaunchArguments( uint32_t unHandle, char *pchArgs, uint32_t unArgs ) = 0;
+
+		// ---------------  Transition methods --------------- //
+
+		/** Returns the app key for the application that is starting up */
+		virtual EVRApplicationError GetStartingApplication( char *pchAppKeyBuffer, uint32_t unAppKeyBufferLen ) = 0;
+
+		/** Returns the application transition state */
+		virtual EVRApplicationTransitionState GetTransitionState() = 0;
+
+		/** Returns errors that would prevent the specified application from launching immediately. Calling this function will
+		* cause the current scene application to quit, so only call it when you are actually about to launch something else.
+		* What the caller should do about these failures depends on the failure:
+		*   VRApplicationError_OldApplicationQuitting - An existing application has been told to quit. Wait for a VREvent_ProcessQuit
+		*                                               and try again.
+		*   VRApplicationError_ApplicationAlreadyStarting - This application is already starting. This is a permanent failure.
+		*   VRApplicationError_LaunchInProgress	      - A different application is already starting. This is a permanent failure.
+		*   VRApplicationError_None                   - Go ahead and launch. Everything is clear.
+		*/
+		virtual EVRApplicationError PerformApplicationPrelaunchCheck( const char *pchAppKey ) = 0;
+
+		/** Returns a string for an application transition state */
+		virtual const char *GetApplicationsTransitionStateNameFromEnum( EVRApplicationTransitionState state ) = 0;
+
+		/** Returns true if the outgoing scene app has requested a save prompt before exiting */
+		virtual bool IsQuitUserPromptRequested() = 0;
+
+		/** Starts a subprocess within the calling application. This
+		* suppresses all application transition UI and automatically identifies the new executable 
+		* as part of the same application. On success the calling process should exit immediately. 
+		* If working directory is NULL or "" the directory portion of the binary path will be 
+		* the working directory. */
+		virtual EVRApplicationError LaunchInternalProcess( const char *pchBinaryPath, const char *pchArguments, const char *pchWorkingDirectory ) = 0;
+
+		/** Returns the current scene process ID according to the application system. A scene process will get scene
+		* focus once it starts rendering, but it will appear here once it calls VR_Init with the Scene application
+		* type. */
+		virtual uint32_t GetCurrentSceneProcessId() = 0;
+	};
+
+	static const char * const IVRApplications_Version = "IVRApplications_006";
+
+} // namespace vr
+
+// ivrsettings.h
+namespace vr
+{
+	enum EVRSettingsError
+	{
+		VRSettingsError_None = 0,
+		VRSettingsError_IPCFailed = 1,
+		VRSettingsError_WriteFailed = 2,
+		VRSettingsError_ReadFailed = 3,
+		VRSettingsError_JsonParseFailed = 4,
+		VRSettingsError_UnsetSettingHasNoDefault = 5, // This will be returned if the setting does not appear in the appropriate default file and has not been set
+	};
+
+	// The maximum length of a settings key
+	static const uint32_t k_unMaxSettingsKeyLength = 128;
+
+	class IVRSettings
+	{
+	public:
+		virtual const char *GetSettingsErrorNameFromEnum( EVRSettingsError eError ) = 0;
+
+		// Returns true if file sync occurred (force or settings dirty)
+		virtual bool Sync( bool bForce = false, EVRSettingsError *peError = nullptr ) = 0;
+
+		virtual void SetBool( const char *pchSection, const char *pchSettingsKey, bool bValue, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void SetInt32( const char *pchSection, const char *pchSettingsKey, int32_t nValue, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void SetFloat( const char *pchSection, const char *pchSettingsKey, float flValue, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void SetString( const char *pchSection, const char *pchSettingsKey, const char *pchValue, EVRSettingsError *peError = nullptr ) = 0;
+
+		// Users of the system need to provide a proper default in default.vrsettings in the resources/settings/ directory
+		// of either the runtime or the driver_xxx directory. Otherwise the default will be false, 0, 0.0 or ""
+		virtual bool GetBool( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0;
+		virtual int32_t GetInt32( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0;
+		virtual float GetFloat( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void GetString( const char *pchSection, const char *pchSettingsKey, VR_OUT_STRING() char *pchValue, uint32_t unValueLen, EVRSettingsError *peError = nullptr ) = 0;
+
+		virtual void RemoveSection( const char *pchSection, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void RemoveKeyInSection( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0;
+	};
+
+	//-----------------------------------------------------------------------------
+	static const char * const IVRSettings_Version = "IVRSettings_002";
+
+	//-----------------------------------------------------------------------------
+	// steamvr keys
+	static const char * const k_pch_SteamVR_Section = "steamvr";
+	static const char * const k_pch_SteamVR_RequireHmd_String = "requireHmd";
+	static const char * const k_pch_SteamVR_ForcedDriverKey_String = "forcedDriver";
+	static const char * const k_pch_SteamVR_ForcedHmdKey_String = "forcedHmd";
+	static const char * const k_pch_SteamVR_DisplayDebug_Bool = "displayDebug";
+	static const char * const k_pch_SteamVR_DebugProcessPipe_String = "debugProcessPipe";
+	static const char * const k_pch_SteamVR_EnableDistortion_Bool = "enableDistortion";
+	static const char * const k_pch_SteamVR_DisplayDebugX_Int32 = "displayDebugX";
+	static const char * const k_pch_SteamVR_DisplayDebugY_Int32 = "displayDebugY";
+	static const char * const k_pch_SteamVR_SendSystemButtonToAllApps_Bool= "sendSystemButtonToAllApps";
+	static const char * const k_pch_SteamVR_LogLevel_Int32 = "loglevel";
+	static const char * const k_pch_SteamVR_IPD_Float = "ipd";
+	static const char * const k_pch_SteamVR_Background_String = "background";
+	static const char * const k_pch_SteamVR_BackgroundUseDomeProjection_Bool = "backgroundUseDomeProjection";
+	static const char * const k_pch_SteamVR_BackgroundCameraHeight_Float = "backgroundCameraHeight";
+	static const char * const k_pch_SteamVR_BackgroundDomeRadius_Float = "backgroundDomeRadius";
+	static const char * const k_pch_SteamVR_GridColor_String = "gridColor";
+	static const char * const k_pch_SteamVR_PlayAreaColor_String = "playAreaColor";
+	static const char * const k_pch_SteamVR_ShowStage_Bool = "showStage";
+	static const char * const k_pch_SteamVR_ActivateMultipleDrivers_Bool = "activateMultipleDrivers";
+	static const char * const k_pch_SteamVR_DirectMode_Bool = "directMode";
+	static const char * const k_pch_SteamVR_DirectModeEdidVid_Int32 = "directModeEdidVid";
+	static const char * const k_pch_SteamVR_DirectModeEdidPid_Int32 = "directModeEdidPid";
+	static const char * const k_pch_SteamVR_UsingSpeakers_Bool = "usingSpeakers";
+	static const char * const k_pch_SteamVR_SpeakersForwardYawOffsetDegrees_Float = "speakersForwardYawOffsetDegrees";
+	static const char * const k_pch_SteamVR_BaseStationPowerManagement_Bool = "basestationPowerManagement";
+	static const char * const k_pch_SteamVR_NeverKillProcesses_Bool = "neverKillProcesses";
+	static const char * const k_pch_SteamVR_RenderTargetMultiplier_Float = "renderTargetMultiplier";
+	static const char * const k_pch_SteamVR_AllowAsyncReprojection_Bool = "allowAsyncReprojection";
+	static const char * const k_pch_SteamVR_AllowReprojection_Bool = "allowInterleavedReprojection";
+	static const char * const k_pch_SteamVR_ForceReprojection_Bool = "forceReprojection";
+	static const char * const k_pch_SteamVR_ForceFadeOnBadTracking_Bool = "forceFadeOnBadTracking";
+	static const char * const k_pch_SteamVR_DefaultMirrorView_Int32 = "defaultMirrorView";
+	static const char * const k_pch_SteamVR_ShowMirrorView_Bool = "showMirrorView";
+	static const char * const k_pch_SteamVR_MirrorViewGeometry_String = "mirrorViewGeometry";
+	static const char * const k_pch_SteamVR_StartMonitorFromAppLaunch = "startMonitorFromAppLaunch";
+	static const char * const k_pch_SteamVR_StartCompositorFromAppLaunch_Bool = "startCompositorFromAppLaunch";
+	static const char * const k_pch_SteamVR_StartDashboardFromAppLaunch_Bool = "startDashboardFromAppLaunch";
+	static const char * const k_pch_SteamVR_StartOverlayAppsFromDashboard_Bool = "startOverlayAppsFromDashboard";
+	static const char * const k_pch_SteamVR_EnableHomeApp = "enableHomeApp";
+	static const char * const k_pch_SteamVR_SetInitialDefaultHomeApp = "setInitialDefaultHomeApp";
+	static const char * const k_pch_SteamVR_CycleBackgroundImageTimeSec_Int32 = "CycleBackgroundImageTimeSec";
+	static const char * const k_pch_SteamVR_RetailDemo_Bool = "retailDemo";
+	static const char * const k_pch_SteamVR_IpdOffset_Float = "ipdOffset";
+
+	//-----------------------------------------------------------------------------
+	// lighthouse keys
+	static const char * const k_pch_Lighthouse_Section = "driver_lighthouse";
+	static const char * const k_pch_Lighthouse_DisableIMU_Bool = "disableimu";
+	static const char * const k_pch_Lighthouse_UseDisambiguation_String = "usedisambiguation";
+	static const char * const k_pch_Lighthouse_DisambiguationDebug_Int32 = "disambiguationdebug";
+	static const char * const k_pch_Lighthouse_PrimaryBasestation_Int32 = "primarybasestation";
+	static const char * const k_pch_Lighthouse_DBHistory_Bool = "dbhistory";
+
+	//-----------------------------------------------------------------------------
+	// null keys
+	static const char * const k_pch_Null_Section = "driver_null";
+	static const char * const k_pch_Null_SerialNumber_String = "serialNumber";
+	static const char * const k_pch_Null_ModelNumber_String = "modelNumber";
+	static const char * const k_pch_Null_WindowX_Int32 = "windowX";
+	static const char * const k_pch_Null_WindowY_Int32 = "windowY";
+	static const char * const k_pch_Null_WindowWidth_Int32 = "windowWidth";
+	static const char * const k_pch_Null_WindowHeight_Int32 = "windowHeight";
+	static const char * const k_pch_Null_RenderWidth_Int32 = "renderWidth";
+	static const char * const k_pch_Null_RenderHeight_Int32 = "renderHeight";
+	static const char * const k_pch_Null_SecondsFromVsyncToPhotons_Float = "secondsFromVsyncToPhotons";
+	static const char * const k_pch_Null_DisplayFrequency_Float = "displayFrequency";
+
+	//-----------------------------------------------------------------------------
+	// user interface keys
+	static const char * const k_pch_UserInterface_Section = "userinterface";
+	static const char * const k_pch_UserInterface_StatusAlwaysOnTop_Bool = "StatusAlwaysOnTop";
+	static const char * const k_pch_UserInterface_MinimizeToTray_Bool = "MinimizeToTray";
+	static const char * const k_pch_UserInterface_Screenshots_Bool = "screenshots";
+	static const char * const k_pch_UserInterface_ScreenshotType_Int = "screenshotType";
+
+	//-----------------------------------------------------------------------------
+	// notification keys
+	static const char * const k_pch_Notifications_Section = "notifications";
+	static const char * const k_pch_Notifications_DoNotDisturb_Bool = "DoNotDisturb";
+
+	//-----------------------------------------------------------------------------
+	// keyboard keys
+	static const char * const k_pch_Keyboard_Section = "keyboard";
+	static const char * const k_pch_Keyboard_TutorialCompletions = "TutorialCompletions";
+	static const char * const k_pch_Keyboard_ScaleX = "ScaleX";
+	static const char * const k_pch_Keyboard_ScaleY = "ScaleY";
+	static const char * const k_pch_Keyboard_OffsetLeftX = "OffsetLeftX";
+	static const char * const k_pch_Keyboard_OffsetRightX = "OffsetRightX";
+	static const char * const k_pch_Keyboard_OffsetY = "OffsetY";
+	static const char * const k_pch_Keyboard_Smoothing = "Smoothing";
+
+	//-----------------------------------------------------------------------------
+	// perf keys
+	static const char * const k_pch_Perf_Section = "perfcheck";
+	static const char * const k_pch_Perf_HeuristicActive_Bool = "heuristicActive";
+	static const char * const k_pch_Perf_NotifyInHMD_Bool = "warnInHMD";
+	static const char * const k_pch_Perf_NotifyOnlyOnce_Bool = "warnOnlyOnce";
+	static const char * const k_pch_Perf_AllowTimingStore_Bool = "allowTimingStore";
+	static const char * const k_pch_Perf_SaveTimingsOnExit_Bool = "saveTimingsOnExit";
+	static const char * const k_pch_Perf_TestData_Float = "perfTestData";
+
+	//-----------------------------------------------------------------------------
+	// collision bounds keys
+	static const char * const k_pch_CollisionBounds_Section = "collisionBounds";
+	static const char * const k_pch_CollisionBounds_Style_Int32 = "CollisionBoundsStyle";
+	static const char * const k_pch_CollisionBounds_GroundPerimeterOn_Bool = "CollisionBoundsGroundPerimeterOn";
+	static const char * const k_pch_CollisionBounds_CenterMarkerOn_Bool = "CollisionBoundsCenterMarkerOn";
+	static const char * const k_pch_CollisionBounds_PlaySpaceOn_Bool = "CollisionBoundsPlaySpaceOn";
+	static const char * const k_pch_CollisionBounds_FadeDistance_Float = "CollisionBoundsFadeDistance";
+	static const char * const k_pch_CollisionBounds_ColorGammaR_Int32 = "CollisionBoundsColorGammaR";
+	static const char * const k_pch_CollisionBounds_ColorGammaG_Int32 = "CollisionBoundsColorGammaG";
+	static const char * const k_pch_CollisionBounds_ColorGammaB_Int32 = "CollisionBoundsColorGammaB";
+	static const char * const k_pch_CollisionBounds_ColorGammaA_Int32 = "CollisionBoundsColorGammaA";
+
+	//-----------------------------------------------------------------------------
+	// camera keys
+	static const char * const k_pch_Camera_Section = "camera";
+	static const char * const k_pch_Camera_EnableCamera_Bool = "enableCamera";
+	static const char * const k_pch_Camera_EnableCameraInDashboard_Bool = "enableCameraInDashboard";
+	static const char * const k_pch_Camera_EnableCameraForCollisionBounds_Bool = "enableCameraForCollisionBounds";
+	static const char * const k_pch_Camera_EnableCameraForRoomView_Bool = "enableCameraForRoomView";
+	static const char * const k_pch_Camera_BoundsColorGammaR_Int32 = "cameraBoundsColorGammaR";
+	static const char * const k_pch_Camera_BoundsColorGammaG_Int32 = "cameraBoundsColorGammaG";
+	static const char * const k_pch_Camera_BoundsColorGammaB_Int32 = "cameraBoundsColorGammaB";
+	static const char * const k_pch_Camera_BoundsColorGammaA_Int32 = "cameraBoundsColorGammaA";
+	static const char * const k_pch_Camera_BoundsStrength_Int32 = "cameraBoundsStrength";
+
+	//-----------------------------------------------------------------------------
+	// audio keys
+	static const char * const k_pch_audio_Section = "audio";
+	static const char * const k_pch_audio_OnPlaybackDevice_String = "onPlaybackDevice";
+	static const char * const k_pch_audio_OnRecordDevice_String = "onRecordDevice";
+	static const char * const k_pch_audio_OnPlaybackMirrorDevice_String = "onPlaybackMirrorDevice";
+	static const char * const k_pch_audio_OffPlaybackDevice_String = "offPlaybackDevice";
+	static const char * const k_pch_audio_OffRecordDevice_String = "offRecordDevice";
+	static const char * const k_pch_audio_VIVEHDMIGain = "viveHDMIGain";
+
+	//-----------------------------------------------------------------------------
+	// power management keys
+	static const char * const k_pch_Power_Section = "power";
+	static const char * const k_pch_Power_PowerOffOnExit_Bool = "powerOffOnExit";
+	static const char * const k_pch_Power_TurnOffScreensTimeout_Float = "turnOffScreensTimeout";
+	static const char * const k_pch_Power_TurnOffControllersTimeout_Float = "turnOffControllersTimeout";
+	static const char * const k_pch_Power_ReturnToWatchdogTimeout_Float = "returnToWatchdogTimeout";
+	static const char * const k_pch_Power_AutoLaunchSteamVROnButtonPress = "autoLaunchSteamVROnButtonPress";
+
+	//-----------------------------------------------------------------------------
+	// dashboard keys
+	static const char * const k_pch_Dashboard_Section = "dashboard";
+	static const char * const k_pch_Dashboard_EnableDashboard_Bool = "enableDashboard";
+	static const char * const k_pch_Dashboard_ArcadeMode_Bool = "arcadeMode";
+
+	//-----------------------------------------------------------------------------
+	// model skin keys
+	static const char * const k_pch_modelskin_Section = "modelskins";
+
+	//-----------------------------------------------------------------------------
+	// driver keys - These could be checked in any driver_<name> section
+	static const char * const k_pch_Driver_Enable_Bool = "enable";
+
+} // namespace vr
+
+// ivrchaperone.h
+namespace vr
+{
+
+#if defined(__linux__) || defined(__APPLE__) 
+	// The 32-bit version of gcc has the alignment requirement for uint64 and double set to
+	// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned.
+	// The 64-bit version of gcc has the alignment requirement for these types set to
+	// 8 meaning that unless we use #pragma pack(4) our structures will get bigger.
+	// The 64-bit structure packing has to match the 32-bit structure packing for each platform.
+	#pragma pack( push, 4 )
+#else
+	#pragma pack( push, 8 )
+#endif
+
+enum ChaperoneCalibrationState
+{
+	// OK!
+	ChaperoneCalibrationState_OK = 1,									// Chaperone is fully calibrated and working correctly
+
+	// Warnings
+	ChaperoneCalibrationState_Warning = 100,
+	ChaperoneCalibrationState_Warning_BaseStationMayHaveMoved = 101,	// A base station thinks that it might have moved
+	ChaperoneCalibrationState_Warning_BaseStationRemoved = 102,			// There are less base stations than when calibrated
+	ChaperoneCalibrationState_Warning_SeatedBoundsInvalid = 103,		// Seated bounds haven't been calibrated for the current tracking center
+
+	// Errors
+	ChaperoneCalibrationState_Error = 200,								// The UniverseID is invalid
+	ChaperoneCalibrationState_Error_BaseStationUninitialized = 201,		// Tracking center hasn't be calibrated for at least one of the base stations
+	ChaperoneCalibrationState_Error_BaseStationConflict = 202,			// Tracking center is calibrated, but base stations disagree on the tracking space
+	ChaperoneCalibrationState_Error_PlayAreaInvalid = 203,				// Play Area hasn't been calibrated for the current tracking center
+	ChaperoneCalibrationState_Error_CollisionBoundsInvalid = 204,		// Collision Bounds haven't been calibrated for the current tracking center
+};
+
+
+/** HIGH LEVEL TRACKING SPACE ASSUMPTIONS:
+* 0,0,0 is the preferred standing area center.
+* 0Y is the floor height.
+* -Z is the preferred forward facing direction. */
+class IVRChaperone
+{
+public:
+
+	/** Get the current state of Chaperone calibration. This state can change at any time during a session due to physical base station changes. **/
+	virtual ChaperoneCalibrationState GetCalibrationState() = 0;
+
+	/** Returns the width and depth of the Play Area (formerly named Soft Bounds) in X and Z. 
+	* Tracking space center (0,0,0) is the center of the Play Area. **/
+	virtual bool GetPlayAreaSize( float *pSizeX, float *pSizeZ ) = 0;
+
+	/** Returns the 4 corner positions of the Play Area (formerly named Soft Bounds).
+	* Corners are in counter-clockwise order.
+	* Standing center (0,0,0) is the center of the Play Area.
+	* It's a rectangle.
+	* 2 sides are parallel to the X axis and 2 sides are parallel to the Z axis.
+	* Height of every corner is 0Y (on the floor). **/
+	virtual bool GetPlayAreaRect( HmdQuad_t *rect ) = 0;
+
+	/** Reload Chaperone data from the .vrchap file on disk. */
+	virtual void ReloadInfo( void ) = 0;
+
+	/** Optionally give the chaperone system a hit about the color and brightness in the scene **/
+	virtual void SetSceneColor( HmdColor_t color ) = 0;
+
+	/** Get the current chaperone bounds draw color and brightness **/
+	virtual void GetBoundsColor( HmdColor_t *pOutputColorArray, int nNumOutputColors, float flCollisionBoundsFadeDistance, HmdColor_t *pOutputCameraColor ) = 0;
+
+	/** Determine whether the bounds are showing right now **/
+	virtual bool AreBoundsVisible() = 0;
+
+	/** Force the bounds to show, mostly for utilities **/
+	virtual void ForceBoundsVisible( bool bForce ) = 0;
+};
+
+static const char * const IVRChaperone_Version = "IVRChaperone_003";
+
+#pragma pack( pop )
+
+}
+
+// ivrchaperonesetup.h
+namespace vr
+{
+
+enum EChaperoneConfigFile
+{
+	EChaperoneConfigFile_Live = 1,		// The live chaperone config, used by most applications and games
+	EChaperoneConfigFile_Temp = 2,		// The temporary chaperone config, used to live-preview collision bounds in room setup
+};
+
+enum EChaperoneImportFlags
+{
+	EChaperoneImport_BoundsOnly = 0x0001,
+};
+
+/** Manages the working copy of the chaperone info. By default this will be the same as the 
+* live copy. Any changes made with this interface will stay in the working copy until 
+* CommitWorkingCopy() is called, at which point the working copy and the live copy will be 
+* the same again. */
+class IVRChaperoneSetup
+{
+public:
+
+	/** Saves the current working copy to disk */
+	virtual bool CommitWorkingCopy( EChaperoneConfigFile configFile ) = 0;
+
+	/** Reverts the working copy to match the live chaperone calibration.
+	* To modify existing data this MUST be do WHILE getting a non-error ChaperoneCalibrationStatus.
+	* Only after this should you do gets and sets on the existing data. */
+	virtual void RevertWorkingCopy() = 0;
+
+	/** Returns the width and depth of the Play Area (formerly named Soft Bounds) in X and Z from the working copy.
+	* Tracking space center (0,0,0) is the center of the Play Area. */
+	virtual bool GetWorkingPlayAreaSize( float *pSizeX, float *pSizeZ ) = 0;
+
+	/** Returns the 4 corner positions of the Play Area (formerly named Soft Bounds) from the working copy.
+	* Corners are in clockwise order.
+	* Tracking space center (0,0,0) is the center of the Play Area.
+	* It's a rectangle.
+	* 2 sides are parallel to the X axis and 2 sides are parallel to the Z axis.
+	* Height of every corner is 0Y (on the floor). **/
+	virtual bool GetWorkingPlayAreaRect( HmdQuad_t *rect ) = 0;
+
+	/** Returns the number of Quads if the buffer points to null. Otherwise it returns Quads 
+	* into the buffer up to the max specified from the working copy. */
+	virtual bool GetWorkingCollisionBoundsInfo( VR_OUT_ARRAY_COUNT(punQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t* punQuadsCount ) = 0;
+
+	/** Returns the number of Quads if the buffer points to null. Otherwise it returns Quads 
+	* into the buffer up to the max specified. */
+	virtual bool GetLiveCollisionBoundsInfo( VR_OUT_ARRAY_COUNT(punQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t* punQuadsCount ) = 0;
+
+	/** Returns the preferred seated position from the working copy. */
+	virtual bool GetWorkingSeatedZeroPoseToRawTrackingPose( HmdMatrix34_t *pmatSeatedZeroPoseToRawTrackingPose ) = 0;
+
+	/** Returns the standing origin from the working copy. */
+	virtual bool GetWorkingStandingZeroPoseToRawTrackingPose( HmdMatrix34_t *pmatStandingZeroPoseToRawTrackingPose ) = 0;
+
+	/** Sets the Play Area in the working copy. */
+	virtual void SetWorkingPlayAreaSize( float sizeX, float sizeZ ) = 0;
+
+	/** Sets the Collision Bounds in the working copy. */
+	virtual void SetWorkingCollisionBoundsInfo( VR_ARRAY_COUNT(unQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t unQuadsCount ) = 0;
+
+	/** Sets the preferred seated position in the working copy. */
+	virtual void SetWorkingSeatedZeroPoseToRawTrackingPose( const HmdMatrix34_t *pMatSeatedZeroPoseToRawTrackingPose ) = 0;
+
+	/** Sets the preferred standing position in the working copy. */
+	virtual void SetWorkingStandingZeroPoseToRawTrackingPose( const HmdMatrix34_t *pMatStandingZeroPoseToRawTrackingPose ) = 0;
+
+	/** Tear everything down and reload it from the file on disk */
+	virtual void ReloadFromDisk( EChaperoneConfigFile configFile ) = 0;
+
+	/** Returns the preferred seated position. */
+	virtual bool GetLiveSeatedZeroPoseToRawTrackingPose( HmdMatrix34_t *pmatSeatedZeroPoseToRawTrackingPose ) = 0;
+
+	virtual void SetWorkingCollisionBoundsTagsInfo( VR_ARRAY_COUNT(unTagCount) uint8_t *pTagsBuffer, uint32_t unTagCount ) = 0;
+	virtual bool GetLiveCollisionBoundsTagsInfo( VR_OUT_ARRAY_COUNT(punTagCount) uint8_t *pTagsBuffer, uint32_t *punTagCount ) = 0;
+
+	virtual bool SetWorkingPhysicalBoundsInfo( VR_ARRAY_COUNT(unQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t unQuadsCount ) = 0;
+	virtual bool GetLivePhysicalBoundsInfo( VR_OUT_ARRAY_COUNT(punQuadsCount) HmdQuad_t *pQuadsBuffer, uint32_t* punQuadsCount ) = 0;
+
+	virtual bool ExportLiveToBuffer( VR_OUT_STRING() char *pBuffer, uint32_t *pnBufferLength ) = 0;
+	virtual bool ImportFromBufferToWorking( const char *pBuffer, uint32_t nImportFlags ) = 0;
+};
+
+static const char * const IVRChaperoneSetup_Version = "IVRChaperoneSetup_005";
+
+
+}
+
+// ivrcompositor.h
+namespace vr
+{
+
+#if defined(__linux__) || defined(__APPLE__) 
+	// The 32-bit version of gcc has the alignment requirement for uint64 and double set to
+	// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned.
+	// The 64-bit version of gcc has the alignment requirement for these types set to
+	// 8 meaning that unless we use #pragma pack(4) our structures will get bigger.
+	// The 64-bit structure packing has to match the 32-bit structure packing for each platform.
+	#pragma pack( push, 4 )
+#else
+	#pragma pack( push, 8 )
+#endif
+
+/** Errors that can occur with the VR compositor */
+enum EVRCompositorError
+{
+	VRCompositorError_None						= 0,
+	VRCompositorError_RequestFailed				= 1,
+	VRCompositorError_IncompatibleVersion		= 100,
+	VRCompositorError_DoNotHaveFocus			= 101,
+	VRCompositorError_InvalidTexture			= 102,
+	VRCompositorError_IsNotSceneApplication		= 103,
+	VRCompositorError_TextureIsOnWrongDevice	= 104,
+	VRCompositorError_TextureUsesUnsupportedFormat = 105,
+	VRCompositorError_SharedTexturesNotSupported = 106,
+	VRCompositorError_IndexOutOfRange			= 107,
+	VRCompositorError_AlreadySubmitted			= 108,
+};
+
+const uint32_t VRCompositor_ReprojectionReason_Cpu = 0x01;
+const uint32_t VRCompositor_ReprojectionReason_Gpu = 0x02;
+const uint32_t VRCompositor_ReprojectionAsync      = 0x04;	// This flag indicates the async reprojection mode is active,
+															// but does not indicate if reprojection actually happened or not.
+															// Use the ReprojectionReason flags above to check if reprojection
+															// was actually applied (i.e. scene texture was reused).
+															// NumFramePresents > 1 also indicates the scene texture was reused,
+															// and also the number of times that it was presented in total.
+
+/** Provides a single frame's timing information to the app */
+struct Compositor_FrameTiming
+{
+	uint32_t m_nSize; // Set to sizeof( Compositor_FrameTiming )
+	uint32_t m_nFrameIndex;
+	uint32_t m_nNumFramePresents; // number of times this frame was presented
+	uint32_t m_nNumMisPresented; // number of times this frame was presented on a vsync other than it was originally predicted to
+	uint32_t m_nNumDroppedFrames; // number of additional times previous frame was scanned out
+	uint32_t m_nReprojectionFlags;
+
+	/** Absolute time reference for comparing frames.  This aligns with the vsync that running start is relative to. */
+	double m_flSystemTimeInSeconds;
+
+	/** These times may include work from other processes due to OS scheduling.
+	* The fewer packets of work these are broken up into, the less likely this will happen.
+	* GPU work can be broken up by calling Flush.  This can sometimes be useful to get the GPU started
+	* processing that work earlier in the frame. */
+	float m_flPreSubmitGpuMs; // time spent rendering the scene (gpu work submitted between WaitGetPoses and second Submit)
+	float m_flPostSubmitGpuMs; // additional time spent rendering by application (e.g. companion window)
+	float m_flTotalRenderGpuMs; // time between work submitted immediately after present (ideally vsync) until the end of compositor submitted work
+	float m_flCompositorRenderGpuMs; // time spend performing distortion correction, rendering chaperone, overlays, etc.
+	float m_flCompositorRenderCpuMs; // time spent on cpu submitting the above work for this frame
+	float m_flCompositorIdleCpuMs; // time spent waiting for running start (application could have used this much more time)
+
+	/** Miscellaneous measured intervals. */
+	float m_flClientFrameIntervalMs; // time between calls to WaitGetPoses
+	float m_flPresentCallCpuMs; // time blocked on call to present (usually 0.0, but can go long)
+	float m_flWaitForPresentCpuMs; // time spent spin-waiting for frame index to change (not near-zero indicates wait object failure)
+	float m_flSubmitFrameMs; // time spent in IVRCompositor::Submit (not near-zero indicates driver issue)
+
+	/** The following are all relative to this frame's SystemTimeInSeconds */
+	float m_flWaitGetPosesCalledMs;
+	float m_flNewPosesReadyMs;
+	float m_flNewFrameReadyMs; // second call to IVRCompositor::Submit
+	float m_flCompositorUpdateStartMs;
+	float m_flCompositorUpdateEndMs;
+	float m_flCompositorRenderStartMs;
+
+	vr::TrackedDevicePose_t m_HmdPose; // pose used by app to render this frame
+};
+
+/** Cumulative stats for current application.  These are not cleared until a new app connects,
+* but they do stop accumulating once the associated app disconnects. */
+struct Compositor_CumulativeStats
+{
+	uint32_t m_nPid; // Process id associated with these stats (may no longer be running).
+	uint32_t m_nNumFramePresents; // total number of times we called present (includes reprojected frames)
+	uint32_t m_nNumDroppedFrames; // total number of times an old frame was re-scanned out (without reprojection)
+	uint32_t m_nNumReprojectedFrames; // total number of times a frame was scanned out a second time (with reprojection)
+
+	/** Values recorded at startup before application has fully faded in the first time. */
+	uint32_t m_nNumFramePresentsOnStartup;
+	uint32_t m_nNumDroppedFramesOnStartup;
+	uint32_t m_nNumReprojectedFramesOnStartup;
+
+	/** Applications may explicitly fade to the compositor.  This is usually to handle level transitions, and loading often causes
+	* system wide hitches.  The following stats are collected during this period.  Does not include values recorded during startup. */
+	uint32_t m_nNumLoading;
+	uint32_t m_nNumFramePresentsLoading;
+	uint32_t m_nNumDroppedFramesLoading;
+	uint32_t m_nNumReprojectedFramesLoading;
+
+	/** If we don't get a new frame from the app in less than 2.5 frames, then we assume the app has hung and start
+	* fading back to the compositor.  The following stats are a result of this, and are a subset of those recorded above.
+	* Does not include values recorded during start up or loading. */
+	uint32_t m_nNumTimedOut;
+	uint32_t m_nNumFramePresentsTimedOut;
+	uint32_t m_nNumDroppedFramesTimedOut;
+	uint32_t m_nNumReprojectedFramesTimedOut;
+};
+
+#pragma pack( pop )
+
+/** Allows the application to interact with the compositor */
+class IVRCompositor
+{
+public:
+	/** Sets tracking space returned by WaitGetPoses */
+	virtual void SetTrackingSpace( ETrackingUniverseOrigin eOrigin ) = 0;
+
+	/** Gets current tracking space returned by WaitGetPoses */
+	virtual ETrackingUniverseOrigin GetTrackingSpace() = 0;
+
+	/** Scene applications should call this function to get poses to render with (and optionally poses predicted an additional frame out to use for gameplay).
+	* This function will block until "running start" milliseconds before the start of the frame, and should be called at the last moment before needing to
+	* start rendering.
+	*
+	* Return codes:
+	*	- IsNotSceneApplication (make sure to call VR_Init with VRApplicaiton_Scene)
+	*	- DoNotHaveFocus (some other app has taken focus - this will throttle the call to 10hz to reduce the impact on that app)
+	*/
+	virtual EVRCompositorError WaitGetPoses( VR_ARRAY_COUNT(unRenderPoseArrayCount) TrackedDevicePose_t* pRenderPoseArray, uint32_t unRenderPoseArrayCount,
+		VR_ARRAY_COUNT(unGamePoseArrayCount) TrackedDevicePose_t* pGamePoseArray, uint32_t unGamePoseArrayCount ) = 0;
+
+	/** Get the last set of poses returned by WaitGetPoses. */
+	virtual EVRCompositorError GetLastPoses( VR_ARRAY_COUNT( unRenderPoseArrayCount ) TrackedDevicePose_t* pRenderPoseArray, uint32_t unRenderPoseArrayCount,
+		VR_ARRAY_COUNT( unGamePoseArrayCount ) TrackedDevicePose_t* pGamePoseArray, uint32_t unGamePoseArrayCount ) = 0;
+
+	/** Interface for accessing last set of poses returned by WaitGetPoses one at a time.
+	* Returns VRCompositorError_IndexOutOfRange if unDeviceIndex not less than k_unMaxTrackedDeviceCount otherwise VRCompositorError_None.
+	* It is okay to pass NULL for either pose if you only want one of the values. */
+	virtual EVRCompositorError GetLastPoseForTrackedDeviceIndex( TrackedDeviceIndex_t unDeviceIndex, TrackedDevicePose_t *pOutputPose, TrackedDevicePose_t *pOutputGamePose ) = 0;
+
+	/** Updated scene texture to display. If pBounds is NULL the entire texture will be used.  If called from an OpenGL app, consider adding a glFlush after
+	* Submitting both frames to signal the driver to start processing, otherwise it may wait until the command buffer fills up, causing the app to miss frames.
+	*
+	* OpenGL dirty state:
+	*	glBindTexture
+	*
+	* Return codes:
+	*	- IsNotSceneApplication (make sure to call VR_Init with VRApplicaiton_Scene)
+	*	- DoNotHaveFocus (some other app has taken focus)
+	*	- TextureIsOnWrongDevice (application did not use proper AdapterIndex - see IVRSystem.GetDXGIOutputInfo)
+	*	- SharedTexturesNotSupported (application needs to call CreateDXGIFactory1 or later before creating DX device)
+	*	- TextureUsesUnsupportedFormat (scene textures must be compatible with DXGI sharing rules - e.g. uncompressed, no mips, etc.)
+	*	- InvalidTexture (usually means bad arguments passed in)
+	*	- AlreadySubmitted (app has submitted two left textures or two right textures in a single frame - i.e. before calling WaitGetPoses again)
+	*/
+	virtual EVRCompositorError Submit( EVREye eEye, const Texture_t *pTexture, const VRTextureBounds_t* pBounds = 0, EVRSubmitFlags nSubmitFlags = Submit_Default ) = 0;
+
+	/** Clears the frame that was sent with the last call to Submit. This will cause the 
+	* compositor to show the grid until Submit is called again. */
+	virtual void ClearLastSubmittedFrame() = 0;
+
+	/** Call immediately after presenting your app's window (i.e. companion window) to unblock the compositor.
+	* This is an optional call, which only needs to be used if you can't instead call WaitGetPoses immediately after Present.
+	* For example, if your engine's render and game loop are not on separate threads, or blocking the render thread until 3ms before the next vsync would
+	* introduce a deadlock of some sort.  This function tells the compositor that you have finished all rendering after having Submitted buffers for both
+	* eyes, and it is free to start its rendering work.  This should only be called from the same thread you are rendering on. */
+	virtual void PostPresentHandoff() = 0;
+
+	/** Returns true if timing data is filled it.  Sets oldest timing info if nFramesAgo is larger than the stored history.
+	* Be sure to set timing.size = sizeof(Compositor_FrameTiming) on struct passed in before calling this function. */
+	virtual bool GetFrameTiming( Compositor_FrameTiming *pTiming, uint32_t unFramesAgo = 0 ) = 0;
+
+	/** Interface for copying a range of timing data.  Frames are returned in ascending order (oldest to newest) with the last being the most recent frame.
+	* Only the first entry's m_nSize needs to be set, as the rest will be inferred from that.  Returns total number of entries filled out. */
+	virtual uint32_t GetFrameTimings( Compositor_FrameTiming *pTiming, uint32_t nFrames ) = 0;
+
+	/** Returns the time in seconds left in the current (as identified by FrameTiming's frameIndex) frame.
+	* Due to "running start", this value may roll over to the next frame before ever reaching 0.0. */
+	virtual float GetFrameTimeRemaining() = 0;
+
+	/** Fills out stats accumulated for the last connected application.  Pass in sizeof( Compositor_CumulativeStats ) as second parameter. */
+	virtual void GetCumulativeStats( Compositor_CumulativeStats *pStats, uint32_t nStatsSizeInBytes ) = 0;
+
+	/** Fades the view on the HMD to the specified color. The fade will take fSeconds, and the color values are between
+	* 0.0 and 1.0. This color is faded on top of the scene based on the alpha parameter. Removing the fade color instantly 
+	* would be FadeToColor( 0.0, 0.0, 0.0, 0.0, 0.0 ).  Values are in un-premultiplied alpha space. */
+	virtual void FadeToColor( float fSeconds, float fRed, float fGreen, float fBlue, float fAlpha, bool bBackground = false ) = 0;
+
+	/** Get current fade color value. */
+	virtual HmdColor_t GetCurrentFadeColor( bool bBackground = false ) = 0;
+
+	/** Fading the Grid in or out in fSeconds */
+	virtual void FadeGrid( float fSeconds, bool bFadeIn ) = 0;
+
+	/** Get current alpha value of grid. */
+	virtual float GetCurrentGridAlpha() = 0;
+
+	/** Override the skybox used in the compositor (e.g. for during level loads when the app can't feed scene images fast enough)
+	* Order is Front, Back, Left, Right, Top, Bottom.  If only a single texture is passed, it is assumed in lat-long format.
+	* If two are passed, it is assumed a lat-long stereo pair. */
+	virtual EVRCompositorError SetSkyboxOverride( VR_ARRAY_COUNT( unTextureCount ) const Texture_t *pTextures, uint32_t unTextureCount ) = 0;
+
+	/** Resets compositor skybox back to defaults. */
+	virtual void ClearSkyboxOverride() = 0;
+
+	/** Brings the compositor window to the front. This is useful for covering any other window that may be on the HMD
+	* and is obscuring the compositor window. */
+	virtual void CompositorBringToFront() = 0;
+
+	/** Pushes the compositor window to the back. This is useful for allowing other applications to draw directly to the HMD. */
+	virtual void CompositorGoToBack() = 0;
+
+	/** Tells the compositor process to clean up and exit. You do not need to call this function at shutdown. Under normal 
+	* circumstances the compositor will manage its own life cycle based on what applications are running. */
+	virtual void CompositorQuit() = 0;
+	
+	/** Return whether the compositor is fullscreen */
+	virtual bool IsFullscreen() = 0;
+
+	/** Returns the process ID of the process that is currently rendering the scene */
+	virtual uint32_t GetCurrentSceneFocusProcess() = 0;
+
+	/** Returns the process ID of the process that rendered the last frame (or 0 if the compositor itself rendered the frame.)
+	* Returns 0 when fading out from an app and the app's process Id when fading into an app. */
+	virtual uint32_t GetLastFrameRenderer() = 0;
+
+	/** Returns true if the current process has the scene focus */
+	virtual bool CanRenderScene() = 0;
+
+	/** Creates a window on the primary monitor to display what is being shown in the headset. */
+	virtual void ShowMirrorWindow() = 0;
+
+	/** Closes the mirror window. */
+	virtual void HideMirrorWindow() = 0;
+
+	/** Returns true if the mirror window is shown. */
+	virtual bool IsMirrorWindowVisible() = 0;
+
+	/** Writes all images that the compositor knows about (including overlays) to a 'screenshots' folder in the SteamVR runtime root. */
+	virtual void CompositorDumpImages() = 0;
+
+	/** Let an app know it should be rendering with low resources. */
+	virtual bool ShouldAppRenderWithLowResources() = 0;
+
+	/** Override interleaved reprojection logic to force on. */
+	virtual void ForceInterleavedReprojectionOn( bool bOverride ) = 0;
+
+	/** Force reconnecting to the compositor process. */
+	virtual void ForceReconnectProcess() = 0;
+
+	/** Temporarily suspends rendering (useful for finer control over scene transitions). */
+	virtual void SuspendRendering( bool bSuspend ) = 0;
+
+	/** Opens a shared D3D11 texture with the undistorted composited image for each eye.  Use ReleaseMirrorTextureD3D11 when finished
+	* instead of calling Release on the resource itself. */
+	virtual vr::EVRCompositorError GetMirrorTextureD3D11( vr::EVREye eEye, void *pD3D11DeviceOrResource, void **ppD3D11ShaderResourceView ) = 0;
+	virtual void ReleaseMirrorTextureD3D11( void *pD3D11ShaderResourceView ) = 0;
+
+	/** Access to mirror textures from OpenGL. */
+	virtual vr::EVRCompositorError GetMirrorTextureGL( vr::EVREye eEye, vr::glUInt_t *pglTextureId, vr::glSharedTextureHandle_t *pglSharedTextureHandle ) = 0;
+	virtual bool ReleaseSharedGLTexture( vr::glUInt_t glTextureId, vr::glSharedTextureHandle_t glSharedTextureHandle ) = 0;
+	virtual void LockGLSharedTextureForAccess( vr::glSharedTextureHandle_t glSharedTextureHandle ) = 0;
+	virtual void UnlockGLSharedTextureForAccess( vr::glSharedTextureHandle_t glSharedTextureHandle ) = 0;
+
+	/** [Vulkan Only]
+	* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing
+	* null.  The string will be a space separated list of-required instance extensions to enable in VkCreateInstance */
+	virtual uint32_t GetVulkanInstanceExtensionsRequired( VR_OUT_STRING() char *pchValue, uint32_t unBufferSize ) = 0;
+
+	/** [Vulkan only]
+	* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing
+	* null.  The string will be a space separated list of required device extensions to enable in VkCreateDevice */
+	virtual uint32_t GetVulkanDeviceExtensionsRequired( VkPhysicalDevice_T *pPhysicalDevice, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize ) = 0;
+
+};
+
+static const char * const IVRCompositor_Version = "IVRCompositor_020";
+
+} // namespace vr
+
+
+
+// ivrnotifications.h
+namespace vr
+{
+
+#if defined(__linux__) || defined(__APPLE__) 
+	// The 32-bit version of gcc has the alignment requirement for uint64 and double set to
+	// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned.
+	// The 64-bit version of gcc has the alignment requirement for these types set to
+	// 8 meaning that unless we use #pragma pack(4) our structures will get bigger.
+	// The 64-bit structure packing has to match the 32-bit structure packing for each platform.
+	#pragma pack( push, 4 )
+#else
+	#pragma pack( push, 8 )
+#endif
+
+// Used for passing graphic data
+struct NotificationBitmap_t
+{
+	NotificationBitmap_t()
+		: m_pImageData( nullptr )
+		, m_nWidth( 0 )
+		, m_nHeight( 0 )
+		, m_nBytesPerPixel( 0 )
+	{
+	};
+
+	void *m_pImageData;
+	int32_t m_nWidth;
+	int32_t m_nHeight;
+	int32_t m_nBytesPerPixel;
+};
+
+
+/** Be aware that the notification type is used as 'priority' to pick the next notification */
+enum EVRNotificationType
+{
+	/** Transient notifications are automatically hidden after a period of time set by the user. 
+	* They are used for things like information and chat messages that do not require user interaction. */
+	EVRNotificationType_Transient = 0,
+
+	/** Persistent notifications are shown to the user until they are hidden by calling RemoveNotification().
+	* They are used for things like phone calls and alarms that require user interaction. */
+	EVRNotificationType_Persistent = 1,
+
+	/** System notifications are shown no matter what. It is expected, that the ulUserValue is used as ID.
+	 * If there is already a system notification in the queue with that ID it is not accepted into the queue
+	 * to prevent spamming with system notification */
+	EVRNotificationType_Transient_SystemWithUserValue = 2,
+};
+
+enum EVRNotificationStyle
+{
+	/** Creates a notification with minimal external styling. */
+	EVRNotificationStyle_None = 0,
+
+	/** Used for notifications about overlay-level status. In Steam this is used for events like downloads completing. */
+	EVRNotificationStyle_Application = 100,
+
+	/** Used for notifications about contacts that are unknown or not available. In Steam this is used for friend invitations and offline friends. */
+	EVRNotificationStyle_Contact_Disabled = 200,
+
+	/** Used for notifications about contacts that are available but inactive. In Steam this is used for friends that are online but not playing a game. */
+	EVRNotificationStyle_Contact_Enabled = 201,
+
+	/** Used for notifications about contacts that are available and active. In Steam this is used for friends that are online and currently running a game. */
+	EVRNotificationStyle_Contact_Active = 202,
+};
+
+static const uint32_t k_unNotificationTextMaxSize = 256;
+
+typedef uint32_t VRNotificationId;
+
+
+
+#pragma pack( pop )
+
+/** Allows notification sources to interact with the VR system
+	This current interface is not yet implemented. Do not use yet. */
+class IVRNotifications
+{
+public:
+	/** Create a notification and enqueue it to be shown to the user.
+	* An overlay handle is required to create a notification, as otherwise it would be impossible for a user to act on it.
+	* To create a two-line notification, use a line break ('\n') to split the text into two lines.
+	* The pImage argument may be NULL, in which case the specified overlay's icon will be used instead. */
+	virtual EVRNotificationError CreateNotification( VROverlayHandle_t ulOverlayHandle, uint64_t ulUserValue, EVRNotificationType type, const char *pchText, EVRNotificationStyle style, const NotificationBitmap_t *pImage, /* out */ VRNotificationId *pNotificationId ) = 0;
+
+	/** Destroy a notification, hiding it first if it currently shown to the user. */
+	virtual EVRNotificationError RemoveNotification( VRNotificationId notificationId ) = 0;
+
+};
+
+static const char * const IVRNotifications_Version = "IVRNotifications_002";
+
+} // namespace vr
+
+
+
+// ivroverlay.h
+namespace vr
+{
+
+	/** The maximum length of an overlay key in bytes, counting the terminating null character. */
+	static const uint32_t k_unVROverlayMaxKeyLength = 128;
+
+	/** The maximum length of an overlay name in bytes, counting the terminating null character. */
+	static const uint32_t k_unVROverlayMaxNameLength = 128;
+
+	/** The maximum number of overlays that can exist in the system at one time. */
+	static const uint32_t k_unMaxOverlayCount = 64;
+
+	/** The maximum number of overlay intersection mask primitives per overlay */
+	static const uint32_t k_unMaxOverlayIntersectionMaskPrimitivesCount = 32;
+
+	/** Types of input supported by VR Overlays */
+	enum VROverlayInputMethod
+	{
+		VROverlayInputMethod_None		= 0, // No input events will be generated automatically for this overlay
+		VROverlayInputMethod_Mouse		= 1, // Tracked controllers will get mouse events automatically
+	};
+
+	/** Allows the caller to figure out which overlay transform getter to call. */
+	enum VROverlayTransformType
+	{
+		VROverlayTransform_Absolute					= 0,
+		VROverlayTransform_TrackedDeviceRelative	= 1,
+		VROverlayTransform_SystemOverlay			= 2,
+		VROverlayTransform_TrackedComponent 		= 3,
+	};
+
+	/** Overlay control settings */
+	enum VROverlayFlags
+	{
+		VROverlayFlags_None			= 0,
+
+		// The following only take effect when rendered using the high quality render path (see SetHighQualityOverlay).
+		VROverlayFlags_Curved		= 1,
+		VROverlayFlags_RGSS4X		= 2,
+
+		// Set this flag on a dashboard overlay to prevent a tab from showing up for that overlay
+		VROverlayFlags_NoDashboardTab = 3,
+
+		// Set this flag on a dashboard that is able to deal with gamepad focus events
+		VROverlayFlags_AcceptsGamepadEvents = 4,
+
+		// Indicates that the overlay should dim/brighten to show gamepad focus
+		VROverlayFlags_ShowGamepadFocus = 5,
+
+		// When in VROverlayInputMethod_Mouse you can optionally enable sending VRScroll_t 
+		VROverlayFlags_SendVRScrollEvents = 6,
+		VROverlayFlags_SendVRTouchpadEvents = 7,
+
+		// If set this will render a vertical scroll wheel on the primary controller, 
+		//  only needed if not using VROverlayFlags_SendVRScrollEvents but you still want to represent a scroll wheel
+		VROverlayFlags_ShowTouchPadScrollWheel = 8,
+
+		// If this is set ownership and render access to the overlay are transferred 
+		// to the new scene process on a call to IVRApplications::LaunchInternalProcess
+		VROverlayFlags_TransferOwnershipToInternalProcess = 9,
+
+		// If set, renders 50% of the texture in each eye, side by side
+		VROverlayFlags_SideBySide_Parallel = 10, // Texture is left/right
+		VROverlayFlags_SideBySide_Crossed = 11, // Texture is crossed and right/left
+
+		VROverlayFlags_Panorama = 12, // Texture is a panorama
+		VROverlayFlags_StereoPanorama = 13, // Texture is a stereo panorama
+
+		// If this is set on an overlay owned by the scene application that overlay
+		// will be sorted with the "Other" overlays on top of all other scene overlays
+		VROverlayFlags_SortWithNonSceneOverlays = 14,
+
+		// If set, the overlay will be shown in the dashboard, otherwise it will be hidden.
+		VROverlayFlags_VisibleInDashboard = 15,
+	};
+
+	enum VRMessageOverlayResponse
+	{
+		VRMessageOverlayResponse_ButtonPress_0 = 0,
+		VRMessageOverlayResponse_ButtonPress_1 = 1,
+		VRMessageOverlayResponse_ButtonPress_2 = 2,
+		VRMessageOverlayResponse_ButtonPress_3 = 3,
+		VRMessageOverlayResponse_CouldntFindSystemOverlay = 4,
+		VRMessageOverlayResponse_CouldntFindOrCreateClientOverlay= 5,
+		VRMessageOverlayResponse_ApplicationQuit = 6
+	};
+
+	struct VROverlayIntersectionParams_t
+	{
+		HmdVector3_t vSource;
+		HmdVector3_t vDirection;
+		ETrackingUniverseOrigin eOrigin;
+	};
+
+	struct VROverlayIntersectionResults_t
+	{
+		HmdVector3_t vPoint;
+		HmdVector3_t vNormal;
+		HmdVector2_t vUVs;
+		float fDistance;
+	};
+
+	// Input modes for the Big Picture gamepad text entry
+	enum EGamepadTextInputMode
+	{
+		k_EGamepadTextInputModeNormal = 0,
+		k_EGamepadTextInputModePassword = 1,
+		k_EGamepadTextInputModeSubmit = 2,
+	};
+
+	// Controls number of allowed lines for the Big Picture gamepad text entry
+	enum EGamepadTextInputLineMode
+	{
+		k_EGamepadTextInputLineModeSingleLine = 0,
+		k_EGamepadTextInputLineModeMultipleLines = 1
+	};
+
+	/** Directions for changing focus between overlays with the gamepad */
+	enum EOverlayDirection
+	{
+		OverlayDirection_Up = 0,
+		OverlayDirection_Down = 1,
+		OverlayDirection_Left = 2,
+		OverlayDirection_Right = 3,
+		
+		OverlayDirection_Count = 4,
+	};
+
+	enum EVROverlayIntersectionMaskPrimitiveType
+	{
+		OverlayIntersectionPrimitiveType_Rectangle,
+		OverlayIntersectionPrimitiveType_Circle,
+	};
+
+	struct IntersectionMaskRectangle_t
+	{
+		float m_flTopLeftX;
+		float m_flTopLeftY;
+		float m_flWidth;
+		float m_flHeight;
+	};
+
+	struct IntersectionMaskCircle_t
+	{
+		float m_flCenterX;
+		float m_flCenterY;
+		float m_flRadius;
+	};
+
+	/** NOTE!!! If you change this you MUST manually update openvr_interop.cs.py and openvr_api_flat.h.py */
+	typedef union
+	{
+		IntersectionMaskRectangle_t m_Rectangle;
+		IntersectionMaskCircle_t m_Circle;
+	} VROverlayIntersectionMaskPrimitive_Data_t;
+
+	struct VROverlayIntersectionMaskPrimitive_t
+	{
+		EVROverlayIntersectionMaskPrimitiveType m_nPrimitiveType;
+		VROverlayIntersectionMaskPrimitive_Data_t m_Primitive;
+	};
+
+	class IVROverlay
+	{
+	public:
+
+		// ---------------------------------------------
+		// Overlay management methods
+		// ---------------------------------------------
+
+		/** Finds an existing overlay with the specified key. */
+		virtual EVROverlayError FindOverlay( const char *pchOverlayKey, VROverlayHandle_t * pOverlayHandle ) = 0;
+
+		/** Creates a new named overlay. All overlays start hidden and with default settings. */
+		virtual EVROverlayError CreateOverlay( const char *pchOverlayKey, const char *pchOverlayFriendlyName, VROverlayHandle_t * pOverlayHandle ) = 0;
+
+		/** Destroys the specified overlay. When an application calls VR_Shutdown all overlays created by that app are
+		* automatically destroyed. */
+		virtual EVROverlayError DestroyOverlay( VROverlayHandle_t ulOverlayHandle ) = 0;
+
+		/** Specify which overlay to use the high quality render path.  This overlay will be composited in during the distortion pass which
+		* results in it drawing on top of everything else, but also at a higher quality as it samples the source texture directly rather than
+		* rasterizing into each eye's render texture first.  Because if this, only one of these is supported at any given time.  It is most useful
+		* for overlays that are expected to take up most of the user's view (e.g. streaming video).
+		* This mode does not support mouse input to your overlay. */
+		virtual EVROverlayError SetHighQualityOverlay( VROverlayHandle_t ulOverlayHandle ) = 0;
+
+		/** Returns the overlay handle of the current overlay being rendered using the single high quality overlay render path.
+		* Otherwise it will return k_ulOverlayHandleInvalid. */
+		virtual vr::VROverlayHandle_t GetHighQualityOverlay() = 0;
+
+		/** Fills the provided buffer with the string key of the overlay. Returns the size of buffer required to store the key, including
+		* the terminating null character. k_unVROverlayMaxKeyLength will be enough bytes to fit the string. */
+		virtual uint32_t GetOverlayKey( VROverlayHandle_t ulOverlayHandle, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, EVROverlayError *pError = 0L ) = 0;
+
+		/** Fills the provided buffer with the friendly name of the overlay. Returns the size of buffer required to store the key, including
+		* the terminating null character. k_unVROverlayMaxNameLength will be enough bytes to fit the string. */
+		virtual uint32_t GetOverlayName( VROverlayHandle_t ulOverlayHandle, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, EVROverlayError *pError = 0L ) = 0;
+
+		/** Gets the raw image data from an overlay. Overlay image data is always returned as RGBA data, 4 bytes per pixel. If the buffer is not large enough, width and height 
+		* will be set and VROverlayError_ArrayTooSmall is returned. */
+		virtual EVROverlayError GetOverlayImageData( VROverlayHandle_t ulOverlayHandle, void *pvBuffer, uint32_t unBufferSize, uint32_t *punWidth, uint32_t *punHeight ) = 0;
+
+		/** returns a string that corresponds with the specified overlay error. The string will be the name 
+		* of the error enum value for all valid error codes */
+		virtual const char *GetOverlayErrorNameFromEnum( EVROverlayError error ) = 0;
+
+
+		// ---------------------------------------------
+		// Overlay rendering methods
+		// ---------------------------------------------
+
+		/** Sets the pid that is allowed to render to this overlay (the creator pid is always allow to render),
+		*	by default this is the pid of the process that made the overlay */
+		virtual EVROverlayError SetOverlayRenderingPid( VROverlayHandle_t ulOverlayHandle, uint32_t unPID ) = 0;
+
+		/** Gets the pid that is allowed to render to this overlay */
+		virtual uint32_t GetOverlayRenderingPid( VROverlayHandle_t ulOverlayHandle ) = 0;
+
+		/** Specify flag setting for a given overlay */
+		virtual EVROverlayError SetOverlayFlag( VROverlayHandle_t ulOverlayHandle, VROverlayFlags eOverlayFlag, bool bEnabled ) = 0;
+
+		/** Sets flag setting for a given overlay */
+		virtual EVROverlayError GetOverlayFlag( VROverlayHandle_t ulOverlayHandle, VROverlayFlags eOverlayFlag, bool *pbEnabled ) = 0;
+
+		/** Sets the color tint of the overlay quad. Use 0.0 to 1.0 per channel. */
+		virtual EVROverlayError SetOverlayColor( VROverlayHandle_t ulOverlayHandle, float fRed, float fGreen, float fBlue ) = 0;
+
+		/** Gets the color tint of the overlay quad. */
+		virtual EVROverlayError GetOverlayColor( VROverlayHandle_t ulOverlayHandle, float *pfRed, float *pfGreen, float *pfBlue ) = 0;
+
+		/** Sets the alpha of the overlay quad. Use 1.0 for 100 percent opacity to 0.0 for 0 percent opacity. */
+		virtual EVROverlayError SetOverlayAlpha( VROverlayHandle_t ulOverlayHandle, float fAlpha ) = 0;
+
+		/** Gets the alpha of the overlay quad. By default overlays are rendering at 100 percent alpha (1.0). */
+		virtual EVROverlayError GetOverlayAlpha( VROverlayHandle_t ulOverlayHandle, float *pfAlpha ) = 0;
+
+		/** Sets the aspect ratio of the texels in the overlay. 1.0 means the texels are square. 2.0 means the texels
+		* are twice as wide as they are tall. Defaults to 1.0. */
+		virtual EVROverlayError SetOverlayTexelAspect( VROverlayHandle_t ulOverlayHandle, float fTexelAspect ) = 0;
+
+		/** Gets the aspect ratio of the texels in the overlay. Defaults to 1.0 */
+		virtual EVROverlayError GetOverlayTexelAspect( VROverlayHandle_t ulOverlayHandle, float *pfTexelAspect ) = 0;
+
+		/** Sets the rendering sort order for the overlay. Overlays are rendered this order:
+		*      Overlays owned by the scene application
+		*      Overlays owned by some other application
+		*
+		*	Within a category overlays are rendered lowest sort order to highest sort order. Overlays with the same 
+		*	sort order are rendered back to front base on distance from the HMD.
+		*
+		*	Sort order defaults to 0. */
+		virtual EVROverlayError SetOverlaySortOrder( VROverlayHandle_t ulOverlayHandle, uint32_t unSortOrder ) = 0;
+
+		/** Gets the sort order of the overlay. See SetOverlaySortOrder for how this works. */
+		virtual EVROverlayError GetOverlaySortOrder( VROverlayHandle_t ulOverlayHandle, uint32_t *punSortOrder ) = 0;
+
+		/** Sets the width of the overlay quad in meters. By default overlays are rendered on a quad that is 1 meter across */
+		virtual EVROverlayError SetOverlayWidthInMeters( VROverlayHandle_t ulOverlayHandle, float fWidthInMeters ) = 0;
+
+		/** Returns the width of the overlay quad in meters. By default overlays are rendered on a quad that is 1 meter across */
+		virtual EVROverlayError GetOverlayWidthInMeters( VROverlayHandle_t ulOverlayHandle, float *pfWidthInMeters ) = 0;
+
+		/** For high-quality curved overlays only, sets the distance range in meters from the overlay used to automatically curve
+		* the surface around the viewer.  Min is distance is when the surface will be most curved.  Max is when least curved. */
+		virtual EVROverlayError SetOverlayAutoCurveDistanceRangeInMeters( VROverlayHandle_t ulOverlayHandle, float fMinDistanceInMeters, float fMaxDistanceInMeters ) = 0;
+
+		/** For high-quality curved overlays only, gets the distance range in meters from the overlay used to automatically curve
+		* the surface around the viewer.  Min is distance is when the surface will be most curved.  Max is when least curved. */
+		virtual EVROverlayError GetOverlayAutoCurveDistanceRangeInMeters( VROverlayHandle_t ulOverlayHandle, float *pfMinDistanceInMeters, float *pfMaxDistanceInMeters ) = 0;
+
+		/** Sets the colorspace the overlay texture's data is in.  Defaults to 'auto'.
+		* If the texture needs to be resolved, you should call SetOverlayTexture with the appropriate colorspace instead. */
+		virtual EVROverlayError SetOverlayTextureColorSpace( VROverlayHandle_t ulOverlayHandle, EColorSpace eTextureColorSpace ) = 0;
+
+		/** Gets the overlay's current colorspace setting. */
+		virtual EVROverlayError GetOverlayTextureColorSpace( VROverlayHandle_t ulOverlayHandle, EColorSpace *peTextureColorSpace ) = 0;
+
+		/** Sets the part of the texture to use for the overlay. UV Min is the upper left corner and UV Max is the lower right corner. */
+		virtual EVROverlayError SetOverlayTextureBounds( VROverlayHandle_t ulOverlayHandle, const VRTextureBounds_t *pOverlayTextureBounds ) = 0;
+
+		/** Gets the part of the texture to use for the overlay. UV Min is the upper left corner and UV Max is the lower right corner. */
+		virtual EVROverlayError GetOverlayTextureBounds( VROverlayHandle_t ulOverlayHandle, VRTextureBounds_t *pOverlayTextureBounds ) = 0;
+
+		/** Returns the transform type of this overlay. */
+		virtual EVROverlayError GetOverlayTransformType( VROverlayHandle_t ulOverlayHandle, VROverlayTransformType *peTransformType ) = 0;
+
+		/** Sets the transform to absolute tracking origin. */
+		virtual EVROverlayError SetOverlayTransformAbsolute( VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin eTrackingOrigin, const HmdMatrix34_t *pmatTrackingOriginToOverlayTransform ) = 0;
+
+		/** Gets the transform if it is absolute. Returns an error if the transform is some other type. */
+		virtual EVROverlayError GetOverlayTransformAbsolute( VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin *peTrackingOrigin, HmdMatrix34_t *pmatTrackingOriginToOverlayTransform ) = 0;
+
+		/** Sets the transform to relative to the transform of the specified tracked device. */
+		virtual EVROverlayError SetOverlayTransformTrackedDeviceRelative( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t unTrackedDevice, const HmdMatrix34_t *pmatTrackedDeviceToOverlayTransform ) = 0;
+
+		/** Gets the transform if it is relative to a tracked device. Returns an error if the transform is some other type. */
+		virtual EVROverlayError GetOverlayTransformTrackedDeviceRelative( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t *punTrackedDevice, HmdMatrix34_t *pmatTrackedDeviceToOverlayTransform ) = 0;
+
+		/** Sets the transform to draw the overlay on a rendermodel component mesh instead of a quad. This will only draw when the system is
+		* drawing the device. Overlays with this transform type cannot receive mouse events. */
+		virtual EVROverlayError SetOverlayTransformTrackedDeviceComponent( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t unDeviceIndex, const char *pchComponentName ) = 0;
+
+		/** Gets the transform information when the overlay is rendering on a component. */
+		virtual EVROverlayError GetOverlayTransformTrackedDeviceComponent( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t *punDeviceIndex, char *pchComponentName, uint32_t unComponentNameSize ) = 0;
+
+		/** Shows the VR overlay.  For dashboard overlays, only the Dashboard Manager is allowed to call this. */
+		virtual EVROverlayError ShowOverlay( VROverlayHandle_t ulOverlayHandle ) = 0;
+
+		/** Hides the VR overlay.  For dashboard overlays, only the Dashboard Manager is allowed to call this. */
+		virtual EVROverlayError HideOverlay( VROverlayHandle_t ulOverlayHandle ) = 0;
+
+		/** Returns true if the overlay is visible. */
+		virtual bool IsOverlayVisible( VROverlayHandle_t ulOverlayHandle ) = 0;
+
+		/** Get the transform in 3d space associated with a specific 2d point in the overlay's coordinate space (where 0,0 is the lower left). -Z points out of the overlay */
+		virtual EVROverlayError GetTransformForOverlayCoordinates( VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin eTrackingOrigin, HmdVector2_t coordinatesInOverlay, HmdMatrix34_t *pmatTransform ) = 0;
+
+		// ---------------------------------------------
+		// Overlay input methods
+		// ---------------------------------------------
+
+		/** Returns true and fills the event with the next event on the overlay's event queue, if there is one. 
+		* If there are no events this method returns false. uncbVREvent should be the size in bytes of the VREvent_t struct */
+		virtual bool PollNextOverlayEvent( VROverlayHandle_t ulOverlayHandle, VREvent_t *pEvent, uint32_t uncbVREvent ) = 0;
+
+		/** Returns the current input settings for the specified overlay. */
+		virtual EVROverlayError GetOverlayInputMethod( VROverlayHandle_t ulOverlayHandle, VROverlayInputMethod *peInputMethod ) = 0;
+
+		/** Sets the input settings for the specified overlay. */
+		virtual EVROverlayError SetOverlayInputMethod( VROverlayHandle_t ulOverlayHandle, VROverlayInputMethod eInputMethod ) = 0;
+
+		/** Gets the mouse scaling factor that is used for mouse events. The actual texture may be a different size, but this is
+		* typically the size of the underlying UI in pixels. */
+		virtual EVROverlayError GetOverlayMouseScale( VROverlayHandle_t ulOverlayHandle, HmdVector2_t *pvecMouseScale ) = 0;
+
+		/** Sets the mouse scaling factor that is used for mouse events. The actual texture may be a different size, but this is
+		* typically the size of the underlying UI in pixels (not in world space). */
+		virtual EVROverlayError SetOverlayMouseScale( VROverlayHandle_t ulOverlayHandle, const HmdVector2_t *pvecMouseScale ) = 0;
+
+		/** Computes the overlay-space pixel coordinates of where the ray intersects the overlay with the
+		* specified settings. Returns false if there is no intersection. */
+		virtual bool ComputeOverlayIntersection( VROverlayHandle_t ulOverlayHandle, const VROverlayIntersectionParams_t *pParams, VROverlayIntersectionResults_t *pResults ) = 0;
+
+		/** Processes mouse input from the specified controller as though it were a mouse pointed at a compositor overlay with the
+		* specified settings. The controller is treated like a laser pointer on the -z axis. The point where the laser pointer would
+		* intersect with the overlay is the mouse position, the trigger is left mouse, and the track pad is right mouse. 
+		*
+		* Return true if the controller is pointed at the overlay and an event was generated. */
+		virtual bool HandleControllerOverlayInteractionAsMouse( VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t unControllerDeviceIndex ) = 0;
+
+		/** Returns true if the specified overlay is the hover target. An overlay is the hover target when it is the last overlay "moused over" 
+		* by the virtual mouse pointer */
+		virtual bool IsHoverTargetOverlay( VROverlayHandle_t ulOverlayHandle ) = 0;
+
+		/** Returns the current Gamepad focus overlay */
+		virtual vr::VROverlayHandle_t GetGamepadFocusOverlay() = 0;
+
+		/** Sets the current Gamepad focus overlay */
+		virtual EVROverlayError SetGamepadFocusOverlay( VROverlayHandle_t ulNewFocusOverlay ) = 0;
+
+		/** Sets an overlay's neighbor. This will also set the neighbor of the "to" overlay
+		* to point back to the "from" overlay. If an overlay's neighbor is set to invalid both
+		* ends will be cleared */
+		virtual EVROverlayError SetOverlayNeighbor( EOverlayDirection eDirection, VROverlayHandle_t ulFrom, VROverlayHandle_t ulTo ) = 0;
+
+		/** Changes the Gamepad focus from one overlay to one of its neighbors. Returns VROverlayError_NoNeighbor if there is no
+		* neighbor in that direction */
+		virtual EVROverlayError MoveGamepadFocusToNeighbor( EOverlayDirection eDirection, VROverlayHandle_t ulFrom ) = 0;
+
+		// ---------------------------------------------
+		// Overlay texture methods
+		// ---------------------------------------------
+
+		/** Texture to draw for the overlay. This function can only be called by the overlay's creator or renderer process (see SetOverlayRenderingPid) .
+		*
+		* OpenGL dirty state:
+		*	glBindTexture
+		*/
+		virtual EVROverlayError SetOverlayTexture( VROverlayHandle_t ulOverlayHandle, const Texture_t *pTexture ) = 0;
+
+		/** Use this to tell the overlay system to release the texture set for this overlay. */
+		virtual EVROverlayError ClearOverlayTexture( VROverlayHandle_t ulOverlayHandle ) = 0;
+
+		/** Separate interface for providing the data as a stream of bytes, but there is an upper bound on data 
+		* that can be sent. This function can only be called by the overlay's renderer process. */
+		virtual EVROverlayError SetOverlayRaw( VROverlayHandle_t ulOverlayHandle, void *pvBuffer, uint32_t unWidth, uint32_t unHeight, uint32_t unDepth ) = 0;
+
+		/** Separate interface for providing the image through a filename: can be png or jpg, and should not be bigger than 1920x1080.
+		* This function can only be called by the overlay's renderer process */
+		virtual EVROverlayError SetOverlayFromFile( VROverlayHandle_t ulOverlayHandle, const char *pchFilePath ) = 0;
+
+		/** Get the native texture handle/device for an overlay you have created.
+		* On windows this handle will be a ID3D11ShaderResourceView with a ID3D11Texture2D bound.
+		*
+		* The texture will always be sized to match the backing texture you supplied in SetOverlayTexture above.
+		*
+		* You MUST call ReleaseNativeOverlayHandle() with pNativeTextureHandle once you are done with this texture.
+		*
+		* pNativeTextureHandle is an OUTPUT, it will be a pointer to a ID3D11ShaderResourceView *.
+		* pNativeTextureRef is an INPUT and should be a ID3D11Resource *. The device used by pNativeTextureRef will be used to bind pNativeTextureHandle.
+		*/
+		virtual EVROverlayError GetOverlayTexture( VROverlayHandle_t ulOverlayHandle, void **pNativeTextureHandle, void *pNativeTextureRef, uint32_t *pWidth, uint32_t *pHeight, uint32_t *pNativeFormat, ETextureType *pAPIType, EColorSpace *pColorSpace, VRTextureBounds_t *pTextureBounds ) = 0;
+
+		/** Release the pNativeTextureHandle provided from the GetOverlayTexture call, this allows the system to free the underlying GPU resources for this object,
+		* so only do it once you stop rendering this texture.
+		*/
+		virtual EVROverlayError ReleaseNativeOverlayHandle( VROverlayHandle_t ulOverlayHandle, void *pNativeTextureHandle ) = 0;
+
+		/** Get the size of the overlay texture */
+		virtual EVROverlayError GetOverlayTextureSize( VROverlayHandle_t ulOverlayHandle, uint32_t *pWidth, uint32_t *pHeight ) = 0;
+
+		// ----------------------------------------------
+		// Dashboard Overlay Methods
+		// ----------------------------------------------
+
+		/** Creates a dashboard overlay and returns its handle */
+		virtual EVROverlayError CreateDashboardOverlay( const char *pchOverlayKey, const char *pchOverlayFriendlyName, VROverlayHandle_t * pMainHandle, VROverlayHandle_t *pThumbnailHandle ) = 0;
+
+		/** Returns true if the dashboard is visible */
+		virtual bool IsDashboardVisible() = 0;
+
+		/** returns true if the dashboard is visible and the specified overlay is the active system Overlay */
+		virtual bool IsActiveDashboardOverlay( VROverlayHandle_t ulOverlayHandle ) = 0;
+
+		/** Sets the dashboard overlay to only appear when the specified process ID has scene focus */
+		virtual EVROverlayError SetDashboardOverlaySceneProcess( VROverlayHandle_t ulOverlayHandle, uint32_t unProcessId ) = 0;
+
+		/** Gets the process ID that this dashboard overlay requires to have scene focus */
+		virtual EVROverlayError GetDashboardOverlaySceneProcess( VROverlayHandle_t ulOverlayHandle, uint32_t *punProcessId ) = 0;
+
+		/** Shows the dashboard. */
+		virtual void ShowDashboard( const char *pchOverlayToShow ) = 0;
+
+		/** Returns the tracked device that has the laser pointer in the dashboard */
+		virtual vr::TrackedDeviceIndex_t GetPrimaryDashboardDevice() = 0;
+
+		// ---------------------------------------------
+		// Keyboard methods
+		// ---------------------------------------------
+		
+		/** Show the virtual keyboard to accept input **/
+		virtual EVROverlayError ShowKeyboard( EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, const char *pchDescription, uint32_t unCharMax, const char *pchExistingText, bool bUseMinimalMode, uint64_t uUserValue ) = 0;
+
+		virtual EVROverlayError ShowKeyboardForOverlay( VROverlayHandle_t ulOverlayHandle, EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, const char *pchDescription, uint32_t unCharMax, const char *pchExistingText, bool bUseMinimalMode, uint64_t uUserValue ) = 0;
+
+		/** Get the text that was entered into the text input **/
+		virtual uint32_t GetKeyboardText( VR_OUT_STRING() char *pchText, uint32_t cchText ) = 0;
+
+		/** Hide the virtual keyboard **/
+		virtual void HideKeyboard() = 0;
+
+		/** Set the position of the keyboard in world space **/
+		virtual void SetKeyboardTransformAbsolute( ETrackingUniverseOrigin eTrackingOrigin, const HmdMatrix34_t *pmatTrackingOriginToKeyboardTransform ) = 0;
+
+		/** Set the position of the keyboard in overlay space by telling it to avoid a rectangle in the overlay. Rectangle coords have (0,0) in the bottom left **/
+		virtual void SetKeyboardPositionForOverlay( VROverlayHandle_t ulOverlayHandle, HmdRect2_t avoidRect ) = 0;
+
+		// ---------------------------------------------
+		// Overlay input methods
+		// ---------------------------------------------
+
+		/** Sets a list of primitives to be used for controller ray intersection
+		* typically the size of the underlying UI in pixels (not in world space). */
+		virtual EVROverlayError SetOverlayIntersectionMask( VROverlayHandle_t ulOverlayHandle, VROverlayIntersectionMaskPrimitive_t *pMaskPrimitives, uint32_t unNumMaskPrimitives, uint32_t unPrimitiveSize = sizeof( VROverlayIntersectionMaskPrimitive_t ) ) = 0;
+
+		virtual EVROverlayError GetOverlayFlags( VROverlayHandle_t ulOverlayHandle, uint32_t *pFlags ) = 0;
+
+		// ---------------------------------------------
+		// Message box methods
+		// ---------------------------------------------
+
+		/** Show the message overlay. This will block and return you a result. **/
+		virtual VRMessageOverlayResponse ShowMessageOverlay( const char* pchText, const char* pchCaption, const char* pchButton0Text, const char* pchButton1Text = nullptr, const char* pchButton2Text = nullptr, const char* pchButton3Text = nullptr ) = 0;
+	};
+
+	static const char * const IVROverlay_Version = "IVROverlay_014";
+
+} // namespace vr
+
+// ivrrendermodels.h
+namespace vr
+{
+
+static const char * const k_pch_Controller_Component_GDC2015 = "gdc2015";   // Canonical coordinate system of the gdc 2015 wired controller, provided for backwards compatibility
+static const char * const k_pch_Controller_Component_Base = "base";         // For controllers with an unambiguous 'base'.
+static const char * const k_pch_Controller_Component_Tip = "tip";           // For controllers with an unambiguous 'tip' (used for 'laser-pointing')
+static const char * const k_pch_Controller_Component_HandGrip = "handgrip"; // Neutral, ambidextrous hand-pose when holding controller. On plane between neutrally posed index finger and thumb
+static const char * const k_pch_Controller_Component_Status = "status";		// 1:1 aspect ratio status area, with canonical [0,1] uv mapping
+
+#if defined(__linux__) || defined(__APPLE__) 
+// The 32-bit version of gcc has the alignment requirement for uint64 and double set to
+// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned.
+// The 64-bit version of gcc has the alignment requirement for these types set to
+// 8 meaning that unless we use #pragma pack(4) our structures will get bigger.
+// The 64-bit structure packing has to match the 32-bit structure packing for each platform.
+#pragma pack( push, 4 )
+#else
+#pragma pack( push, 8 )
+#endif
+
+/** Errors that can occur with the VR compositor */
+enum EVRRenderModelError
+{
+	VRRenderModelError_None = 0,
+	VRRenderModelError_Loading = 100,
+	VRRenderModelError_NotSupported = 200,
+	VRRenderModelError_InvalidArg = 300,
+	VRRenderModelError_InvalidModel = 301,
+	VRRenderModelError_NoShapes = 302,
+	VRRenderModelError_MultipleShapes = 303,
+	VRRenderModelError_TooManyVertices = 304,
+	VRRenderModelError_MultipleTextures = 305,
+	VRRenderModelError_BufferTooSmall = 306,
+	VRRenderModelError_NotEnoughNormals = 307,
+	VRRenderModelError_NotEnoughTexCoords = 308,
+
+	VRRenderModelError_InvalidTexture = 400,
+};
+
+typedef uint32_t VRComponentProperties;
+
+enum EVRComponentProperty
+{
+	VRComponentProperty_IsStatic = (1 << 0),
+	VRComponentProperty_IsVisible = (1 << 1),
+	VRComponentProperty_IsTouched = (1 << 2),
+	VRComponentProperty_IsPressed = (1 << 3),
+	VRComponentProperty_IsScrolled = (1 << 4),
+};
+
+/** Describes state information about a render-model component, including transforms and other dynamic properties */
+struct RenderModel_ComponentState_t
+{
+	HmdMatrix34_t mTrackingToComponentRenderModel;  // Transform required when drawing the component render model
+	HmdMatrix34_t mTrackingToComponentLocal;        // Transform available for attaching to a local component coordinate system (-Z out from surface )
+	VRComponentProperties uProperties;
+};
+
+/** A single vertex in a render model */
+struct RenderModel_Vertex_t
+{
+	HmdVector3_t vPosition;		// position in meters in device space
+	HmdVector3_t vNormal;
+	float rfTextureCoord[2];
+};
+
+/** A texture map for use on a render model */
+struct RenderModel_TextureMap_t
+{
+	uint16_t unWidth, unHeight; // width and height of the texture map in pixels
+	const uint8_t *rubTextureMapData;	// Map texture data. All textures are RGBA with 8 bits per channel per pixel. Data size is width * height * 4ub
+};
+
+/**  Session unique texture identifier. Rendermodels which share the same texture will have the same id.
+IDs <0 denote the texture is not present */
+
+typedef int32_t TextureID_t;
+
+const TextureID_t INVALID_TEXTURE_ID = -1;
+
+struct RenderModel_t
+{
+	const RenderModel_Vertex_t *rVertexData;	// Vertex data for the mesh
+	uint32_t unVertexCount;						// Number of vertices in the vertex data
+	const uint16_t *rIndexData;					// Indices into the vertex data for each triangle
+	uint32_t unTriangleCount;					// Number of triangles in the mesh. Index count is 3 * TriangleCount
+	TextureID_t diffuseTextureId;				// Session unique texture identifier. Rendermodels which share the same texture will have the same id. <0 == texture not present
+};
+
+struct RenderModel_ControllerMode_State_t
+{
+	bool bScrollWheelVisible; // is this controller currently set to be in a scroll wheel mode
+};
+
+#pragma pack( pop )
+
+class IVRRenderModels
+{
+public:
+
+	/** Loads and returns a render model for use in the application. pchRenderModelName should be a render model name
+	* from the Prop_RenderModelName_String property or an absolute path name to a render model on disk. 
+	*
+	* The resulting render model is valid until VR_Shutdown() is called or until FreeRenderModel() is called. When the 
+	* application is finished with the render model it should call FreeRenderModel() to free the memory associated
+	* with the model.
+	*
+	* The method returns VRRenderModelError_Loading while the render model is still being loaded.
+	* The method returns VRRenderModelError_None once loaded successfully, otherwise will return an error. */
+	virtual EVRRenderModelError LoadRenderModel_Async( const char *pchRenderModelName, RenderModel_t **ppRenderModel ) = 0;
+
+	/** Frees a previously returned render model
+	*   It is safe to call this on a null ptr. */
+	virtual void FreeRenderModel( RenderModel_t *pRenderModel ) = 0;
+
+	/** Loads and returns a texture for use in the application. */
+	virtual EVRRenderModelError LoadTexture_Async( TextureID_t textureId, RenderModel_TextureMap_t **ppTexture ) = 0;
+
+	/** Frees a previously returned texture
+	*   It is safe to call this on a null ptr. */
+	virtual void FreeTexture( RenderModel_TextureMap_t *pTexture ) = 0;
+
+	/** Creates a D3D11 texture and loads data into it. */
+	virtual EVRRenderModelError LoadTextureD3D11_Async( TextureID_t textureId, void *pD3D11Device, void **ppD3D11Texture2D ) = 0;
+
+	/** Helper function to copy the bits into an existing texture. */
+	virtual EVRRenderModelError LoadIntoTextureD3D11_Async( TextureID_t textureId, void *pDstTexture ) = 0;
+
+	/** Use this to free textures created with LoadTextureD3D11_Async instead of calling Release on them. */
+	virtual void FreeTextureD3D11( void *pD3D11Texture2D ) = 0;
+
+	/** Use this to get the names of available render models.  Index does not correlate to a tracked device index, but
+	* is only used for iterating over all available render models.  If the index is out of range, this function will return 0.
+	* Otherwise, it will return the size of the buffer required for the name. */
+	virtual uint32_t GetRenderModelName( uint32_t unRenderModelIndex, VR_OUT_STRING() char *pchRenderModelName, uint32_t unRenderModelNameLen ) = 0;
+
+	/** Returns the number of available render models. */
+	virtual uint32_t GetRenderModelCount() = 0;
+
+
+	/** Returns the number of components of the specified render model.
+	*  Components are useful when client application wish to draw, label, or otherwise interact with components of tracked objects.
+	*  Examples controller components:
+	*   renderable things such as triggers, buttons
+	*   non-renderable things which include coordinate systems such as 'tip', 'base', a neutral controller agnostic hand-pose
+	*   If all controller components are enumerated and rendered, it will be equivalent to drawing the traditional render model
+	*   Returns 0 if components not supported, >0 otherwise */
+	virtual uint32_t GetComponentCount( const char *pchRenderModelName ) = 0;
+
+	/** Use this to get the names of available components.  Index does not correlate to a tracked device index, but
+	* is only used for iterating over all available components.  If the index is out of range, this function will return 0.
+	* Otherwise, it will return the size of the buffer required for the name. */
+	virtual uint32_t GetComponentName( const char *pchRenderModelName, uint32_t unComponentIndex, VR_OUT_STRING( ) char *pchComponentName, uint32_t unComponentNameLen ) = 0;
+
+	/** Get the button mask for all buttons associated with this component
+	*   If no buttons (or axes) are associated with this component, return 0
+	*   Note: multiple components may be associated with the same button. Ex: two grip buttons on a single controller.
+	*   Note: A single component may be associated with multiple buttons. Ex: A trackpad which also provides "D-pad" functionality */
+	virtual uint64_t GetComponentButtonMask( const char *pchRenderModelName, const char *pchComponentName ) = 0;
+
+	/** Use this to get the render model name for the specified rendermode/component combination, to be passed to LoadRenderModel.
+	* If the component name is out of range, this function will return 0.
+	* Otherwise, it will return the size of the buffer required for the name. */
+	virtual uint32_t GetComponentRenderModelName( const char *pchRenderModelName, const char *pchComponentName, VR_OUT_STRING( ) char *pchComponentRenderModelName, uint32_t unComponentRenderModelNameLen ) = 0;
+
+	/** Use this to query information about the component, as a function of the controller state.
+	*
+	* For dynamic controller components (ex: trigger) values will reflect component motions
+	* For static components this will return a consistent value independent of the VRControllerState_t
+	*
+	* If the pchRenderModelName or pchComponentName is invalid, this will return false (and transforms will be set to identity).
+	* Otherwise, return true
+	* Note: For dynamic objects, visibility may be dynamic. (I.e., true/false will be returned based on controller state and controller mode state ) */
+	virtual bool GetComponentState( const char *pchRenderModelName, const char *pchComponentName, const vr::VRControllerState_t *pControllerState, const RenderModel_ControllerMode_State_t *pState, RenderModel_ComponentState_t *pComponentState ) = 0;
+
+	/** Returns true if the render model has a component with the specified name */
+	virtual bool RenderModelHasComponent( const char *pchRenderModelName, const char *pchComponentName ) = 0;
+
+	/** Returns the URL of the thumbnail image for this rendermodel */
+	virtual uint32_t GetRenderModelThumbnailURL( const char *pchRenderModelName, VR_OUT_STRING() char *pchThumbnailURL, uint32_t unThumbnailURLLen, vr::EVRRenderModelError *peError ) = 0;
+
+	/** Provides a render model path that will load the unskinned model if the model name provided has been replace by the user. If the model
+	* hasn't been replaced the path value will still be a valid path to load the model. Pass this to LoadRenderModel_Async, etc. to load the
+	* model. */
+	virtual uint32_t GetRenderModelOriginalPath( const char *pchRenderModelName, VR_OUT_STRING() char *pchOriginalPath, uint32_t unOriginalPathLen, vr::EVRRenderModelError *peError ) = 0;
+
+	/** Returns a string for a render model error */
+	virtual const char *GetRenderModelErrorNameFromEnum( vr::EVRRenderModelError error ) = 0;
+};
+
+static const char * const IVRRenderModels_Version = "IVRRenderModels_005";
+
+}
+
+
+// ivrextendeddisplay.h
+namespace vr
+{
+
+	/** NOTE: Use of this interface is not recommended in production applications. It will not work for displays which use
+	* direct-to-display mode. Creating our own window is also incompatible with the VR compositor and is not available when the compositor is running. */
+	class IVRExtendedDisplay
+	{
+	public:
+
+		/** Size and position that the window needs to be on the VR display. */
+		virtual void GetWindowBounds( int32_t *pnX, int32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0;
+
+		/** Gets the viewport in the frame buffer to draw the output of the distortion into */
+		virtual void GetEyeOutputViewport( EVREye eEye, uint32_t *pnX, uint32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0;
+
+		/** [D3D10/11 Only]
+		* Returns the adapter index and output index that the user should pass into EnumAdapters and EnumOutputs
+		* to create the device and swap chain in DX10 and DX11. If an error occurs both indices will be set to -1.
+		*/
+		virtual void GetDXGIOutputInfo( int32_t *pnAdapterIndex, int32_t *pnAdapterOutputIndex ) = 0;
+
+	};
+
+	static const char * const IVRExtendedDisplay_Version = "IVRExtendedDisplay_001";
+
+}
+
+
+// ivrtrackedcamera.h
+namespace vr
+{
+
+class IVRTrackedCamera
+{
+public:
+	/** Returns a string for an error */
+	virtual const char *GetCameraErrorNameFromEnum( vr::EVRTrackedCameraError eCameraError ) = 0;
+
+	/** For convenience, same as tracked property request Prop_HasCamera_Bool */
+	virtual vr::EVRTrackedCameraError HasCamera( vr::TrackedDeviceIndex_t nDeviceIndex, bool *pHasCamera ) = 0;
+
+	/** Gets size of the image frame. */
+	virtual vr::EVRTrackedCameraError GetCameraFrameSize( vr::TrackedDeviceIndex_t nDeviceIndex, vr::EVRTrackedCameraFrameType eFrameType, uint32_t *pnWidth, uint32_t *pnHeight, uint32_t *pnFrameBufferSize ) = 0;
+
+	virtual vr::EVRTrackedCameraError GetCameraIntrinsics( vr::TrackedDeviceIndex_t nDeviceIndex, vr::EVRTrackedCameraFrameType eFrameType, vr::HmdVector2_t *pFocalLength, vr::HmdVector2_t *pCenter ) = 0;
+
+	virtual vr::EVRTrackedCameraError GetCameraProjection( vr::TrackedDeviceIndex_t nDeviceIndex, vr::EVRTrackedCameraFrameType eFrameType, float flZNear, float flZFar, vr::HmdMatrix44_t *pProjection ) = 0;
+
+	/** Acquiring streaming service permits video streaming for the caller. Releasing hints the system that video services do not need to be maintained for this client.
+	* If the camera has not already been activated, a one time spin up may incur some auto exposure as well as initial streaming frame delays.
+	* The camera should be considered a global resource accessible for shared consumption but not exclusive to any caller.
+	* The camera may go inactive due to lack of active consumers or headset idleness. */
+	virtual vr::EVRTrackedCameraError AcquireVideoStreamingService( vr::TrackedDeviceIndex_t nDeviceIndex, vr::TrackedCameraHandle_t *pHandle ) = 0;
+	virtual vr::EVRTrackedCameraError ReleaseVideoStreamingService( vr::TrackedCameraHandle_t hTrackedCamera ) = 0;
+
+	/** Copies the image frame into a caller's provided buffer. The image data is currently provided as RGBA data, 4 bytes per pixel.
+	* A caller can provide null for the framebuffer or frameheader if not desired. Requesting the frame header first, followed by the frame buffer allows
+	* the caller to determine if the frame as advanced per the frame header sequence. 
+	* If there is no frame available yet, due to initial camera spinup or re-activation, the error will be VRTrackedCameraError_NoFrameAvailable.
+	* Ideally a caller should be polling at ~16ms intervals */
+	virtual vr::EVRTrackedCameraError GetVideoStreamFrameBuffer( vr::TrackedCameraHandle_t hTrackedCamera, vr::EVRTrackedCameraFrameType eFrameType, void *pFrameBuffer, uint32_t nFrameBufferSize, vr::CameraVideoStreamFrameHeader_t *pFrameHeader, uint32_t nFrameHeaderSize ) = 0;
+
+	/** Gets size of the image frame. */
+	virtual vr::EVRTrackedCameraError GetVideoStreamTextureSize( vr::TrackedDeviceIndex_t nDeviceIndex, vr::EVRTrackedCameraFrameType eFrameType, vr::VRTextureBounds_t *pTextureBounds, uint32_t *pnWidth, uint32_t *pnHeight ) = 0; 
+
+	/** Access a shared D3D11 texture for the specified tracked camera stream.
+	* The camera frame type VRTrackedCameraFrameType_Undistorted is not supported directly as a shared texture. It is an interior subregion of the shared texture VRTrackedCameraFrameType_MaximumUndistorted.
+	* Instead, use GetVideoStreamTextureSize() with VRTrackedCameraFrameType_Undistorted to determine the proper interior subregion bounds along with GetVideoStreamTextureD3D11() with
+	* VRTrackedCameraFrameType_MaximumUndistorted to provide the texture. The VRTrackedCameraFrameType_MaximumUndistorted will yield an image where the invalid regions are decoded
+	* by the alpha channel having a zero component. The valid regions all have a non-zero alpha component. The subregion as described by VRTrackedCameraFrameType_Undistorted 
+	* guarantees a rectangle where all pixels are valid. */
+	virtual vr::EVRTrackedCameraError GetVideoStreamTextureD3D11( vr::TrackedCameraHandle_t hTrackedCamera, vr::EVRTrackedCameraFrameType eFrameType, void *pD3D11DeviceOrResource, void **ppD3D11ShaderResourceView, vr::CameraVideoStreamFrameHeader_t *pFrameHeader, uint32_t nFrameHeaderSize ) = 0;
+
+	/** Access a shared GL texture for the specified tracked camera stream */
+	virtual vr::EVRTrackedCameraError GetVideoStreamTextureGL( vr::TrackedCameraHandle_t hTrackedCamera, vr::EVRTrackedCameraFrameType eFrameType, vr::glUInt_t *pglTextureId, vr::CameraVideoStreamFrameHeader_t *pFrameHeader, uint32_t nFrameHeaderSize ) = 0;
+	virtual vr::EVRTrackedCameraError ReleaseVideoStreamTextureGL( vr::TrackedCameraHandle_t hTrackedCamera, vr::glUInt_t glTextureId ) = 0;
+};
+
+static const char * const IVRTrackedCamera_Version = "IVRTrackedCamera_003";
+
+} // namespace vr
+
+
+// ivrscreenshots.h
+namespace vr
+{
+
+/** Errors that can occur with the VR compositor */
+enum EVRScreenshotError
+{
+	VRScreenshotError_None							= 0,
+	VRScreenshotError_RequestFailed					= 1,
+	VRScreenshotError_IncompatibleVersion			= 100,
+	VRScreenshotError_NotFound						= 101,
+	VRScreenshotError_BufferTooSmall				= 102,
+	VRScreenshotError_ScreenshotAlreadyInProgress	= 108,
+};
+
+/** Allows the application to generate screenshots */
+class IVRScreenshots
+{
+public:
+	/** Request a screenshot of the requested type.
+	 *  A request of the VRScreenshotType_Stereo type will always
+	 *  work. Other types will depend on the underlying application
+	 *  support.
+	 *  The first file name is for the preview image and should be a
+	 *  regular screenshot (ideally from the left eye). The second
+	 *  is the VR screenshot in the correct format. They should be
+	 *  in the same aspect ratio.  Formats per type:
+	 *  VRScreenshotType_Mono: the VR filename is ignored (can be
+	 *  nullptr), this is a normal flat single shot.
+	 *  VRScreenshotType_Stereo:  The VR image should be a
+	 *  side-by-side with the left eye image on the left.
+	 *  VRScreenshotType_Cubemap: The VR image should be six square
+	 *  images composited horizontally.
+	 *  VRScreenshotType_StereoPanorama: above/below with left eye
+	 *  panorama being the above image.  Image is typically square
+	 *  with the panorama being 2x horizontal.
+	 *  
+	 *  Note that the VR dashboard will call this function when
+	 *  the user presses the screenshot binding (currently System
+	 *  Button + Trigger).  If Steam is running, the destination
+	 *  file names will be in %TEMP% and will be copied into
+	 *  Steam's screenshot library for the running application
+	 *  once SubmitScreenshot() is called.
+	 *  If Steam is not running, the paths will be in the user's
+	 *  documents folder under Documents\SteamVR\Screenshots.
+	 *  Other VR applications can call this to initate a
+	 *  screenshot outside of user control.
+	 *  The destination file names do not need an extension,
+	 *  will be replaced with the correct one for the format
+	 *  which is currently .png. */
+	virtual vr::EVRScreenshotError RequestScreenshot( vr::ScreenshotHandle_t *pOutScreenshotHandle, vr::EVRScreenshotType type, const char *pchPreviewFilename, const char *pchVRFilename ) = 0;
+
+	/** Called by the running VR application to indicate that it
+	 *  wishes to be in charge of screenshots.  If the
+	 *  application does not call this, the Compositor will only
+	 *  support VRScreenshotType_Stereo screenshots that will be
+	 *  captured without notification to the running app.
+	 *  Once hooked your application will receive a
+	 *  VREvent_RequestScreenshot event when the user presses the
+	 *  buttons to take a screenshot. */
+	virtual vr::EVRScreenshotError HookScreenshot( VR_ARRAY_COUNT( numTypes ) const vr::EVRScreenshotType *pSupportedTypes, int numTypes ) = 0;
+
+	/** When your application receives a
+	 *  VREvent_RequestScreenshot event, call these functions to get
+	 *  the details of the screenshot request. */
+	virtual vr::EVRScreenshotType GetScreenshotPropertyType( vr::ScreenshotHandle_t screenshotHandle, vr::EVRScreenshotError *pError ) = 0;
+
+	/** Get the filename for the preview or vr image (see
+	 *  vr::EScreenshotPropertyFilenames).  The return value is
+	 *  the size of the string.   */
+ 	virtual uint32_t GetScreenshotPropertyFilename( vr::ScreenshotHandle_t screenshotHandle, vr::EVRScreenshotPropertyFilenames filenameType, VR_OUT_STRING() char *pchFilename, uint32_t cchFilename, vr::EVRScreenshotError *pError ) = 0;
+
+	/** Call this if the application is taking the screen shot
+	 *  will take more than a few ms processing. This will result
+	 *  in an overlay being presented that shows a completion
+	 *  bar. */
+	virtual vr::EVRScreenshotError UpdateScreenshotProgress( vr::ScreenshotHandle_t screenshotHandle, float flProgress ) = 0;
+
+	/** Tells the compositor to take an internal screenshot of
+	 *  type VRScreenshotType_Stereo. It will take the current
+	 *  submitted scene textures of the running application and
+	 *  write them into the preview image and a side-by-side file
+	 *  for the VR image.
+	 *  This is similiar to request screenshot, but doesn't ever
+	 *  talk to the application, just takes the shot and submits. */
+	virtual vr::EVRScreenshotError TakeStereoScreenshot( vr::ScreenshotHandle_t *pOutScreenshotHandle, const char *pchPreviewFilename, const char *pchVRFilename ) = 0;
+
+	/** Submit the completed screenshot.  If Steam is running
+	 *  this will call into the Steam client and upload the
+	 *  screenshot to the screenshots section of the library for
+	 *  the running application.  If Steam is not running, this
+	 *  function will display a notification to the user that the
+	 *  screenshot was taken. The paths should be full paths with
+	 *  extensions.
+	 *  File paths should be absolute including
+	 *  exntensions.
+	 *  screenshotHandle can be k_unScreenshotHandleInvalid if this
+	 *  was a new shot taking by the app to be saved and not
+	 *  initiated by a user (achievement earned or something) */
+	virtual vr::EVRScreenshotError SubmitScreenshot( vr::ScreenshotHandle_t screenshotHandle, vr::EVRScreenshotType type, const char *pchSourcePreviewFilename, const char *pchSourceVRFilename ) = 0;
+};
+
+static const char * const IVRScreenshots_Version = "IVRScreenshots_001";
+
+} // namespace vr
+
+
+
+// ivrresources.h
+namespace vr
+{
+
+class IVRResources
+{
+public:
+
+	// ------------------------------------
+	// Shared Resource Methods
+	// ------------------------------------
+
+	/** Loads the specified resource into the provided buffer if large enough.
+	* Returns the size in bytes of the buffer required to hold the specified resource. */
+	virtual uint32_t LoadSharedResource( const char *pchResourceName, char *pchBuffer, uint32_t unBufferLen ) = 0;
+
+	/** Provides the full path to the specified resource. Resource names can include named directories for
+	* drivers and other things, and this resolves all of those and returns the actual physical path. 
+	* pchResourceTypeDirectory is the subdirectory of resources to look in. */
+	virtual uint32_t GetResourceFullPath( const char *pchResourceName, const char *pchResourceTypeDirectory, char *pchPathBuffer, uint32_t unBufferLen ) = 0;
+};
+
+static const char * const IVRResources_Version = "IVRResources_001";
+
+
+}// End
+
+#endif // _OPENVR_API
+
+
+namespace vr
+{
+	/** Finds the active installation of the VR API and initializes it. The provided path must be absolute
+	* or relative to the current working directory. These are the local install versions of the equivalent
+	* functions in steamvr.h and will work without a local Steam install.
+	*
+	* This path is to the "root" of the VR API install. That's the directory with
+	* the "drivers" directory and a platform (i.e. "win32") directory in it, not the directory with the DLL itself.
+	*/
+	inline IVRSystem *VR_Init( EVRInitError *peError, EVRApplicationType eApplicationType );
+
+	/** unloads vrclient.dll. Any interface pointers from the interface are
+	* invalid after this point */
+	inline void VR_Shutdown();
+
+	/** Returns true if there is an HMD attached. This check is as lightweight as possible and
+	* can be called outside of VR_Init/VR_Shutdown. It should be used when an application wants
+	* to know if initializing VR is a possibility but isn't ready to take that step yet.
+	*/
+	VR_INTERFACE bool VR_CALLTYPE VR_IsHmdPresent();
+
+	/** Returns true if the OpenVR runtime is installed. */
+	VR_INTERFACE bool VR_CALLTYPE VR_IsRuntimeInstalled();
+
+	/** Returns where the OpenVR runtime is installed. */
+	VR_INTERFACE const char *VR_CALLTYPE VR_RuntimePath();
+
+	/** Returns the name of the enum value for an EVRInitError. This function may be called outside of VR_Init()/VR_Shutdown(). */
+	VR_INTERFACE const char *VR_CALLTYPE VR_GetVRInitErrorAsSymbol( EVRInitError error );
+
+	/** Returns an english string for an EVRInitError. Applications should call VR_GetVRInitErrorAsSymbol instead and
+	* use that as a key to look up their own localized error message. This function may be called outside of VR_Init()/VR_Shutdown(). */
+	VR_INTERFACE const char *VR_CALLTYPE VR_GetVRInitErrorAsEnglishDescription( EVRInitError error );
+
+	/** Returns the interface of the specified version. This method must be called after VR_Init. The
+	* pointer returned is valid until VR_Shutdown is called.
+	*/
+	VR_INTERFACE void *VR_CALLTYPE VR_GetGenericInterface( const char *pchInterfaceVersion, EVRInitError *peError );
+
+	/** Returns whether the interface of the specified version exists.
+	*/
+	VR_INTERFACE bool VR_CALLTYPE VR_IsInterfaceVersionValid( const char *pchInterfaceVersion );
+
+	/** Returns a token that represents whether the VR interface handles need to be reloaded */
+	VR_INTERFACE uint32_t VR_CALLTYPE VR_GetInitToken();
+
+	// These typedefs allow old enum names from SDK 0.9.11 to be used in applications.
+	// They will go away in the future.
+	typedef EVRInitError HmdError;
+	typedef EVREye Hmd_Eye;
+	typedef EColorSpace ColorSpace;
+	typedef ETrackingResult HmdTrackingResult;
+	typedef ETrackedDeviceClass TrackedDeviceClass;
+	typedef ETrackingUniverseOrigin TrackingUniverseOrigin;
+	typedef ETrackedDeviceProperty TrackedDeviceProperty;
+	typedef ETrackedPropertyError TrackedPropertyError;
+	typedef EVRSubmitFlags VRSubmitFlags_t;
+	typedef EVRState VRState_t;
+	typedef ECollisionBoundsStyle CollisionBoundsStyle_t;
+	typedef EVROverlayError VROverlayError;
+	typedef EVRFirmwareError VRFirmwareError;
+	typedef EVRCompositorError VRCompositorError;
+	typedef EVRScreenshotError VRScreenshotsError;
+
+	inline uint32_t &VRToken()
+	{
+		static uint32_t token;
+		return token;
+	}
+
+	class COpenVRContext
+	{
+	public:
+		COpenVRContext() { Clear(); }
+		void Clear();
+
+		inline void CheckClear()
+		{
+			if ( VRToken() != VR_GetInitToken() )
+			{
+				Clear();
+				VRToken() = VR_GetInitToken();
+			}
+		}
+
+		IVRSystem *VRSystem()
+		{
+			CheckClear();
+			if ( m_pVRSystem == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRSystem = ( IVRSystem * )VR_GetGenericInterface( IVRSystem_Version, &eError );
+			}
+			return m_pVRSystem;
+		}
+		IVRChaperone *VRChaperone()
+		{
+			CheckClear();
+			if ( m_pVRChaperone == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRChaperone = ( IVRChaperone * )VR_GetGenericInterface( IVRChaperone_Version, &eError );
+			}
+			return m_pVRChaperone;
+		}
+
+		IVRChaperoneSetup *VRChaperoneSetup()
+		{
+			CheckClear();
+			if ( m_pVRChaperoneSetup == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRChaperoneSetup = ( IVRChaperoneSetup * )VR_GetGenericInterface( IVRChaperoneSetup_Version, &eError );
+			}
+			return m_pVRChaperoneSetup;
+		}
+
+		IVRCompositor *VRCompositor()
+		{
+			CheckClear();
+			if ( m_pVRCompositor == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRCompositor = ( IVRCompositor * )VR_GetGenericInterface( IVRCompositor_Version, &eError );
+			}
+			return m_pVRCompositor;
+		}
+
+		IVROverlay *VROverlay()
+		{
+			CheckClear();
+			if ( m_pVROverlay == nullptr )
+			{
+				EVRInitError eError;
+				m_pVROverlay = ( IVROverlay * )VR_GetGenericInterface( IVROverlay_Version, &eError );
+			}
+			return m_pVROverlay;
+		}
+
+		IVRResources *VRResources()
+		{
+			CheckClear();
+			if ( m_pVRResources == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRResources = (IVRResources *)VR_GetGenericInterface( IVRResources_Version, &eError );
+			}
+			return m_pVRResources;
+		}
+
+		IVRScreenshots *VRScreenshots()
+		{
+			CheckClear();
+			if ( m_pVRScreenshots == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRScreenshots = ( IVRScreenshots * )VR_GetGenericInterface( IVRScreenshots_Version, &eError );
+			}
+			return m_pVRScreenshots;
+		}
+
+		IVRRenderModels *VRRenderModels()
+		{
+			CheckClear();
+			if ( m_pVRRenderModels == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRRenderModels = ( IVRRenderModels * )VR_GetGenericInterface( IVRRenderModels_Version, &eError );
+			}
+			return m_pVRRenderModels;
+		}
+
+		IVRExtendedDisplay *VRExtendedDisplay()
+		{
+			CheckClear();
+			if ( m_pVRExtendedDisplay == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRExtendedDisplay = ( IVRExtendedDisplay * )VR_GetGenericInterface( IVRExtendedDisplay_Version, &eError );
+			}
+			return m_pVRExtendedDisplay;
+		}
+
+		IVRSettings *VRSettings()
+		{
+			CheckClear();
+			if ( m_pVRSettings == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRSettings = ( IVRSettings * )VR_GetGenericInterface( IVRSettings_Version, &eError );
+			}
+			return m_pVRSettings;
+		}
+
+		IVRApplications *VRApplications()
+		{
+			CheckClear();
+			if ( m_pVRApplications == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRApplications = ( IVRApplications * )VR_GetGenericInterface( IVRApplications_Version, &eError );
+			}
+			return m_pVRApplications;
+		}
+
+		IVRTrackedCamera *VRTrackedCamera()
+		{
+			CheckClear();
+			if ( m_pVRTrackedCamera == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRTrackedCamera = ( IVRTrackedCamera * )VR_GetGenericInterface( IVRTrackedCamera_Version, &eError );
+			}
+			return m_pVRTrackedCamera;
+		}
+
+	private:
+		IVRSystem			*m_pVRSystem;
+		IVRChaperone		*m_pVRChaperone;
+		IVRChaperoneSetup	*m_pVRChaperoneSetup;
+		IVRCompositor		*m_pVRCompositor;
+		IVROverlay			*m_pVROverlay;
+		IVRResources		*m_pVRResources;
+		IVRRenderModels		*m_pVRRenderModels;
+		IVRExtendedDisplay	*m_pVRExtendedDisplay;
+		IVRSettings			*m_pVRSettings;
+		IVRApplications		*m_pVRApplications;
+		IVRTrackedCamera	*m_pVRTrackedCamera;
+		IVRScreenshots		*m_pVRScreenshots;
+	};
+
+	inline COpenVRContext &OpenVRInternal_ModuleContext()
+	{
+		static void *ctx[ sizeof( COpenVRContext ) / sizeof( void * ) ];
+		return *( COpenVRContext * )ctx; // bypass zero-init constructor
+	}
+
+	inline IVRSystem *VR_CALLTYPE VRSystem() { return OpenVRInternal_ModuleContext().VRSystem(); }
+	inline IVRChaperone *VR_CALLTYPE VRChaperone() { return OpenVRInternal_ModuleContext().VRChaperone(); }
+	inline IVRChaperoneSetup *VR_CALLTYPE VRChaperoneSetup() { return OpenVRInternal_ModuleContext().VRChaperoneSetup(); }
+	inline IVRCompositor *VR_CALLTYPE VRCompositor() { return OpenVRInternal_ModuleContext().VRCompositor(); }
+	inline IVROverlay *VR_CALLTYPE VROverlay() { return OpenVRInternal_ModuleContext().VROverlay(); }
+	inline IVRScreenshots *VR_CALLTYPE VRScreenshots() { return OpenVRInternal_ModuleContext().VRScreenshots(); }
+	inline IVRRenderModels *VR_CALLTYPE VRRenderModels() { return OpenVRInternal_ModuleContext().VRRenderModels(); }
+	inline IVRApplications *VR_CALLTYPE VRApplications() { return OpenVRInternal_ModuleContext().VRApplications(); }
+	inline IVRSettings *VR_CALLTYPE VRSettings() { return OpenVRInternal_ModuleContext().VRSettings(); }
+	inline IVRResources *VR_CALLTYPE VRResources() { return OpenVRInternal_ModuleContext().VRResources(); }
+	inline IVRExtendedDisplay *VR_CALLTYPE VRExtendedDisplay() { return OpenVRInternal_ModuleContext().VRExtendedDisplay(); }
+	inline IVRTrackedCamera *VR_CALLTYPE VRTrackedCamera() { return OpenVRInternal_ModuleContext().VRTrackedCamera(); }
+
+	inline void COpenVRContext::Clear()
+	{
+		m_pVRSystem = nullptr;
+		m_pVRChaperone = nullptr;
+		m_pVRChaperoneSetup = nullptr;
+		m_pVRCompositor = nullptr;
+		m_pVROverlay = nullptr;
+		m_pVRRenderModels = nullptr;
+		m_pVRExtendedDisplay = nullptr;
+		m_pVRSettings = nullptr;
+		m_pVRApplications = nullptr;
+		m_pVRTrackedCamera = nullptr;
+		m_pVRResources = nullptr;
+		m_pVRScreenshots = nullptr;
+	}
+
+	VR_INTERFACE uint32_t VR_CALLTYPE VR_InitInternal( EVRInitError *peError, EVRApplicationType eApplicationType );
+	VR_INTERFACE void VR_CALLTYPE VR_ShutdownInternal();
+
+	/** Finds the active installation of vrclient.dll and initializes it */
+	inline IVRSystem *VR_Init( EVRInitError *peError, EVRApplicationType eApplicationType )
+	{
+		IVRSystem *pVRSystem = nullptr;
+
+		EVRInitError eError;
+		VRToken() = VR_InitInternal( &eError, eApplicationType );
+		COpenVRContext &ctx = OpenVRInternal_ModuleContext();
+		ctx.Clear();
+
+		if ( eError == VRInitError_None )
+		{
+			if ( VR_IsInterfaceVersionValid( IVRSystem_Version ) )
+			{
+				pVRSystem = VRSystem();
+			}
+			else
+			{
+				VR_ShutdownInternal();
+				eError = VRInitError_Init_InterfaceNotFound;
+			}
+		}
+
+		if ( peError )
+			*peError = eError;
+		return pVRSystem;
+	}
+
+	/** unloads vrclient.dll. Any interface pointers from the interface are
+	* invalid after this point */
+	inline void VR_Shutdown()
+	{
+		VR_ShutdownInternal();
+	}
+}
diff --git a/third_party/openvr/src/headers/openvr_api.cs b/third_party/openvr/src/headers/openvr_api.cs
new file mode 100644
index 0000000..33bfd25
--- /dev/null
+++ b/third_party/openvr/src/headers/openvr_api.cs
@@ -0,0 +1,4786 @@
+//======= Copyright (c) Valve Corporation, All rights reserved. ===============
+//
+// Purpose: This file contains C#/managed code bindings for the OpenVR interfaces
+// This file is auto-generated, do not edit it.
+//
+//=============================================================================
+
+using System;
+using System.Runtime.InteropServices;
+using Valve.VR;
+
+namespace Valve.VR
+{
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRSystem
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetRecommendedRenderTargetSize(ref uint pnWidth, ref uint pnHeight);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetRecommendedRenderTargetSize GetRecommendedRenderTargetSize;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate HmdMatrix44_t _GetProjectionMatrix(EVREye eEye, float fNearZ, float fFarZ);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetProjectionMatrix GetProjectionMatrix;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetProjectionRaw(EVREye eEye, ref float pfLeft, ref float pfRight, ref float pfTop, ref float pfBottom);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetProjectionRaw GetProjectionRaw;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _ComputeDistortion(EVREye eEye, float fU, float fV, ref DistortionCoordinates_t pDistortionCoordinates);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ComputeDistortion ComputeDistortion;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate HmdMatrix34_t _GetEyeToHeadTransform(EVREye eEye);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetEyeToHeadTransform GetEyeToHeadTransform;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetTimeSinceLastVsync(ref float pfSecondsSinceLastVsync, ref ulong pulFrameCounter);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetTimeSinceLastVsync GetTimeSinceLastVsync;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate int _GetD3D9AdapterIndex();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetD3D9AdapterIndex GetD3D9AdapterIndex;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetDXGIOutputInfo(ref int pnAdapterIndex);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetDXGIOutputInfo GetDXGIOutputInfo;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsDisplayOnDesktop();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsDisplayOnDesktop IsDisplayOnDesktop;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _SetDisplayVisibility(bool bIsVisibleOnDesktop);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetDisplayVisibility SetDisplayVisibility;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin eOrigin, float fPredictedSecondsToPhotonsFromNow, [In, Out] TrackedDevicePose_t[] pTrackedDevicePoseArray, uint unTrackedDevicePoseArrayCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetDeviceToAbsoluteTrackingPose GetDeviceToAbsoluteTrackingPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ResetSeatedZeroPose();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ResetSeatedZeroPose ResetSeatedZeroPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate HmdMatrix34_t _GetSeatedZeroPoseToStandingAbsoluteTrackingPose();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetSeatedZeroPoseToStandingAbsoluteTrackingPose GetSeatedZeroPoseToStandingAbsoluteTrackingPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate HmdMatrix34_t _GetRawZeroPoseToStandingAbsoluteTrackingPose();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetRawZeroPoseToStandingAbsoluteTrackingPose GetRawZeroPoseToStandingAbsoluteTrackingPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetSortedTrackedDeviceIndicesOfClass(ETrackedDeviceClass eTrackedDeviceClass, [In, Out] uint[] punTrackedDeviceIndexArray, uint unTrackedDeviceIndexArrayCount, uint unRelativeToTrackedDeviceIndex);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetSortedTrackedDeviceIndicesOfClass GetSortedTrackedDeviceIndicesOfClass;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EDeviceActivityLevel _GetTrackedDeviceActivityLevel(uint unDeviceId);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetTrackedDeviceActivityLevel GetTrackedDeviceActivityLevel;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ApplyTransform(ref TrackedDevicePose_t pOutputPose, ref TrackedDevicePose_t pTrackedDevicePose, ref HmdMatrix34_t pTransform);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ApplyTransform ApplyTransform;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole unDeviceType);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetTrackedDeviceIndexForControllerRole GetTrackedDeviceIndexForControllerRole;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate ETrackedControllerRole _GetControllerRoleForTrackedDeviceIndex(uint unDeviceIndex);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetControllerRoleForTrackedDeviceIndex GetControllerRoleForTrackedDeviceIndex;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate ETrackedDeviceClass _GetTrackedDeviceClass(uint unDeviceIndex);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetTrackedDeviceClass GetTrackedDeviceClass;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsTrackedDeviceConnected(uint unDeviceIndex);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsTrackedDeviceConnected IsTrackedDeviceConnected;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetBoolTrackedDeviceProperty(uint unDeviceIndex, ETrackedDeviceProperty prop, ref ETrackedPropertyError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetBoolTrackedDeviceProperty GetBoolTrackedDeviceProperty;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate float _GetFloatTrackedDeviceProperty(uint unDeviceIndex, ETrackedDeviceProperty prop, ref ETrackedPropertyError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetFloatTrackedDeviceProperty GetFloatTrackedDeviceProperty;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate int _GetInt32TrackedDeviceProperty(uint unDeviceIndex, ETrackedDeviceProperty prop, ref ETrackedPropertyError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetInt32TrackedDeviceProperty GetInt32TrackedDeviceProperty;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate ulong _GetUint64TrackedDeviceProperty(uint unDeviceIndex, ETrackedDeviceProperty prop, ref ETrackedPropertyError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetUint64TrackedDeviceProperty GetUint64TrackedDeviceProperty;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate HmdMatrix34_t _GetMatrix34TrackedDeviceProperty(uint unDeviceIndex, ETrackedDeviceProperty prop, ref ETrackedPropertyError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetMatrix34TrackedDeviceProperty GetMatrix34TrackedDeviceProperty;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetStringTrackedDeviceProperty(uint unDeviceIndex, ETrackedDeviceProperty prop, System.Text.StringBuilder pchValue, uint unBufferSize, ref ETrackedPropertyError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetStringTrackedDeviceProperty GetStringTrackedDeviceProperty;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetPropErrorNameFromEnum(ETrackedPropertyError error);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetPropErrorNameFromEnum GetPropErrorNameFromEnum;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _PollNextEvent(ref VREvent_t pEvent, uint uncbVREvent);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _PollNextEvent PollNextEvent;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _PollNextEventWithPose(ETrackingUniverseOrigin eOrigin, ref VREvent_t pEvent, uint uncbVREvent, ref TrackedDevicePose_t pTrackedDevicePose);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _PollNextEventWithPose PollNextEventWithPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetEventTypeNameFromEnum(EVREventType eType);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetEventTypeNameFromEnum GetEventTypeNameFromEnum;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate HiddenAreaMesh_t _GetHiddenAreaMesh(EVREye eEye, EHiddenAreaMeshType type);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetHiddenAreaMesh GetHiddenAreaMesh;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetControllerState(uint unControllerDeviceIndex, ref VRControllerState_t pControllerState, uint unControllerStateSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetControllerState GetControllerState;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetControllerStateWithPose(ETrackingUniverseOrigin eOrigin, uint unControllerDeviceIndex, ref VRControllerState_t pControllerState, uint unControllerStateSize, ref TrackedDevicePose_t pTrackedDevicePose);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetControllerStateWithPose GetControllerStateWithPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _TriggerHapticPulse(uint unControllerDeviceIndex, uint unAxisId, char usDurationMicroSec);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _TriggerHapticPulse TriggerHapticPulse;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetButtonIdNameFromEnum(EVRButtonId eButtonId);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetButtonIdNameFromEnum GetButtonIdNameFromEnum;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetControllerAxisTypeNameFromEnum(EVRControllerAxisType eAxisType);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetControllerAxisTypeNameFromEnum GetControllerAxisTypeNameFromEnum;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _CaptureInputFocus();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CaptureInputFocus CaptureInputFocus;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ReleaseInputFocus();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ReleaseInputFocus ReleaseInputFocus;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsInputFocusCapturedByAnotherProcess();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsInputFocusCapturedByAnotherProcess IsInputFocusCapturedByAnotherProcess;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _DriverDebugRequest(uint unDeviceIndex, string pchRequest, string pchResponseBuffer, uint unResponseBufferSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _DriverDebugRequest DriverDebugRequest;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRFirmwareError _PerformFirmwareUpdate(uint unDeviceIndex);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _PerformFirmwareUpdate PerformFirmwareUpdate;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _AcknowledgeQuit_Exiting();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _AcknowledgeQuit_Exiting AcknowledgeQuit_Exiting;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _AcknowledgeQuit_UserPrompt();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _AcknowledgeQuit_UserPrompt AcknowledgeQuit_UserPrompt;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRExtendedDisplay
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetWindowBounds(ref int pnX, ref int pnY, ref uint pnWidth, ref uint pnHeight);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetWindowBounds GetWindowBounds;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetEyeOutputViewport(EVREye eEye, ref uint pnX, ref uint pnY, ref uint pnWidth, ref uint pnHeight);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetEyeOutputViewport GetEyeOutputViewport;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetDXGIOutputInfo(ref int pnAdapterIndex, ref int pnAdapterOutputIndex);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetDXGIOutputInfo GetDXGIOutputInfo;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRTrackedCamera
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetCameraErrorNameFromEnum(EVRTrackedCameraError eCameraError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCameraErrorNameFromEnum GetCameraErrorNameFromEnum;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _HasCamera(uint nDeviceIndex, ref bool pHasCamera);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _HasCamera HasCamera;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _GetCameraFrameSize(uint nDeviceIndex, EVRTrackedCameraFrameType eFrameType, ref uint pnWidth, ref uint pnHeight, ref uint pnFrameBufferSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCameraFrameSize GetCameraFrameSize;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _GetCameraIntrinsics(uint nDeviceIndex, EVRTrackedCameraFrameType eFrameType, ref HmdVector2_t pFocalLength, ref HmdVector2_t pCenter);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCameraIntrinsics GetCameraIntrinsics;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _GetCameraProjection(uint nDeviceIndex, EVRTrackedCameraFrameType eFrameType, float flZNear, float flZFar, ref HmdMatrix44_t pProjection);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCameraProjection GetCameraProjection;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _AcquireVideoStreamingService(uint nDeviceIndex, ref ulong pHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _AcquireVideoStreamingService AcquireVideoStreamingService;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _ReleaseVideoStreamingService(ulong hTrackedCamera);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ReleaseVideoStreamingService ReleaseVideoStreamingService;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _GetVideoStreamFrameBuffer(ulong hTrackedCamera, EVRTrackedCameraFrameType eFrameType, IntPtr pFrameBuffer, uint nFrameBufferSize, ref CameraVideoStreamFrameHeader_t pFrameHeader, uint nFrameHeaderSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetVideoStreamFrameBuffer GetVideoStreamFrameBuffer;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _GetVideoStreamTextureSize(uint nDeviceIndex, EVRTrackedCameraFrameType eFrameType, ref VRTextureBounds_t pTextureBounds, ref uint pnWidth, ref uint pnHeight);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetVideoStreamTextureSize GetVideoStreamTextureSize;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _GetVideoStreamTextureD3D11(ulong hTrackedCamera, EVRTrackedCameraFrameType eFrameType, IntPtr pD3D11DeviceOrResource, ref IntPtr ppD3D11ShaderResourceView, ref CameraVideoStreamFrameHeader_t pFrameHeader, uint nFrameHeaderSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetVideoStreamTextureD3D11 GetVideoStreamTextureD3D11;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _GetVideoStreamTextureGL(ulong hTrackedCamera, EVRTrackedCameraFrameType eFrameType, ref uint pglTextureId, ref CameraVideoStreamFrameHeader_t pFrameHeader, uint nFrameHeaderSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetVideoStreamTextureGL GetVideoStreamTextureGL;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRTrackedCameraError _ReleaseVideoStreamTextureGL(ulong hTrackedCamera, uint glTextureId);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ReleaseVideoStreamTextureGL ReleaseVideoStreamTextureGL;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRApplications
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _AddApplicationManifest(string pchApplicationManifestFullPath, bool bTemporary);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _AddApplicationManifest AddApplicationManifest;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _RemoveApplicationManifest(string pchApplicationManifestFullPath);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _RemoveApplicationManifest RemoveApplicationManifest;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsApplicationInstalled(string pchAppKey);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsApplicationInstalled IsApplicationInstalled;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetApplicationCount();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationCount GetApplicationCount;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _GetApplicationKeyByIndex(uint unApplicationIndex, System.Text.StringBuilder pchAppKeyBuffer, uint unAppKeyBufferLen);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationKeyByIndex GetApplicationKeyByIndex;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _GetApplicationKeyByProcessId(uint unProcessId, string pchAppKeyBuffer, uint unAppKeyBufferLen);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationKeyByProcessId GetApplicationKeyByProcessId;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _LaunchApplication(string pchAppKey);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LaunchApplication LaunchApplication;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _LaunchTemplateApplication(string pchTemplateAppKey, string pchNewAppKey, [In, Out] AppOverrideKeys_t[] pKeys, uint unKeys);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LaunchTemplateApplication LaunchTemplateApplication;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _LaunchApplicationFromMimeType(string pchMimeType, string pchArgs);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LaunchApplicationFromMimeType LaunchApplicationFromMimeType;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _LaunchDashboardOverlay(string pchAppKey);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LaunchDashboardOverlay LaunchDashboardOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _CancelApplicationLaunch(string pchAppKey);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CancelApplicationLaunch CancelApplicationLaunch;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _IdentifyApplication(uint unProcessId, string pchAppKey);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IdentifyApplication IdentifyApplication;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetApplicationProcessId(string pchAppKey);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationProcessId GetApplicationProcessId;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetApplicationsErrorNameFromEnum(EVRApplicationError error);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationsErrorNameFromEnum GetApplicationsErrorNameFromEnum;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetApplicationPropertyString(string pchAppKey, EVRApplicationProperty eProperty, System.Text.StringBuilder pchPropertyValueBuffer, uint unPropertyValueBufferLen, ref EVRApplicationError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationPropertyString GetApplicationPropertyString;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetApplicationPropertyBool(string pchAppKey, EVRApplicationProperty eProperty, ref EVRApplicationError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationPropertyBool GetApplicationPropertyBool;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate ulong _GetApplicationPropertyUint64(string pchAppKey, EVRApplicationProperty eProperty, ref EVRApplicationError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationPropertyUint64 GetApplicationPropertyUint64;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _SetApplicationAutoLaunch(string pchAppKey, bool bAutoLaunch);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetApplicationAutoLaunch SetApplicationAutoLaunch;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetApplicationAutoLaunch(string pchAppKey);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationAutoLaunch GetApplicationAutoLaunch;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _SetDefaultApplicationForMimeType(string pchAppKey, string pchMimeType);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetDefaultApplicationForMimeType SetDefaultApplicationForMimeType;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetDefaultApplicationForMimeType(string pchMimeType, string pchAppKeyBuffer, uint unAppKeyBufferLen);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetDefaultApplicationForMimeType GetDefaultApplicationForMimeType;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetApplicationSupportedMimeTypes(string pchAppKey, string pchMimeTypesBuffer, uint unMimeTypesBuffer);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationSupportedMimeTypes GetApplicationSupportedMimeTypes;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetApplicationsThatSupportMimeType(string pchMimeType, string pchAppKeysThatSupportBuffer, uint unAppKeysThatSupportBuffer);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationsThatSupportMimeType GetApplicationsThatSupportMimeType;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetApplicationLaunchArguments(uint unHandle, string pchArgs, uint unArgs);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationLaunchArguments GetApplicationLaunchArguments;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _GetStartingApplication(string pchAppKeyBuffer, uint unAppKeyBufferLen);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetStartingApplication GetStartingApplication;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationTransitionState _GetTransitionState();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetTransitionState GetTransitionState;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _PerformApplicationPrelaunchCheck(string pchAppKey);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _PerformApplicationPrelaunchCheck PerformApplicationPrelaunchCheck;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetApplicationsTransitionStateNameFromEnum(EVRApplicationTransitionState state);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetApplicationsTransitionStateNameFromEnum GetApplicationsTransitionStateNameFromEnum;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsQuitUserPromptRequested();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsQuitUserPromptRequested IsQuitUserPromptRequested;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRApplicationError _LaunchInternalProcess(string pchBinaryPath, string pchArguments, string pchWorkingDirectory);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LaunchInternalProcess LaunchInternalProcess;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetCurrentSceneProcessId();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCurrentSceneProcessId GetCurrentSceneProcessId;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRChaperone
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate ChaperoneCalibrationState _GetCalibrationState();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCalibrationState GetCalibrationState;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetPlayAreaSize(ref float pSizeX, ref float pSizeZ);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetPlayAreaSize GetPlayAreaSize;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetPlayAreaRect(ref HmdQuad_t rect);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetPlayAreaRect GetPlayAreaRect;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ReloadInfo();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ReloadInfo ReloadInfo;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetSceneColor(HmdColor_t color);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetSceneColor SetSceneColor;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetBoundsColor(ref HmdColor_t pOutputColorArray, int nNumOutputColors, float flCollisionBoundsFadeDistance, ref HmdColor_t pOutputCameraColor);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetBoundsColor GetBoundsColor;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _AreBoundsVisible();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _AreBoundsVisible AreBoundsVisible;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ForceBoundsVisible(bool bForce);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ForceBoundsVisible ForceBoundsVisible;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRChaperoneSetup
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _CommitWorkingCopy(EChaperoneConfigFile configFile);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CommitWorkingCopy CommitWorkingCopy;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _RevertWorkingCopy();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _RevertWorkingCopy RevertWorkingCopy;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetWorkingPlayAreaSize(ref float pSizeX, ref float pSizeZ);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetWorkingPlayAreaSize GetWorkingPlayAreaSize;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetWorkingPlayAreaRect(ref HmdQuad_t rect);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetWorkingPlayAreaRect GetWorkingPlayAreaRect;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetWorkingCollisionBoundsInfo([In, Out] HmdQuad_t[] pQuadsBuffer, ref uint punQuadsCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetWorkingCollisionBoundsInfo GetWorkingCollisionBoundsInfo;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetLiveCollisionBoundsInfo([In, Out] HmdQuad_t[] pQuadsBuffer, ref uint punQuadsCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetLiveCollisionBoundsInfo GetLiveCollisionBoundsInfo;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetWorkingSeatedZeroPoseToRawTrackingPose(ref HmdMatrix34_t pmatSeatedZeroPoseToRawTrackingPose);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetWorkingSeatedZeroPoseToRawTrackingPose GetWorkingSeatedZeroPoseToRawTrackingPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetWorkingStandingZeroPoseToRawTrackingPose(ref HmdMatrix34_t pmatStandingZeroPoseToRawTrackingPose);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetWorkingStandingZeroPoseToRawTrackingPose GetWorkingStandingZeroPoseToRawTrackingPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetWorkingPlayAreaSize(float sizeX, float sizeZ);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetWorkingPlayAreaSize SetWorkingPlayAreaSize;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetWorkingCollisionBoundsInfo([In, Out] HmdQuad_t[] pQuadsBuffer, uint unQuadsCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetWorkingCollisionBoundsInfo SetWorkingCollisionBoundsInfo;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetWorkingSeatedZeroPoseToRawTrackingPose(ref HmdMatrix34_t pMatSeatedZeroPoseToRawTrackingPose);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetWorkingSeatedZeroPoseToRawTrackingPose SetWorkingSeatedZeroPoseToRawTrackingPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetWorkingStandingZeroPoseToRawTrackingPose(ref HmdMatrix34_t pMatStandingZeroPoseToRawTrackingPose);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetWorkingStandingZeroPoseToRawTrackingPose SetWorkingStandingZeroPoseToRawTrackingPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ReloadFromDisk(EChaperoneConfigFile configFile);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ReloadFromDisk ReloadFromDisk;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetLiveSeatedZeroPoseToRawTrackingPose(ref HmdMatrix34_t pmatSeatedZeroPoseToRawTrackingPose);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetLiveSeatedZeroPoseToRawTrackingPose GetLiveSeatedZeroPoseToRawTrackingPose;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetWorkingCollisionBoundsTagsInfo([In, Out] byte[] pTagsBuffer, uint unTagCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetWorkingCollisionBoundsTagsInfo SetWorkingCollisionBoundsTagsInfo;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetLiveCollisionBoundsTagsInfo([In, Out] byte[] pTagsBuffer, ref uint punTagCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetLiveCollisionBoundsTagsInfo GetLiveCollisionBoundsTagsInfo;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _SetWorkingPhysicalBoundsInfo([In, Out] HmdQuad_t[] pQuadsBuffer, uint unQuadsCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetWorkingPhysicalBoundsInfo SetWorkingPhysicalBoundsInfo;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetLivePhysicalBoundsInfo([In, Out] HmdQuad_t[] pQuadsBuffer, ref uint punQuadsCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetLivePhysicalBoundsInfo GetLivePhysicalBoundsInfo;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _ExportLiveToBuffer(System.Text.StringBuilder pBuffer, ref uint pnBufferLength);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ExportLiveToBuffer ExportLiveToBuffer;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _ImportFromBufferToWorking(string pBuffer, uint nImportFlags);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ImportFromBufferToWorking ImportFromBufferToWorking;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRCompositor
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetTrackingSpace(ETrackingUniverseOrigin eOrigin);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetTrackingSpace SetTrackingSpace;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate ETrackingUniverseOrigin _GetTrackingSpace();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetTrackingSpace GetTrackingSpace;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRCompositorError _WaitGetPoses([In, Out] TrackedDevicePose_t[] pRenderPoseArray, uint unRenderPoseArrayCount, [In, Out] TrackedDevicePose_t[] pGamePoseArray, uint unGamePoseArrayCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _WaitGetPoses WaitGetPoses;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRCompositorError _GetLastPoses([In, Out] TrackedDevicePose_t[] pRenderPoseArray, uint unRenderPoseArrayCount, [In, Out] TrackedDevicePose_t[] pGamePoseArray, uint unGamePoseArrayCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetLastPoses GetLastPoses;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRCompositorError _GetLastPoseForTrackedDeviceIndex(uint unDeviceIndex, ref TrackedDevicePose_t pOutputPose, ref TrackedDevicePose_t pOutputGamePose);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetLastPoseForTrackedDeviceIndex GetLastPoseForTrackedDeviceIndex;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRCompositorError _Submit(EVREye eEye, ref Texture_t pTexture, ref VRTextureBounds_t pBounds, EVRSubmitFlags nSubmitFlags);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _Submit Submit;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ClearLastSubmittedFrame();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ClearLastSubmittedFrame ClearLastSubmittedFrame;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _PostPresentHandoff();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _PostPresentHandoff PostPresentHandoff;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetFrameTiming(ref Compositor_FrameTiming pTiming, uint unFramesAgo);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetFrameTiming GetFrameTiming;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetFrameTimings(ref Compositor_FrameTiming pTiming, uint nFrames);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetFrameTimings GetFrameTimings;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate float _GetFrameTimeRemaining();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetFrameTimeRemaining GetFrameTimeRemaining;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetCumulativeStats(ref Compositor_CumulativeStats pStats, uint nStatsSizeInBytes);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCumulativeStats GetCumulativeStats;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _FadeToColor(float fSeconds, float fRed, float fGreen, float fBlue, float fAlpha, bool bBackground);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _FadeToColor FadeToColor;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate HmdColor_t _GetCurrentFadeColor(bool bBackground);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCurrentFadeColor GetCurrentFadeColor;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _FadeGrid(float fSeconds, bool bFadeIn);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _FadeGrid FadeGrid;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate float _GetCurrentGridAlpha();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCurrentGridAlpha GetCurrentGridAlpha;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRCompositorError _SetSkyboxOverride([In, Out] Texture_t[] pTextures, uint unTextureCount);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetSkyboxOverride SetSkyboxOverride;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ClearSkyboxOverride();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ClearSkyboxOverride ClearSkyboxOverride;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _CompositorBringToFront();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CompositorBringToFront CompositorBringToFront;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _CompositorGoToBack();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CompositorGoToBack CompositorGoToBack;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _CompositorQuit();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CompositorQuit CompositorQuit;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsFullscreen();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsFullscreen IsFullscreen;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetCurrentSceneFocusProcess();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetCurrentSceneFocusProcess GetCurrentSceneFocusProcess;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetLastFrameRenderer();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetLastFrameRenderer GetLastFrameRenderer;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _CanRenderScene();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CanRenderScene CanRenderScene;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ShowMirrorWindow();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ShowMirrorWindow ShowMirrorWindow;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _HideMirrorWindow();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _HideMirrorWindow HideMirrorWindow;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsMirrorWindowVisible();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsMirrorWindowVisible IsMirrorWindowVisible;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _CompositorDumpImages();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CompositorDumpImages CompositorDumpImages;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _ShouldAppRenderWithLowResources();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ShouldAppRenderWithLowResources ShouldAppRenderWithLowResources;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ForceInterleavedReprojectionOn(bool bOverride);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ForceInterleavedReprojectionOn ForceInterleavedReprojectionOn;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ForceReconnectProcess();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ForceReconnectProcess ForceReconnectProcess;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SuspendRendering(bool bSuspend);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SuspendRendering SuspendRendering;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRCompositorError _GetMirrorTextureD3D11(EVREye eEye, IntPtr pD3D11DeviceOrResource, ref IntPtr ppD3D11ShaderResourceView);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetMirrorTextureD3D11 GetMirrorTextureD3D11;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ReleaseMirrorTextureD3D11(IntPtr pD3D11ShaderResourceView);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ReleaseMirrorTextureD3D11 ReleaseMirrorTextureD3D11;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRCompositorError _GetMirrorTextureGL(EVREye eEye, ref uint pglTextureId, IntPtr pglSharedTextureHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetMirrorTextureGL GetMirrorTextureGL;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _ReleaseSharedGLTexture(uint glTextureId, IntPtr glSharedTextureHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ReleaseSharedGLTexture ReleaseSharedGLTexture;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _LockGLSharedTextureForAccess(IntPtr glSharedTextureHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LockGLSharedTextureForAccess LockGLSharedTextureForAccess;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _UnlockGLSharedTextureForAccess(IntPtr glSharedTextureHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _UnlockGLSharedTextureForAccess UnlockGLSharedTextureForAccess;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetVulkanInstanceExtensionsRequired(System.Text.StringBuilder pchValue, uint unBufferSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetVulkanInstanceExtensionsRequired GetVulkanInstanceExtensionsRequired;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetVulkanDeviceExtensionsRequired(IntPtr pPhysicalDevice, System.Text.StringBuilder pchValue, uint unBufferSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetVulkanDeviceExtensionsRequired GetVulkanDeviceExtensionsRequired;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVROverlay
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _FindOverlay(string pchOverlayKey, ref ulong pOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _FindOverlay FindOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _CreateOverlay(string pchOverlayKey, string pchOverlayFriendlyName, ref ulong pOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CreateOverlay CreateOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _DestroyOverlay(ulong ulOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _DestroyOverlay DestroyOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetHighQualityOverlay(ulong ulOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetHighQualityOverlay SetHighQualityOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate ulong _GetHighQualityOverlay();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetHighQualityOverlay GetHighQualityOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetOverlayKey(ulong ulOverlayHandle, System.Text.StringBuilder pchValue, uint unBufferSize, ref EVROverlayError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayKey GetOverlayKey;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetOverlayName(ulong ulOverlayHandle, System.Text.StringBuilder pchValue, uint unBufferSize, ref EVROverlayError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayName GetOverlayName;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayImageData(ulong ulOverlayHandle, IntPtr pvBuffer, uint unBufferSize, ref uint punWidth, ref uint punHeight);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayImageData GetOverlayImageData;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetOverlayErrorNameFromEnum(EVROverlayError error);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayErrorNameFromEnum GetOverlayErrorNameFromEnum;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayRenderingPid(ulong ulOverlayHandle, uint unPID);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayRenderingPid SetOverlayRenderingPid;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetOverlayRenderingPid(ulong ulOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayRenderingPid GetOverlayRenderingPid;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayFlag(ulong ulOverlayHandle, VROverlayFlags eOverlayFlag, bool bEnabled);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayFlag SetOverlayFlag;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayFlag(ulong ulOverlayHandle, VROverlayFlags eOverlayFlag, ref bool pbEnabled);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayFlag GetOverlayFlag;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayColor(ulong ulOverlayHandle, float fRed, float fGreen, float fBlue);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayColor SetOverlayColor;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayColor(ulong ulOverlayHandle, ref float pfRed, ref float pfGreen, ref float pfBlue);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayColor GetOverlayColor;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayAlpha(ulong ulOverlayHandle, float fAlpha);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayAlpha SetOverlayAlpha;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayAlpha(ulong ulOverlayHandle, ref float pfAlpha);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayAlpha GetOverlayAlpha;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayTexelAspect(ulong ulOverlayHandle, float fTexelAspect);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayTexelAspect SetOverlayTexelAspect;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayTexelAspect(ulong ulOverlayHandle, ref float pfTexelAspect);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayTexelAspect GetOverlayTexelAspect;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlaySortOrder(ulong ulOverlayHandle, uint unSortOrder);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlaySortOrder SetOverlaySortOrder;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlaySortOrder(ulong ulOverlayHandle, ref uint punSortOrder);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlaySortOrder GetOverlaySortOrder;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayWidthInMeters(ulong ulOverlayHandle, float fWidthInMeters);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayWidthInMeters SetOverlayWidthInMeters;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayWidthInMeters(ulong ulOverlayHandle, ref float pfWidthInMeters);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayWidthInMeters GetOverlayWidthInMeters;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayAutoCurveDistanceRangeInMeters(ulong ulOverlayHandle, float fMinDistanceInMeters, float fMaxDistanceInMeters);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayAutoCurveDistanceRangeInMeters SetOverlayAutoCurveDistanceRangeInMeters;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayAutoCurveDistanceRangeInMeters(ulong ulOverlayHandle, ref float pfMinDistanceInMeters, ref float pfMaxDistanceInMeters);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayAutoCurveDistanceRangeInMeters GetOverlayAutoCurveDistanceRangeInMeters;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayTextureColorSpace(ulong ulOverlayHandle, EColorSpace eTextureColorSpace);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayTextureColorSpace SetOverlayTextureColorSpace;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayTextureColorSpace(ulong ulOverlayHandle, ref EColorSpace peTextureColorSpace);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayTextureColorSpace GetOverlayTextureColorSpace;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayTextureBounds(ulong ulOverlayHandle, ref VRTextureBounds_t pOverlayTextureBounds);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayTextureBounds SetOverlayTextureBounds;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayTextureBounds(ulong ulOverlayHandle, ref VRTextureBounds_t pOverlayTextureBounds);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayTextureBounds GetOverlayTextureBounds;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayTransformType(ulong ulOverlayHandle, ref VROverlayTransformType peTransformType);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayTransformType GetOverlayTransformType;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayTransformAbsolute(ulong ulOverlayHandle, ETrackingUniverseOrigin eTrackingOrigin, ref HmdMatrix34_t pmatTrackingOriginToOverlayTransform);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayTransformAbsolute SetOverlayTransformAbsolute;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayTransformAbsolute(ulong ulOverlayHandle, ref ETrackingUniverseOrigin peTrackingOrigin, ref HmdMatrix34_t pmatTrackingOriginToOverlayTransform);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayTransformAbsolute GetOverlayTransformAbsolute;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayTransformTrackedDeviceRelative(ulong ulOverlayHandle, uint unTrackedDevice, ref HmdMatrix34_t pmatTrackedDeviceToOverlayTransform);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayTransformTrackedDeviceRelative SetOverlayTransformTrackedDeviceRelative;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayTransformTrackedDeviceRelative(ulong ulOverlayHandle, ref uint punTrackedDevice, ref HmdMatrix34_t pmatTrackedDeviceToOverlayTransform);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayTransformTrackedDeviceRelative GetOverlayTransformTrackedDeviceRelative;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayTransformTrackedDeviceComponent(ulong ulOverlayHandle, uint unDeviceIndex, string pchComponentName);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayTransformTrackedDeviceComponent SetOverlayTransformTrackedDeviceComponent;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayTransformTrackedDeviceComponent(ulong ulOverlayHandle, ref uint punDeviceIndex, string pchComponentName, uint unComponentNameSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayTransformTrackedDeviceComponent GetOverlayTransformTrackedDeviceComponent;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _ShowOverlay(ulong ulOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ShowOverlay ShowOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _HideOverlay(ulong ulOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _HideOverlay HideOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsOverlayVisible(ulong ulOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsOverlayVisible IsOverlayVisible;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetTransformForOverlayCoordinates(ulong ulOverlayHandle, ETrackingUniverseOrigin eTrackingOrigin, HmdVector2_t coordinatesInOverlay, ref HmdMatrix34_t pmatTransform);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetTransformForOverlayCoordinates GetTransformForOverlayCoordinates;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _PollNextOverlayEvent(ulong ulOverlayHandle, ref VREvent_t pEvent, uint uncbVREvent);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _PollNextOverlayEvent PollNextOverlayEvent;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayInputMethod(ulong ulOverlayHandle, ref VROverlayInputMethod peInputMethod);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayInputMethod GetOverlayInputMethod;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayInputMethod(ulong ulOverlayHandle, VROverlayInputMethod eInputMethod);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayInputMethod SetOverlayInputMethod;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayMouseScale(ulong ulOverlayHandle, ref HmdVector2_t pvecMouseScale);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayMouseScale GetOverlayMouseScale;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayMouseScale(ulong ulOverlayHandle, ref HmdVector2_t pvecMouseScale);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayMouseScale SetOverlayMouseScale;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _ComputeOverlayIntersection(ulong ulOverlayHandle, ref VROverlayIntersectionParams_t pParams, ref VROverlayIntersectionResults_t pResults);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ComputeOverlayIntersection ComputeOverlayIntersection;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _HandleControllerOverlayInteractionAsMouse(ulong ulOverlayHandle, uint unControllerDeviceIndex);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _HandleControllerOverlayInteractionAsMouse HandleControllerOverlayInteractionAsMouse;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsHoverTargetOverlay(ulong ulOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsHoverTargetOverlay IsHoverTargetOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate ulong _GetGamepadFocusOverlay();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetGamepadFocusOverlay GetGamepadFocusOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetGamepadFocusOverlay(ulong ulNewFocusOverlay);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetGamepadFocusOverlay SetGamepadFocusOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayNeighbor(EOverlayDirection eDirection, ulong ulFrom, ulong ulTo);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayNeighbor SetOverlayNeighbor;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _MoveGamepadFocusToNeighbor(EOverlayDirection eDirection, ulong ulFrom);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _MoveGamepadFocusToNeighbor MoveGamepadFocusToNeighbor;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayTexture(ulong ulOverlayHandle, ref Texture_t pTexture);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayTexture SetOverlayTexture;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _ClearOverlayTexture(ulong ulOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ClearOverlayTexture ClearOverlayTexture;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayRaw(ulong ulOverlayHandle, IntPtr pvBuffer, uint unWidth, uint unHeight, uint unDepth);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayRaw SetOverlayRaw;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayFromFile(ulong ulOverlayHandle, string pchFilePath);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayFromFile SetOverlayFromFile;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayTexture(ulong ulOverlayHandle, ref IntPtr pNativeTextureHandle, IntPtr pNativeTextureRef, ref uint pWidth, ref uint pHeight, ref uint pNativeFormat, ref ETextureType pAPIType, ref EColorSpace pColorSpace, ref VRTextureBounds_t pTextureBounds);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayTexture GetOverlayTexture;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _ReleaseNativeOverlayHandle(ulong ulOverlayHandle, IntPtr pNativeTextureHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ReleaseNativeOverlayHandle ReleaseNativeOverlayHandle;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayTextureSize(ulong ulOverlayHandle, ref uint pWidth, ref uint pHeight);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayTextureSize GetOverlayTextureSize;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _CreateDashboardOverlay(string pchOverlayKey, string pchOverlayFriendlyName, ref ulong pMainHandle, ref ulong pThumbnailHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CreateDashboardOverlay CreateDashboardOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsDashboardVisible();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsDashboardVisible IsDashboardVisible;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _IsActiveDashboardOverlay(ulong ulOverlayHandle);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _IsActiveDashboardOverlay IsActiveDashboardOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetDashboardOverlaySceneProcess(ulong ulOverlayHandle, uint unProcessId);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetDashboardOverlaySceneProcess SetDashboardOverlaySceneProcess;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetDashboardOverlaySceneProcess(ulong ulOverlayHandle, ref uint punProcessId);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetDashboardOverlaySceneProcess GetDashboardOverlaySceneProcess;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _ShowDashboard(string pchOverlayToShow);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ShowDashboard ShowDashboard;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetPrimaryDashboardDevice();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetPrimaryDashboardDevice GetPrimaryDashboardDevice;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _ShowKeyboard(int eInputMode, int eLineInputMode, string pchDescription, uint unCharMax, string pchExistingText, bool bUseMinimalMode, ulong uUserValue);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ShowKeyboard ShowKeyboard;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _ShowKeyboardForOverlay(ulong ulOverlayHandle, int eInputMode, int eLineInputMode, string pchDescription, uint unCharMax, string pchExistingText, bool bUseMinimalMode, ulong uUserValue);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ShowKeyboardForOverlay ShowKeyboardForOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetKeyboardText(System.Text.StringBuilder pchText, uint cchText);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetKeyboardText GetKeyboardText;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _HideKeyboard();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _HideKeyboard HideKeyboard;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetKeyboardTransformAbsolute(ETrackingUniverseOrigin eTrackingOrigin, ref HmdMatrix34_t pmatTrackingOriginToKeyboardTransform);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetKeyboardTransformAbsolute SetKeyboardTransformAbsolute;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetKeyboardPositionForOverlay(ulong ulOverlayHandle, HmdRect2_t avoidRect);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetKeyboardPositionForOverlay SetKeyboardPositionForOverlay;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _SetOverlayIntersectionMask(ulong ulOverlayHandle, ref VROverlayIntersectionMaskPrimitive_t pMaskPrimitives, uint unNumMaskPrimitives, uint unPrimitiveSize);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetOverlayIntersectionMask SetOverlayIntersectionMask;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVROverlayError _GetOverlayFlags(ulong ulOverlayHandle, ref uint pFlags);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetOverlayFlags GetOverlayFlags;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate VRMessageOverlayResponse _ShowMessageOverlay(string pchText, string pchCaption, string pchButton0Text, string pchButton1Text, string pchButton2Text, string pchButton3Text);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _ShowMessageOverlay ShowMessageOverlay;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRRenderModels
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRRenderModelError _LoadRenderModel_Async(string pchRenderModelName, ref IntPtr ppRenderModel);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LoadRenderModel_Async LoadRenderModel_Async;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _FreeRenderModel(IntPtr pRenderModel);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _FreeRenderModel FreeRenderModel;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRRenderModelError _LoadTexture_Async(int textureId, ref IntPtr ppTexture);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LoadTexture_Async LoadTexture_Async;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _FreeTexture(IntPtr pTexture);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _FreeTexture FreeTexture;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRRenderModelError _LoadTextureD3D11_Async(int textureId, IntPtr pD3D11Device, ref IntPtr ppD3D11Texture2D);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LoadTextureD3D11_Async LoadTextureD3D11_Async;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRRenderModelError _LoadIntoTextureD3D11_Async(int textureId, IntPtr pDstTexture);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LoadIntoTextureD3D11_Async LoadIntoTextureD3D11_Async;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _FreeTextureD3D11(IntPtr pD3D11Texture2D);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _FreeTextureD3D11 FreeTextureD3D11;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetRenderModelName(uint unRenderModelIndex, System.Text.StringBuilder pchRenderModelName, uint unRenderModelNameLen);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetRenderModelName GetRenderModelName;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetRenderModelCount();
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetRenderModelCount GetRenderModelCount;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetComponentCount(string pchRenderModelName);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetComponentCount GetComponentCount;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetComponentName(string pchRenderModelName, uint unComponentIndex, System.Text.StringBuilder pchComponentName, uint unComponentNameLen);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetComponentName GetComponentName;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate ulong _GetComponentButtonMask(string pchRenderModelName, string pchComponentName);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetComponentButtonMask GetComponentButtonMask;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetComponentRenderModelName(string pchRenderModelName, string pchComponentName, System.Text.StringBuilder pchComponentRenderModelName, uint unComponentRenderModelNameLen);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetComponentRenderModelName GetComponentRenderModelName;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetComponentState(string pchRenderModelName, string pchComponentName, ref VRControllerState_t pControllerState, ref RenderModel_ControllerMode_State_t pState, ref RenderModel_ComponentState_t pComponentState);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetComponentState GetComponentState;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _RenderModelHasComponent(string pchRenderModelName, string pchComponentName);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _RenderModelHasComponent RenderModelHasComponent;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetRenderModelThumbnailURL(string pchRenderModelName, System.Text.StringBuilder pchThumbnailURL, uint unThumbnailURLLen, ref EVRRenderModelError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetRenderModelThumbnailURL GetRenderModelThumbnailURL;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetRenderModelOriginalPath(string pchRenderModelName, System.Text.StringBuilder pchOriginalPath, uint unOriginalPathLen, ref EVRRenderModelError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetRenderModelOriginalPath GetRenderModelOriginalPath;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetRenderModelErrorNameFromEnum(EVRRenderModelError error);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetRenderModelErrorNameFromEnum GetRenderModelErrorNameFromEnum;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRNotifications
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRNotificationError _CreateNotification(ulong ulOverlayHandle, ulong ulUserValue, EVRNotificationType type, string pchText, EVRNotificationStyle style, ref NotificationBitmap_t pImage, ref uint pNotificationId);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _CreateNotification CreateNotification;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRNotificationError _RemoveNotification(uint notificationId);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _RemoveNotification RemoveNotification;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRSettings
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate IntPtr _GetSettingsErrorNameFromEnum(EVRSettingsError eError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetSettingsErrorNameFromEnum GetSettingsErrorNameFromEnum;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _Sync(bool bForce, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _Sync Sync;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetBool(string pchSection, string pchSettingsKey, bool bValue, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetBool SetBool;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetInt32(string pchSection, string pchSettingsKey, int nValue, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetInt32 SetInt32;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetFloat(string pchSection, string pchSettingsKey, float flValue, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetFloat SetFloat;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _SetString(string pchSection, string pchSettingsKey, string pchValue, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SetString SetString;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetBool(string pchSection, string pchSettingsKey, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetBool GetBool;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate int _GetInt32(string pchSection, string pchSettingsKey, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetInt32 GetInt32;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate float _GetFloat(string pchSection, string pchSettingsKey, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetFloat GetFloat;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _GetString(string pchSection, string pchSettingsKey, System.Text.StringBuilder pchValue, uint unValueLen, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetString GetString;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _RemoveSection(string pchSection, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _RemoveSection RemoveSection;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate void _RemoveKeyInSection(string pchSection, string pchSettingsKey, ref EVRSettingsError peError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _RemoveKeyInSection RemoveKeyInSection;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRScreenshots
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRScreenshotError _RequestScreenshot(ref uint pOutScreenshotHandle, EVRScreenshotType type, string pchPreviewFilename, string pchVRFilename);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _RequestScreenshot RequestScreenshot;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRScreenshotError _HookScreenshot([In, Out] EVRScreenshotType[] pSupportedTypes, int numTypes);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _HookScreenshot HookScreenshot;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRScreenshotType _GetScreenshotPropertyType(uint screenshotHandle, ref EVRScreenshotError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetScreenshotPropertyType GetScreenshotPropertyType;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetScreenshotPropertyFilename(uint screenshotHandle, EVRScreenshotPropertyFilenames filenameType, System.Text.StringBuilder pchFilename, uint cchFilename, ref EVRScreenshotError pError);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetScreenshotPropertyFilename GetScreenshotPropertyFilename;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRScreenshotError _UpdateScreenshotProgress(uint screenshotHandle, float flProgress);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _UpdateScreenshotProgress UpdateScreenshotProgress;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRScreenshotError _TakeStereoScreenshot(ref uint pOutScreenshotHandle, string pchPreviewFilename, string pchVRFilename);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _TakeStereoScreenshot TakeStereoScreenshot;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate EVRScreenshotError _SubmitScreenshot(uint screenshotHandle, EVRScreenshotType type, string pchSourcePreviewFilename, string pchSourceVRFilename);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _SubmitScreenshot SubmitScreenshot;
+
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct IVRResources
+{
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _LoadSharedResource(string pchResourceName, string pchBuffer, uint unBufferLen);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _LoadSharedResource LoadSharedResource;
+
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate uint _GetResourceFullPath(string pchResourceName, string pchResourceTypeDirectory, string pchPathBuffer, uint unBufferLen);
+	[MarshalAs(UnmanagedType.FunctionPtr)]
+	internal _GetResourceFullPath GetResourceFullPath;
+
+}
+
+
+public class CVRSystem
+{
+	IVRSystem FnTable;
+	internal CVRSystem(IntPtr pInterface)
+	{
+		FnTable = (IVRSystem)Marshal.PtrToStructure(pInterface, typeof(IVRSystem));
+	}
+	public void GetRecommendedRenderTargetSize(ref uint pnWidth,ref uint pnHeight)
+	{
+		pnWidth = 0;
+		pnHeight = 0;
+		FnTable.GetRecommendedRenderTargetSize(ref pnWidth,ref pnHeight);
+	}
+	public HmdMatrix44_t GetProjectionMatrix(EVREye eEye,float fNearZ,float fFarZ)
+	{
+		HmdMatrix44_t result = FnTable.GetProjectionMatrix(eEye,fNearZ,fFarZ);
+		return result;
+	}
+	public void GetProjectionRaw(EVREye eEye,ref float pfLeft,ref float pfRight,ref float pfTop,ref float pfBottom)
+	{
+		pfLeft = 0;
+		pfRight = 0;
+		pfTop = 0;
+		pfBottom = 0;
+		FnTable.GetProjectionRaw(eEye,ref pfLeft,ref pfRight,ref pfTop,ref pfBottom);
+	}
+	public bool ComputeDistortion(EVREye eEye,float fU,float fV,ref DistortionCoordinates_t pDistortionCoordinates)
+	{
+		bool result = FnTable.ComputeDistortion(eEye,fU,fV,ref pDistortionCoordinates);
+		return result;
+	}
+	public HmdMatrix34_t GetEyeToHeadTransform(EVREye eEye)
+	{
+		HmdMatrix34_t result = FnTable.GetEyeToHeadTransform(eEye);
+		return result;
+	}
+	public bool GetTimeSinceLastVsync(ref float pfSecondsSinceLastVsync,ref ulong pulFrameCounter)
+	{
+		pfSecondsSinceLastVsync = 0;
+		pulFrameCounter = 0;
+		bool result = FnTable.GetTimeSinceLastVsync(ref pfSecondsSinceLastVsync,ref pulFrameCounter);
+		return result;
+	}
+	public int GetD3D9AdapterIndex()
+	{
+		int result = FnTable.GetD3D9AdapterIndex();
+		return result;
+	}
+	public void GetDXGIOutputInfo(ref int pnAdapterIndex)
+	{
+		pnAdapterIndex = 0;
+		FnTable.GetDXGIOutputInfo(ref pnAdapterIndex);
+	}
+	public bool IsDisplayOnDesktop()
+	{
+		bool result = FnTable.IsDisplayOnDesktop();
+		return result;
+	}
+	public bool SetDisplayVisibility(bool bIsVisibleOnDesktop)
+	{
+		bool result = FnTable.SetDisplayVisibility(bIsVisibleOnDesktop);
+		return result;
+	}
+	public void GetDeviceToAbsoluteTrackingPose(ETrackingUniverseOrigin eOrigin,float fPredictedSecondsToPhotonsFromNow,TrackedDevicePose_t [] pTrackedDevicePoseArray)
+	{
+		FnTable.GetDeviceToAbsoluteTrackingPose(eOrigin,fPredictedSecondsToPhotonsFromNow,pTrackedDevicePoseArray,(uint) pTrackedDevicePoseArray.Length);
+	}
+	public void ResetSeatedZeroPose()
+	{
+		FnTable.ResetSeatedZeroPose();
+	}
+	public HmdMatrix34_t GetSeatedZeroPoseToStandingAbsoluteTrackingPose()
+	{
+		HmdMatrix34_t result = FnTable.GetSeatedZeroPoseToStandingAbsoluteTrackingPose();
+		return result;
+	}
+	public HmdMatrix34_t GetRawZeroPoseToStandingAbsoluteTrackingPose()
+	{
+		HmdMatrix34_t result = FnTable.GetRawZeroPoseToStandingAbsoluteTrackingPose();
+		return result;
+	}
+	public uint GetSortedTrackedDeviceIndicesOfClass(ETrackedDeviceClass eTrackedDeviceClass,uint [] punTrackedDeviceIndexArray,uint unRelativeToTrackedDeviceIndex)
+	{
+		uint result = FnTable.GetSortedTrackedDeviceIndicesOfClass(eTrackedDeviceClass,punTrackedDeviceIndexArray,(uint) punTrackedDeviceIndexArray.Length,unRelativeToTrackedDeviceIndex);
+		return result;
+	}
+	public EDeviceActivityLevel GetTrackedDeviceActivityLevel(uint unDeviceId)
+	{
+		EDeviceActivityLevel result = FnTable.GetTrackedDeviceActivityLevel(unDeviceId);
+		return result;
+	}
+	public void ApplyTransform(ref TrackedDevicePose_t pOutputPose,ref TrackedDevicePose_t pTrackedDevicePose,ref HmdMatrix34_t pTransform)
+	{
+		FnTable.ApplyTransform(ref pOutputPose,ref pTrackedDevicePose,ref pTransform);
+	}
+	public uint GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole unDeviceType)
+	{
+		uint result = FnTable.GetTrackedDeviceIndexForControllerRole(unDeviceType);
+		return result;
+	}
+	public ETrackedControllerRole GetControllerRoleForTrackedDeviceIndex(uint unDeviceIndex)
+	{
+		ETrackedControllerRole result = FnTable.GetControllerRoleForTrackedDeviceIndex(unDeviceIndex);
+		return result;
+	}
+	public ETrackedDeviceClass GetTrackedDeviceClass(uint unDeviceIndex)
+	{
+		ETrackedDeviceClass result = FnTable.GetTrackedDeviceClass(unDeviceIndex);
+		return result;
+	}
+	public bool IsTrackedDeviceConnected(uint unDeviceIndex)
+	{
+		bool result = FnTable.IsTrackedDeviceConnected(unDeviceIndex);
+		return result;
+	}
+	public bool GetBoolTrackedDeviceProperty(uint unDeviceIndex,ETrackedDeviceProperty prop,ref ETrackedPropertyError pError)
+	{
+		bool result = FnTable.GetBoolTrackedDeviceProperty(unDeviceIndex,prop,ref pError);
+		return result;
+	}
+	public float GetFloatTrackedDeviceProperty(uint unDeviceIndex,ETrackedDeviceProperty prop,ref ETrackedPropertyError pError)
+	{
+		float result = FnTable.GetFloatTrackedDeviceProperty(unDeviceIndex,prop,ref pError);
+		return result;
+	}
+	public int GetInt32TrackedDeviceProperty(uint unDeviceIndex,ETrackedDeviceProperty prop,ref ETrackedPropertyError pError)
+	{
+		int result = FnTable.GetInt32TrackedDeviceProperty(unDeviceIndex,prop,ref pError);
+		return result;
+	}
+	public ulong GetUint64TrackedDeviceProperty(uint unDeviceIndex,ETrackedDeviceProperty prop,ref ETrackedPropertyError pError)
+	{
+		ulong result = FnTable.GetUint64TrackedDeviceProperty(unDeviceIndex,prop,ref pError);
+		return result;
+	}
+	public HmdMatrix34_t GetMatrix34TrackedDeviceProperty(uint unDeviceIndex,ETrackedDeviceProperty prop,ref ETrackedPropertyError pError)
+	{
+		HmdMatrix34_t result = FnTable.GetMatrix34TrackedDeviceProperty(unDeviceIndex,prop,ref pError);
+		return result;
+	}
+	public uint GetStringTrackedDeviceProperty(uint unDeviceIndex,ETrackedDeviceProperty prop,System.Text.StringBuilder pchValue,uint unBufferSize,ref ETrackedPropertyError pError)
+	{
+		uint result = FnTable.GetStringTrackedDeviceProperty(unDeviceIndex,prop,pchValue,unBufferSize,ref pError);
+		return result;
+	}
+	public string GetPropErrorNameFromEnum(ETrackedPropertyError error)
+	{
+		IntPtr result = FnTable.GetPropErrorNameFromEnum(error);
+		return Marshal.PtrToStringAnsi(result);
+	}
+	public bool PollNextEvent(ref VREvent_t pEvent,uint uncbVREvent)
+	{
+		bool result = FnTable.PollNextEvent(ref pEvent,uncbVREvent);
+		return result;
+	}
+	public bool PollNextEventWithPose(ETrackingUniverseOrigin eOrigin,ref VREvent_t pEvent,uint uncbVREvent,ref TrackedDevicePose_t pTrackedDevicePose)
+	{
+		bool result = FnTable.PollNextEventWithPose(eOrigin,ref pEvent,uncbVREvent,ref pTrackedDevicePose);
+		return result;
+	}
+	public string GetEventTypeNameFromEnum(EVREventType eType)
+	{
+		IntPtr result = FnTable.GetEventTypeNameFromEnum(eType);
+		return Marshal.PtrToStringAnsi(result);
+	}
+	public HiddenAreaMesh_t GetHiddenAreaMesh(EVREye eEye,EHiddenAreaMeshType type)
+	{
+		HiddenAreaMesh_t result = FnTable.GetHiddenAreaMesh(eEye,type);
+		return result;
+	}
+// This is a terrible hack to workaround the fact that VRControllerState_t was
+// originally mis-compiled with the wrong packing for Linux and OSX.
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetControllerStatePacked(uint unControllerDeviceIndex,ref VRControllerState_t_Packed pControllerState,uint unControllerStateSize);
+	[StructLayout(LayoutKind.Explicit)]
+	struct GetControllerStateUnion
+	{
+		[FieldOffset(0)]
+		public IVRSystem._GetControllerState pGetControllerState;
+		[FieldOffset(0)]
+		public _GetControllerStatePacked pGetControllerStatePacked;
+	}
+	public bool GetControllerState(uint unControllerDeviceIndex,ref VRControllerState_t pControllerState,uint unControllerStateSize)
+	{
+		if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) ||
+				(System.Environment.OSVersion.Platform == System.PlatformID.Unix))
+		{
+			GetControllerStateUnion u;
+			VRControllerState_t_Packed state_packed = new VRControllerState_t_Packed();
+			u.pGetControllerStatePacked = null;
+			u.pGetControllerState = FnTable.GetControllerState;
+			bool packed_result = u.pGetControllerStatePacked(unControllerDeviceIndex,ref state_packed,(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t_Packed)));
+
+			state_packed.Unpack(ref pControllerState);
+			return packed_result;
+		}
+		bool result = FnTable.GetControllerState(unControllerDeviceIndex,ref pControllerState,unControllerStateSize);
+		return result;
+	}
+// This is a terrible hack to workaround the fact that VRControllerState_t was
+// originally mis-compiled with the wrong packing for Linux and OSX.
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetControllerStateWithPosePacked(ETrackingUniverseOrigin eOrigin,uint unControllerDeviceIndex,ref VRControllerState_t_Packed pControllerState,uint unControllerStateSize,ref TrackedDevicePose_t pTrackedDevicePose);
+	[StructLayout(LayoutKind.Explicit)]
+	struct GetControllerStateWithPoseUnion
+	{
+		[FieldOffset(0)]
+		public IVRSystem._GetControllerStateWithPose pGetControllerStateWithPose;
+		[FieldOffset(0)]
+		public _GetControllerStateWithPosePacked pGetControllerStateWithPosePacked;
+	}
+	public bool GetControllerStateWithPose(ETrackingUniverseOrigin eOrigin,uint unControllerDeviceIndex,ref VRControllerState_t pControllerState,uint unControllerStateSize,ref TrackedDevicePose_t pTrackedDevicePose)
+	{
+		if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) ||
+				(System.Environment.OSVersion.Platform == System.PlatformID.Unix))
+		{
+			GetControllerStateWithPoseUnion u;
+			VRControllerState_t_Packed state_packed = new VRControllerState_t_Packed();
+			u.pGetControllerStateWithPosePacked = null;
+			u.pGetControllerStateWithPose = FnTable.GetControllerStateWithPose;
+			bool packed_result = u.pGetControllerStateWithPosePacked(eOrigin,unControllerDeviceIndex,ref state_packed,(uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t_Packed)),ref pTrackedDevicePose);
+
+			state_packed.Unpack(ref pControllerState);
+			return packed_result;
+		}
+		bool result = FnTable.GetControllerStateWithPose(eOrigin,unControllerDeviceIndex,ref pControllerState,unControllerStateSize,ref pTrackedDevicePose);
+		return result;
+	}
+	public void TriggerHapticPulse(uint unControllerDeviceIndex,uint unAxisId,char usDurationMicroSec)
+	{
+		FnTable.TriggerHapticPulse(unControllerDeviceIndex,unAxisId,usDurationMicroSec);
+	}
+	public string GetButtonIdNameFromEnum(EVRButtonId eButtonId)
+	{
+		IntPtr result = FnTable.GetButtonIdNameFromEnum(eButtonId);
+		return Marshal.PtrToStringAnsi(result);
+	}
+	public string GetControllerAxisTypeNameFromEnum(EVRControllerAxisType eAxisType)
+	{
+		IntPtr result = FnTable.GetControllerAxisTypeNameFromEnum(eAxisType);
+		return Marshal.PtrToStringAnsi(result);
+	}
+	public bool CaptureInputFocus()
+	{
+		bool result = FnTable.CaptureInputFocus();
+		return result;
+	}
+	public void ReleaseInputFocus()
+	{
+		FnTable.ReleaseInputFocus();
+	}
+	public bool IsInputFocusCapturedByAnotherProcess()
+	{
+		bool result = FnTable.IsInputFocusCapturedByAnotherProcess();
+		return result;
+	}
+	public uint DriverDebugRequest(uint unDeviceIndex,string pchRequest,string pchResponseBuffer,uint unResponseBufferSize)
+	{
+		uint result = FnTable.DriverDebugRequest(unDeviceIndex,pchRequest,pchResponseBuffer,unResponseBufferSize);
+		return result;
+	}
+	public EVRFirmwareError PerformFirmwareUpdate(uint unDeviceIndex)
+	{
+		EVRFirmwareError result = FnTable.PerformFirmwareUpdate(unDeviceIndex);
+		return result;
+	}
+	public void AcknowledgeQuit_Exiting()
+	{
+		FnTable.AcknowledgeQuit_Exiting();
+	}
+	public void AcknowledgeQuit_UserPrompt()
+	{
+		FnTable.AcknowledgeQuit_UserPrompt();
+	}
+}
+
+
+public class CVRExtendedDisplay
+{
+	IVRExtendedDisplay FnTable;
+	internal CVRExtendedDisplay(IntPtr pInterface)
+	{
+		FnTable = (IVRExtendedDisplay)Marshal.PtrToStructure(pInterface, typeof(IVRExtendedDisplay));
+	}
+	public void GetWindowBounds(ref int pnX,ref int pnY,ref uint pnWidth,ref uint pnHeight)
+	{
+		pnX = 0;
+		pnY = 0;
+		pnWidth = 0;
+		pnHeight = 0;
+		FnTable.GetWindowBounds(ref pnX,ref pnY,ref pnWidth,ref pnHeight);
+	}
+	public void GetEyeOutputViewport(EVREye eEye,ref uint pnX,ref uint pnY,ref uint pnWidth,ref uint pnHeight)
+	{
+		pnX = 0;
+		pnY = 0;
+		pnWidth = 0;
+		pnHeight = 0;
+		FnTable.GetEyeOutputViewport(eEye,ref pnX,ref pnY,ref pnWidth,ref pnHeight);
+	}
+	public void GetDXGIOutputInfo(ref int pnAdapterIndex,ref int pnAdapterOutputIndex)
+	{
+		pnAdapterIndex = 0;
+		pnAdapterOutputIndex = 0;
+		FnTable.GetDXGIOutputInfo(ref pnAdapterIndex,ref pnAdapterOutputIndex);
+	}
+}
+
+
+public class CVRTrackedCamera
+{
+	IVRTrackedCamera FnTable;
+	internal CVRTrackedCamera(IntPtr pInterface)
+	{
+		FnTable = (IVRTrackedCamera)Marshal.PtrToStructure(pInterface, typeof(IVRTrackedCamera));
+	}
+	public string GetCameraErrorNameFromEnum(EVRTrackedCameraError eCameraError)
+	{
+		IntPtr result = FnTable.GetCameraErrorNameFromEnum(eCameraError);
+		return Marshal.PtrToStringAnsi(result);
+	}
+	public EVRTrackedCameraError HasCamera(uint nDeviceIndex,ref bool pHasCamera)
+	{
+		pHasCamera = false;
+		EVRTrackedCameraError result = FnTable.HasCamera(nDeviceIndex,ref pHasCamera);
+		return result;
+	}
+	public EVRTrackedCameraError GetCameraFrameSize(uint nDeviceIndex,EVRTrackedCameraFrameType eFrameType,ref uint pnWidth,ref uint pnHeight,ref uint pnFrameBufferSize)
+	{
+		pnWidth = 0;
+		pnHeight = 0;
+		pnFrameBufferSize = 0;
+		EVRTrackedCameraError result = FnTable.GetCameraFrameSize(nDeviceIndex,eFrameType,ref pnWidth,ref pnHeight,ref pnFrameBufferSize);
+		return result;
+	}
+	public EVRTrackedCameraError GetCameraIntrinsics(uint nDeviceIndex,EVRTrackedCameraFrameType eFrameType,ref HmdVector2_t pFocalLength,ref HmdVector2_t pCenter)
+	{
+		EVRTrackedCameraError result = FnTable.GetCameraIntrinsics(nDeviceIndex,eFrameType,ref pFocalLength,ref pCenter);
+		return result;
+	}
+	public EVRTrackedCameraError GetCameraProjection(uint nDeviceIndex,EVRTrackedCameraFrameType eFrameType,float flZNear,float flZFar,ref HmdMatrix44_t pProjection)
+	{
+		EVRTrackedCameraError result = FnTable.GetCameraProjection(nDeviceIndex,eFrameType,flZNear,flZFar,ref pProjection);
+		return result;
+	}
+	public EVRTrackedCameraError AcquireVideoStreamingService(uint nDeviceIndex,ref ulong pHandle)
+	{
+		pHandle = 0;
+		EVRTrackedCameraError result = FnTable.AcquireVideoStreamingService(nDeviceIndex,ref pHandle);
+		return result;
+	}
+	public EVRTrackedCameraError ReleaseVideoStreamingService(ulong hTrackedCamera)
+	{
+		EVRTrackedCameraError result = FnTable.ReleaseVideoStreamingService(hTrackedCamera);
+		return result;
+	}
+	public EVRTrackedCameraError GetVideoStreamFrameBuffer(ulong hTrackedCamera,EVRTrackedCameraFrameType eFrameType,IntPtr pFrameBuffer,uint nFrameBufferSize,ref CameraVideoStreamFrameHeader_t pFrameHeader,uint nFrameHeaderSize)
+	{
+		EVRTrackedCameraError result = FnTable.GetVideoStreamFrameBuffer(hTrackedCamera,eFrameType,pFrameBuffer,nFrameBufferSize,ref pFrameHeader,nFrameHeaderSize);
+		return result;
+	}
+	public EVRTrackedCameraError GetVideoStreamTextureSize(uint nDeviceIndex,EVRTrackedCameraFrameType eFrameType,ref VRTextureBounds_t pTextureBounds,ref uint pnWidth,ref uint pnHeight)
+	{
+		pnWidth = 0;
+		pnHeight = 0;
+		EVRTrackedCameraError result = FnTable.GetVideoStreamTextureSize(nDeviceIndex,eFrameType,ref pTextureBounds,ref pnWidth,ref pnHeight);
+		return result;
+	}
+	public EVRTrackedCameraError GetVideoStreamTextureD3D11(ulong hTrackedCamera,EVRTrackedCameraFrameType eFrameType,IntPtr pD3D11DeviceOrResource,ref IntPtr ppD3D11ShaderResourceView,ref CameraVideoStreamFrameHeader_t pFrameHeader,uint nFrameHeaderSize)
+	{
+		EVRTrackedCameraError result = FnTable.GetVideoStreamTextureD3D11(hTrackedCamera,eFrameType,pD3D11DeviceOrResource,ref ppD3D11ShaderResourceView,ref pFrameHeader,nFrameHeaderSize);
+		return result;
+	}
+	public EVRTrackedCameraError GetVideoStreamTextureGL(ulong hTrackedCamera,EVRTrackedCameraFrameType eFrameType,ref uint pglTextureId,ref CameraVideoStreamFrameHeader_t pFrameHeader,uint nFrameHeaderSize)
+	{
+		pglTextureId = 0;
+		EVRTrackedCameraError result = FnTable.GetVideoStreamTextureGL(hTrackedCamera,eFrameType,ref pglTextureId,ref pFrameHeader,nFrameHeaderSize);
+		return result;
+	}
+	public EVRTrackedCameraError ReleaseVideoStreamTextureGL(ulong hTrackedCamera,uint glTextureId)
+	{
+		EVRTrackedCameraError result = FnTable.ReleaseVideoStreamTextureGL(hTrackedCamera,glTextureId);
+		return result;
+	}
+}
+
+
+public class CVRApplications
+{
+	IVRApplications FnTable;
+	internal CVRApplications(IntPtr pInterface)
+	{
+		FnTable = (IVRApplications)Marshal.PtrToStructure(pInterface, typeof(IVRApplications));
+	}
+	public EVRApplicationError AddApplicationManifest(string pchApplicationManifestFullPath,bool bTemporary)
+	{
+		EVRApplicationError result = FnTable.AddApplicationManifest(pchApplicationManifestFullPath,bTemporary);
+		return result;
+	}
+	public EVRApplicationError RemoveApplicationManifest(string pchApplicationManifestFullPath)
+	{
+		EVRApplicationError result = FnTable.RemoveApplicationManifest(pchApplicationManifestFullPath);
+		return result;
+	}
+	public bool IsApplicationInstalled(string pchAppKey)
+	{
+		bool result = FnTable.IsApplicationInstalled(pchAppKey);
+		return result;
+	}
+	public uint GetApplicationCount()
+	{
+		uint result = FnTable.GetApplicationCount();
+		return result;
+	}
+	public EVRApplicationError GetApplicationKeyByIndex(uint unApplicationIndex,System.Text.StringBuilder pchAppKeyBuffer,uint unAppKeyBufferLen)
+	{
+		EVRApplicationError result = FnTable.GetApplicationKeyByIndex(unApplicationIndex,pchAppKeyBuffer,unAppKeyBufferLen);
+		return result;
+	}
+	public EVRApplicationError GetApplicationKeyByProcessId(uint unProcessId,string pchAppKeyBuffer,uint unAppKeyBufferLen)
+	{
+		EVRApplicationError result = FnTable.GetApplicationKeyByProcessId(unProcessId,pchAppKeyBuffer,unAppKeyBufferLen);
+		return result;
+	}
+	public EVRApplicationError LaunchApplication(string pchAppKey)
+	{
+		EVRApplicationError result = FnTable.LaunchApplication(pchAppKey);
+		return result;
+	}
+	public EVRApplicationError LaunchTemplateApplication(string pchTemplateAppKey,string pchNewAppKey,AppOverrideKeys_t [] pKeys)
+	{
+		EVRApplicationError result = FnTable.LaunchTemplateApplication(pchTemplateAppKey,pchNewAppKey,pKeys,(uint) pKeys.Length);
+		return result;
+	}
+	public EVRApplicationError LaunchApplicationFromMimeType(string pchMimeType,string pchArgs)
+	{
+		EVRApplicationError result = FnTable.LaunchApplicationFromMimeType(pchMimeType,pchArgs);
+		return result;
+	}
+	public EVRApplicationError LaunchDashboardOverlay(string pchAppKey)
+	{
+		EVRApplicationError result = FnTable.LaunchDashboardOverlay(pchAppKey);
+		return result;
+	}
+	public bool CancelApplicationLaunch(string pchAppKey)
+	{
+		bool result = FnTable.CancelApplicationLaunch(pchAppKey);
+		return result;
+	}
+	public EVRApplicationError IdentifyApplication(uint unProcessId,string pchAppKey)
+	{
+		EVRApplicationError result = FnTable.IdentifyApplication(unProcessId,pchAppKey);
+		return result;
+	}
+	public uint GetApplicationProcessId(string pchAppKey)
+	{
+		uint result = FnTable.GetApplicationProcessId(pchAppKey);
+		return result;
+	}
+	public string GetApplicationsErrorNameFromEnum(EVRApplicationError error)
+	{
+		IntPtr result = FnTable.GetApplicationsErrorNameFromEnum(error);
+		return Marshal.PtrToStringAnsi(result);
+	}
+	public uint GetApplicationPropertyString(string pchAppKey,EVRApplicationProperty eProperty,System.Text.StringBuilder pchPropertyValueBuffer,uint unPropertyValueBufferLen,ref EVRApplicationError peError)
+	{
+		uint result = FnTable.GetApplicationPropertyString(pchAppKey,eProperty,pchPropertyValueBuffer,unPropertyValueBufferLen,ref peError);
+		return result;
+	}
+	public bool GetApplicationPropertyBool(string pchAppKey,EVRApplicationProperty eProperty,ref EVRApplicationError peError)
+	{
+		bool result = FnTable.GetApplicationPropertyBool(pchAppKey,eProperty,ref peError);
+		return result;
+	}
+	public ulong GetApplicationPropertyUint64(string pchAppKey,EVRApplicationProperty eProperty,ref EVRApplicationError peError)
+	{
+		ulong result = FnTable.GetApplicationPropertyUint64(pchAppKey,eProperty,ref peError);
+		return result;
+	}
+	public EVRApplicationError SetApplicationAutoLaunch(string pchAppKey,bool bAutoLaunch)
+	{
+		EVRApplicationError result = FnTable.SetApplicationAutoLaunch(pchAppKey,bAutoLaunch);
+		return result;
+	}
+	public bool GetApplicationAutoLaunch(string pchAppKey)
+	{
+		bool result = FnTable.GetApplicationAutoLaunch(pchAppKey);
+		return result;
+	}
+	public EVRApplicationError SetDefaultApplicationForMimeType(string pchAppKey,string pchMimeType)
+	{
+		EVRApplicationError result = FnTable.SetDefaultApplicationForMimeType(pchAppKey,pchMimeType);
+		return result;
+	}
+	public bool GetDefaultApplicationForMimeType(string pchMimeType,string pchAppKeyBuffer,uint unAppKeyBufferLen)
+	{
+		bool result = FnTable.GetDefaultApplicationForMimeType(pchMimeType,pchAppKeyBuffer,unAppKeyBufferLen);
+		return result;
+	}
+	public bool GetApplicationSupportedMimeTypes(string pchAppKey,string pchMimeTypesBuffer,uint unMimeTypesBuffer)
+	{
+		bool result = FnTable.GetApplicationSupportedMimeTypes(pchAppKey,pchMimeTypesBuffer,unMimeTypesBuffer);
+		return result;
+	}
+	public uint GetApplicationsThatSupportMimeType(string pchMimeType,string pchAppKeysThatSupportBuffer,uint unAppKeysThatSupportBuffer)
+	{
+		uint result = FnTable.GetApplicationsThatSupportMimeType(pchMimeType,pchAppKeysThatSupportBuffer,unAppKeysThatSupportBuffer);
+		return result;
+	}
+	public uint GetApplicationLaunchArguments(uint unHandle,string pchArgs,uint unArgs)
+	{
+		uint result = FnTable.GetApplicationLaunchArguments(unHandle,pchArgs,unArgs);
+		return result;
+	}
+	public EVRApplicationError GetStartingApplication(string pchAppKeyBuffer,uint unAppKeyBufferLen)
+	{
+		EVRApplicationError result = FnTable.GetStartingApplication(pchAppKeyBuffer,unAppKeyBufferLen);
+		return result;
+	}
+	public EVRApplicationTransitionState GetTransitionState()
+	{
+		EVRApplicationTransitionState result = FnTable.GetTransitionState();
+		return result;
+	}
+	public EVRApplicationError PerformApplicationPrelaunchCheck(string pchAppKey)
+	{
+		EVRApplicationError result = FnTable.PerformApplicationPrelaunchCheck(pchAppKey);
+		return result;
+	}
+	public string GetApplicationsTransitionStateNameFromEnum(EVRApplicationTransitionState state)
+	{
+		IntPtr result = FnTable.GetApplicationsTransitionStateNameFromEnum(state);
+		return Marshal.PtrToStringAnsi(result);
+	}
+	public bool IsQuitUserPromptRequested()
+	{
+		bool result = FnTable.IsQuitUserPromptRequested();
+		return result;
+	}
+	public EVRApplicationError LaunchInternalProcess(string pchBinaryPath,string pchArguments,string pchWorkingDirectory)
+	{
+		EVRApplicationError result = FnTable.LaunchInternalProcess(pchBinaryPath,pchArguments,pchWorkingDirectory);
+		return result;
+	}
+	public uint GetCurrentSceneProcessId()
+	{
+		uint result = FnTable.GetCurrentSceneProcessId();
+		return result;
+	}
+}
+
+
+public class CVRChaperone
+{
+	IVRChaperone FnTable;
+	internal CVRChaperone(IntPtr pInterface)
+	{
+		FnTable = (IVRChaperone)Marshal.PtrToStructure(pInterface, typeof(IVRChaperone));
+	}
+	public ChaperoneCalibrationState GetCalibrationState()
+	{
+		ChaperoneCalibrationState result = FnTable.GetCalibrationState();
+		return result;
+	}
+	public bool GetPlayAreaSize(ref float pSizeX,ref float pSizeZ)
+	{
+		pSizeX = 0;
+		pSizeZ = 0;
+		bool result = FnTable.GetPlayAreaSize(ref pSizeX,ref pSizeZ);
+		return result;
+	}
+	public bool GetPlayAreaRect(ref HmdQuad_t rect)
+	{
+		bool result = FnTable.GetPlayAreaRect(ref rect);
+		return result;
+	}
+	public void ReloadInfo()
+	{
+		FnTable.ReloadInfo();
+	}
+	public void SetSceneColor(HmdColor_t color)
+	{
+		FnTable.SetSceneColor(color);
+	}
+	public void GetBoundsColor(ref HmdColor_t pOutputColorArray,int nNumOutputColors,float flCollisionBoundsFadeDistance,ref HmdColor_t pOutputCameraColor)
+	{
+		FnTable.GetBoundsColor(ref pOutputColorArray,nNumOutputColors,flCollisionBoundsFadeDistance,ref pOutputCameraColor);
+	}
+	public bool AreBoundsVisible()
+	{
+		bool result = FnTable.AreBoundsVisible();
+		return result;
+	}
+	public void ForceBoundsVisible(bool bForce)
+	{
+		FnTable.ForceBoundsVisible(bForce);
+	}
+}
+
+
+public class CVRChaperoneSetup
+{
+	IVRChaperoneSetup FnTable;
+	internal CVRChaperoneSetup(IntPtr pInterface)
+	{
+		FnTable = (IVRChaperoneSetup)Marshal.PtrToStructure(pInterface, typeof(IVRChaperoneSetup));
+	}
+	public bool CommitWorkingCopy(EChaperoneConfigFile configFile)
+	{
+		bool result = FnTable.CommitWorkingCopy(configFile);
+		return result;
+	}
+	public void RevertWorkingCopy()
+	{
+		FnTable.RevertWorkingCopy();
+	}
+	public bool GetWorkingPlayAreaSize(ref float pSizeX,ref float pSizeZ)
+	{
+		pSizeX = 0;
+		pSizeZ = 0;
+		bool result = FnTable.GetWorkingPlayAreaSize(ref pSizeX,ref pSizeZ);
+		return result;
+	}
+	public bool GetWorkingPlayAreaRect(ref HmdQuad_t rect)
+	{
+		bool result = FnTable.GetWorkingPlayAreaRect(ref rect);
+		return result;
+	}
+	public bool GetWorkingCollisionBoundsInfo(out HmdQuad_t [] pQuadsBuffer)
+	{
+		uint punQuadsCount = 0;
+		bool result = FnTable.GetWorkingCollisionBoundsInfo(null,ref punQuadsCount);
+		pQuadsBuffer= new HmdQuad_t[punQuadsCount];
+		result = FnTable.GetWorkingCollisionBoundsInfo(pQuadsBuffer,ref punQuadsCount);
+		return result;
+	}
+	public bool GetLiveCollisionBoundsInfo(out HmdQuad_t [] pQuadsBuffer)
+	{
+		uint punQuadsCount = 0;
+		bool result = FnTable.GetLiveCollisionBoundsInfo(null,ref punQuadsCount);
+		pQuadsBuffer= new HmdQuad_t[punQuadsCount];
+		result = FnTable.GetLiveCollisionBoundsInfo(pQuadsBuffer,ref punQuadsCount);
+		return result;
+	}
+	public bool GetWorkingSeatedZeroPoseToRawTrackingPose(ref HmdMatrix34_t pmatSeatedZeroPoseToRawTrackingPose)
+	{
+		bool result = FnTable.GetWorkingSeatedZeroPoseToRawTrackingPose(ref pmatSeatedZeroPoseToRawTrackingPose);
+		return result;
+	}
+	public bool GetWorkingStandingZeroPoseToRawTrackingPose(ref HmdMatrix34_t pmatStandingZeroPoseToRawTrackingPose)
+	{
+		bool result = FnTable.GetWorkingStandingZeroPoseToRawTrackingPose(ref pmatStandingZeroPoseToRawTrackingPose);
+		return result;
+	}
+	public void SetWorkingPlayAreaSize(float sizeX,float sizeZ)
+	{
+		FnTable.SetWorkingPlayAreaSize(sizeX,sizeZ);
+	}
+	public void SetWorkingCollisionBoundsInfo(HmdQuad_t [] pQuadsBuffer)
+	{
+		FnTable.SetWorkingCollisionBoundsInfo(pQuadsBuffer,(uint) pQuadsBuffer.Length);
+	}
+	public void SetWorkingSeatedZeroPoseToRawTrackingPose(ref HmdMatrix34_t pMatSeatedZeroPoseToRawTrackingPose)
+	{
+		FnTable.SetWorkingSeatedZeroPoseToRawTrackingPose(ref pMatSeatedZeroPoseToRawTrackingPose);
+	}
+	public void SetWorkingStandingZeroPoseToRawTrackingPose(ref HmdMatrix34_t pMatStandingZeroPoseToRawTrackingPose)
+	{
+		FnTable.SetWorkingStandingZeroPoseToRawTrackingPose(ref pMatStandingZeroPoseToRawTrackingPose);
+	}
+	public void ReloadFromDisk(EChaperoneConfigFile configFile)
+	{
+		FnTable.ReloadFromDisk(configFile);
+	}
+	public bool GetLiveSeatedZeroPoseToRawTrackingPose(ref HmdMatrix34_t pmatSeatedZeroPoseToRawTrackingPose)
+	{
+		bool result = FnTable.GetLiveSeatedZeroPoseToRawTrackingPose(ref pmatSeatedZeroPoseToRawTrackingPose);
+		return result;
+	}
+	public void SetWorkingCollisionBoundsTagsInfo(byte [] pTagsBuffer)
+	{
+		FnTable.SetWorkingCollisionBoundsTagsInfo(pTagsBuffer,(uint) pTagsBuffer.Length);
+	}
+	public bool GetLiveCollisionBoundsTagsInfo(out byte [] pTagsBuffer)
+	{
+		uint punTagCount = 0;
+		bool result = FnTable.GetLiveCollisionBoundsTagsInfo(null,ref punTagCount);
+		pTagsBuffer= new byte[punTagCount];
+		result = FnTable.GetLiveCollisionBoundsTagsInfo(pTagsBuffer,ref punTagCount);
+		return result;
+	}
+	public bool SetWorkingPhysicalBoundsInfo(HmdQuad_t [] pQuadsBuffer)
+	{
+		bool result = FnTable.SetWorkingPhysicalBoundsInfo(pQuadsBuffer,(uint) pQuadsBuffer.Length);
+		return result;
+	}
+	public bool GetLivePhysicalBoundsInfo(out HmdQuad_t [] pQuadsBuffer)
+	{
+		uint punQuadsCount = 0;
+		bool result = FnTable.GetLivePhysicalBoundsInfo(null,ref punQuadsCount);
+		pQuadsBuffer= new HmdQuad_t[punQuadsCount];
+		result = FnTable.GetLivePhysicalBoundsInfo(pQuadsBuffer,ref punQuadsCount);
+		return result;
+	}
+	public bool ExportLiveToBuffer(System.Text.StringBuilder pBuffer,ref uint pnBufferLength)
+	{
+		pnBufferLength = 0;
+		bool result = FnTable.ExportLiveToBuffer(pBuffer,ref pnBufferLength);
+		return result;
+	}
+	public bool ImportFromBufferToWorking(string pBuffer,uint nImportFlags)
+	{
+		bool result = FnTable.ImportFromBufferToWorking(pBuffer,nImportFlags);
+		return result;
+	}
+}
+
+
+public class CVRCompositor
+{
+	IVRCompositor FnTable;
+	internal CVRCompositor(IntPtr pInterface)
+	{
+		FnTable = (IVRCompositor)Marshal.PtrToStructure(pInterface, typeof(IVRCompositor));
+	}
+	public void SetTrackingSpace(ETrackingUniverseOrigin eOrigin)
+	{
+		FnTable.SetTrackingSpace(eOrigin);
+	}
+	public ETrackingUniverseOrigin GetTrackingSpace()
+	{
+		ETrackingUniverseOrigin result = FnTable.GetTrackingSpace();
+		return result;
+	}
+	public EVRCompositorError WaitGetPoses(TrackedDevicePose_t [] pRenderPoseArray,TrackedDevicePose_t [] pGamePoseArray)
+	{
+		EVRCompositorError result = FnTable.WaitGetPoses(pRenderPoseArray,(uint) pRenderPoseArray.Length,pGamePoseArray,(uint) pGamePoseArray.Length);
+		return result;
+	}
+	public EVRCompositorError GetLastPoses(TrackedDevicePose_t [] pRenderPoseArray,TrackedDevicePose_t [] pGamePoseArray)
+	{
+		EVRCompositorError result = FnTable.GetLastPoses(pRenderPoseArray,(uint) pRenderPoseArray.Length,pGamePoseArray,(uint) pGamePoseArray.Length);
+		return result;
+	}
+	public EVRCompositorError GetLastPoseForTrackedDeviceIndex(uint unDeviceIndex,ref TrackedDevicePose_t pOutputPose,ref TrackedDevicePose_t pOutputGamePose)
+	{
+		EVRCompositorError result = FnTable.GetLastPoseForTrackedDeviceIndex(unDeviceIndex,ref pOutputPose,ref pOutputGamePose);
+		return result;
+	}
+	public EVRCompositorError Submit(EVREye eEye,ref Texture_t pTexture,ref VRTextureBounds_t pBounds,EVRSubmitFlags nSubmitFlags)
+	{
+		EVRCompositorError result = FnTable.Submit(eEye,ref pTexture,ref pBounds,nSubmitFlags);
+		return result;
+	}
+	public void ClearLastSubmittedFrame()
+	{
+		FnTable.ClearLastSubmittedFrame();
+	}
+	public void PostPresentHandoff()
+	{
+		FnTable.PostPresentHandoff();
+	}
+	public bool GetFrameTiming(ref Compositor_FrameTiming pTiming,uint unFramesAgo)
+	{
+		bool result = FnTable.GetFrameTiming(ref pTiming,unFramesAgo);
+		return result;
+	}
+	public uint GetFrameTimings(ref Compositor_FrameTiming pTiming,uint nFrames)
+	{
+		uint result = FnTable.GetFrameTimings(ref pTiming,nFrames);
+		return result;
+	}
+	public float GetFrameTimeRemaining()
+	{
+		float result = FnTable.GetFrameTimeRemaining();
+		return result;
+	}
+	public void GetCumulativeStats(ref Compositor_CumulativeStats pStats,uint nStatsSizeInBytes)
+	{
+		FnTable.GetCumulativeStats(ref pStats,nStatsSizeInBytes);
+	}
+	public void FadeToColor(float fSeconds,float fRed,float fGreen,float fBlue,float fAlpha,bool bBackground)
+	{
+		FnTable.FadeToColor(fSeconds,fRed,fGreen,fBlue,fAlpha,bBackground);
+	}
+	public HmdColor_t GetCurrentFadeColor(bool bBackground)
+	{
+		HmdColor_t result = FnTable.GetCurrentFadeColor(bBackground);
+		return result;
+	}
+	public void FadeGrid(float fSeconds,bool bFadeIn)
+	{
+		FnTable.FadeGrid(fSeconds,bFadeIn);
+	}
+	public float GetCurrentGridAlpha()
+	{
+		float result = FnTable.GetCurrentGridAlpha();
+		return result;
+	}
+	public EVRCompositorError SetSkyboxOverride(Texture_t [] pTextures)
+	{
+		EVRCompositorError result = FnTable.SetSkyboxOverride(pTextures,(uint) pTextures.Length);
+		return result;
+	}
+	public void ClearSkyboxOverride()
+	{
+		FnTable.ClearSkyboxOverride();
+	}
+	public void CompositorBringToFront()
+	{
+		FnTable.CompositorBringToFront();
+	}
+	public void CompositorGoToBack()
+	{
+		FnTable.CompositorGoToBack();
+	}
+	public void CompositorQuit()
+	{
+		FnTable.CompositorQuit();
+	}
+	public bool IsFullscreen()
+	{
+		bool result = FnTable.IsFullscreen();
+		return result;
+	}
+	public uint GetCurrentSceneFocusProcess()
+	{
+		uint result = FnTable.GetCurrentSceneFocusProcess();
+		return result;
+	}
+	public uint GetLastFrameRenderer()
+	{
+		uint result = FnTable.GetLastFrameRenderer();
+		return result;
+	}
+	public bool CanRenderScene()
+	{
+		bool result = FnTable.CanRenderScene();
+		return result;
+	}
+	public void ShowMirrorWindow()
+	{
+		FnTable.ShowMirrorWindow();
+	}
+	public void HideMirrorWindow()
+	{
+		FnTable.HideMirrorWindow();
+	}
+	public bool IsMirrorWindowVisible()
+	{
+		bool result = FnTable.IsMirrorWindowVisible();
+		return result;
+	}
+	public void CompositorDumpImages()
+	{
+		FnTable.CompositorDumpImages();
+	}
+	public bool ShouldAppRenderWithLowResources()
+	{
+		bool result = FnTable.ShouldAppRenderWithLowResources();
+		return result;
+	}
+	public void ForceInterleavedReprojectionOn(bool bOverride)
+	{
+		FnTable.ForceInterleavedReprojectionOn(bOverride);
+	}
+	public void ForceReconnectProcess()
+	{
+		FnTable.ForceReconnectProcess();
+	}
+	public void SuspendRendering(bool bSuspend)
+	{
+		FnTable.SuspendRendering(bSuspend);
+	}
+	public EVRCompositorError GetMirrorTextureD3D11(EVREye eEye,IntPtr pD3D11DeviceOrResource,ref IntPtr ppD3D11ShaderResourceView)
+	{
+		EVRCompositorError result = FnTable.GetMirrorTextureD3D11(eEye,pD3D11DeviceOrResource,ref ppD3D11ShaderResourceView);
+		return result;
+	}
+	public void ReleaseMirrorTextureD3D11(IntPtr pD3D11ShaderResourceView)
+	{
+		FnTable.ReleaseMirrorTextureD3D11(pD3D11ShaderResourceView);
+	}
+	public EVRCompositorError GetMirrorTextureGL(EVREye eEye,ref uint pglTextureId,IntPtr pglSharedTextureHandle)
+	{
+		pglTextureId = 0;
+		EVRCompositorError result = FnTable.GetMirrorTextureGL(eEye,ref pglTextureId,pglSharedTextureHandle);
+		return result;
+	}
+	public bool ReleaseSharedGLTexture(uint glTextureId,IntPtr glSharedTextureHandle)
+	{
+		bool result = FnTable.ReleaseSharedGLTexture(glTextureId,glSharedTextureHandle);
+		return result;
+	}
+	public void LockGLSharedTextureForAccess(IntPtr glSharedTextureHandle)
+	{
+		FnTable.LockGLSharedTextureForAccess(glSharedTextureHandle);
+	}
+	public void UnlockGLSharedTextureForAccess(IntPtr glSharedTextureHandle)
+	{
+		FnTable.UnlockGLSharedTextureForAccess(glSharedTextureHandle);
+	}
+	public uint GetVulkanInstanceExtensionsRequired(System.Text.StringBuilder pchValue,uint unBufferSize)
+	{
+		uint result = FnTable.GetVulkanInstanceExtensionsRequired(pchValue,unBufferSize);
+		return result;
+	}
+	public uint GetVulkanDeviceExtensionsRequired(IntPtr pPhysicalDevice,System.Text.StringBuilder pchValue,uint unBufferSize)
+	{
+		uint result = FnTable.GetVulkanDeviceExtensionsRequired(pPhysicalDevice,pchValue,unBufferSize);
+		return result;
+	}
+}
+
+
+public class CVROverlay
+{
+	IVROverlay FnTable;
+	internal CVROverlay(IntPtr pInterface)
+	{
+		FnTable = (IVROverlay)Marshal.PtrToStructure(pInterface, typeof(IVROverlay));
+	}
+	public EVROverlayError FindOverlay(string pchOverlayKey,ref ulong pOverlayHandle)
+	{
+		pOverlayHandle = 0;
+		EVROverlayError result = FnTable.FindOverlay(pchOverlayKey,ref pOverlayHandle);
+		return result;
+	}
+	public EVROverlayError CreateOverlay(string pchOverlayKey,string pchOverlayFriendlyName,ref ulong pOverlayHandle)
+	{
+		pOverlayHandle = 0;
+		EVROverlayError result = FnTable.CreateOverlay(pchOverlayKey,pchOverlayFriendlyName,ref pOverlayHandle);
+		return result;
+	}
+	public EVROverlayError DestroyOverlay(ulong ulOverlayHandle)
+	{
+		EVROverlayError result = FnTable.DestroyOverlay(ulOverlayHandle);
+		return result;
+	}
+	public EVROverlayError SetHighQualityOverlay(ulong ulOverlayHandle)
+	{
+		EVROverlayError result = FnTable.SetHighQualityOverlay(ulOverlayHandle);
+		return result;
+	}
+	public ulong GetHighQualityOverlay()
+	{
+		ulong result = FnTable.GetHighQualityOverlay();
+		return result;
+	}
+	public uint GetOverlayKey(ulong ulOverlayHandle,System.Text.StringBuilder pchValue,uint unBufferSize,ref EVROverlayError pError)
+	{
+		uint result = FnTable.GetOverlayKey(ulOverlayHandle,pchValue,unBufferSize,ref pError);
+		return result;
+	}
+	public uint GetOverlayName(ulong ulOverlayHandle,System.Text.StringBuilder pchValue,uint unBufferSize,ref EVROverlayError pError)
+	{
+		uint result = FnTable.GetOverlayName(ulOverlayHandle,pchValue,unBufferSize,ref pError);
+		return result;
+	}
+	public EVROverlayError GetOverlayImageData(ulong ulOverlayHandle,IntPtr pvBuffer,uint unBufferSize,ref uint punWidth,ref uint punHeight)
+	{
+		punWidth = 0;
+		punHeight = 0;
+		EVROverlayError result = FnTable.GetOverlayImageData(ulOverlayHandle,pvBuffer,unBufferSize,ref punWidth,ref punHeight);
+		return result;
+	}
+	public string GetOverlayErrorNameFromEnum(EVROverlayError error)
+	{
+		IntPtr result = FnTable.GetOverlayErrorNameFromEnum(error);
+		return Marshal.PtrToStringAnsi(result);
+	}
+	public EVROverlayError SetOverlayRenderingPid(ulong ulOverlayHandle,uint unPID)
+	{
+		EVROverlayError result = FnTable.SetOverlayRenderingPid(ulOverlayHandle,unPID);
+		return result;
+	}
+	public uint GetOverlayRenderingPid(ulong ulOverlayHandle)
+	{
+		uint result = FnTable.GetOverlayRenderingPid(ulOverlayHandle);
+		return result;
+	}
+	public EVROverlayError SetOverlayFlag(ulong ulOverlayHandle,VROverlayFlags eOverlayFlag,bool bEnabled)
+	{
+		EVROverlayError result = FnTable.SetOverlayFlag(ulOverlayHandle,eOverlayFlag,bEnabled);
+		return result;
+	}
+	public EVROverlayError GetOverlayFlag(ulong ulOverlayHandle,VROverlayFlags eOverlayFlag,ref bool pbEnabled)
+	{
+		pbEnabled = false;
+		EVROverlayError result = FnTable.GetOverlayFlag(ulOverlayHandle,eOverlayFlag,ref pbEnabled);
+		return result;
+	}
+	public EVROverlayError SetOverlayColor(ulong ulOverlayHandle,float fRed,float fGreen,float fBlue)
+	{
+		EVROverlayError result = FnTable.SetOverlayColor(ulOverlayHandle,fRed,fGreen,fBlue);
+		return result;
+	}
+	public EVROverlayError GetOverlayColor(ulong ulOverlayHandle,ref float pfRed,ref float pfGreen,ref float pfBlue)
+	{
+		pfRed = 0;
+		pfGreen = 0;
+		pfBlue = 0;
+		EVROverlayError result = FnTable.GetOverlayColor(ulOverlayHandle,ref pfRed,ref pfGreen,ref pfBlue);
+		return result;
+	}
+	public EVROverlayError SetOverlayAlpha(ulong ulOverlayHandle,float fAlpha)
+	{
+		EVROverlayError result = FnTable.SetOverlayAlpha(ulOverlayHandle,fAlpha);
+		return result;
+	}
+	public EVROverlayError GetOverlayAlpha(ulong ulOverlayHandle,ref float pfAlpha)
+	{
+		pfAlpha = 0;
+		EVROverlayError result = FnTable.GetOverlayAlpha(ulOverlayHandle,ref pfAlpha);
+		return result;
+	}
+	public EVROverlayError SetOverlayTexelAspect(ulong ulOverlayHandle,float fTexelAspect)
+	{
+		EVROverlayError result = FnTable.SetOverlayTexelAspect(ulOverlayHandle,fTexelAspect);
+		return result;
+	}
+	public EVROverlayError GetOverlayTexelAspect(ulong ulOverlayHandle,ref float pfTexelAspect)
+	{
+		pfTexelAspect = 0;
+		EVROverlayError result = FnTable.GetOverlayTexelAspect(ulOverlayHandle,ref pfTexelAspect);
+		return result;
+	}
+	public EVROverlayError SetOverlaySortOrder(ulong ulOverlayHandle,uint unSortOrder)
+	{
+		EVROverlayError result = FnTable.SetOverlaySortOrder(ulOverlayHandle,unSortOrder);
+		return result;
+	}
+	public EVROverlayError GetOverlaySortOrder(ulong ulOverlayHandle,ref uint punSortOrder)
+	{
+		punSortOrder = 0;
+		EVROverlayError result = FnTable.GetOverlaySortOrder(ulOverlayHandle,ref punSortOrder);
+		return result;
+	}
+	public EVROverlayError SetOverlayWidthInMeters(ulong ulOverlayHandle,float fWidthInMeters)
+	{
+		EVROverlayError result = FnTable.SetOverlayWidthInMeters(ulOverlayHandle,fWidthInMeters);
+		return result;
+	}
+	public EVROverlayError GetOverlayWidthInMeters(ulong ulOverlayHandle,ref float pfWidthInMeters)
+	{
+		pfWidthInMeters = 0;
+		EVROverlayError result = FnTable.GetOverlayWidthInMeters(ulOverlayHandle,ref pfWidthInMeters);
+		return result;
+	}
+	public EVROverlayError SetOverlayAutoCurveDistanceRangeInMeters(ulong ulOverlayHandle,float fMinDistanceInMeters,float fMaxDistanceInMeters)
+	{
+		EVROverlayError result = FnTable.SetOverlayAutoCurveDistanceRangeInMeters(ulOverlayHandle,fMinDistanceInMeters,fMaxDistanceInMeters);
+		return result;
+	}
+	public EVROverlayError GetOverlayAutoCurveDistanceRangeInMeters(ulong ulOverlayHandle,ref float pfMinDistanceInMeters,ref float pfMaxDistanceInMeters)
+	{
+		pfMinDistanceInMeters = 0;
+		pfMaxDistanceInMeters = 0;
+		EVROverlayError result = FnTable.GetOverlayAutoCurveDistanceRangeInMeters(ulOverlayHandle,ref pfMinDistanceInMeters,ref pfMaxDistanceInMeters);
+		return result;
+	}
+	public EVROverlayError SetOverlayTextureColorSpace(ulong ulOverlayHandle,EColorSpace eTextureColorSpace)
+	{
+		EVROverlayError result = FnTable.SetOverlayTextureColorSpace(ulOverlayHandle,eTextureColorSpace);
+		return result;
+	}
+	public EVROverlayError GetOverlayTextureColorSpace(ulong ulOverlayHandle,ref EColorSpace peTextureColorSpace)
+	{
+		EVROverlayError result = FnTable.GetOverlayTextureColorSpace(ulOverlayHandle,ref peTextureColorSpace);
+		return result;
+	}
+	public EVROverlayError SetOverlayTextureBounds(ulong ulOverlayHandle,ref VRTextureBounds_t pOverlayTextureBounds)
+	{
+		EVROverlayError result = FnTable.SetOverlayTextureBounds(ulOverlayHandle,ref pOverlayTextureBounds);
+		return result;
+	}
+	public EVROverlayError GetOverlayTextureBounds(ulong ulOverlayHandle,ref VRTextureBounds_t pOverlayTextureBounds)
+	{
+		EVROverlayError result = FnTable.GetOverlayTextureBounds(ulOverlayHandle,ref pOverlayTextureBounds);
+		return result;
+	}
+	public EVROverlayError GetOverlayTransformType(ulong ulOverlayHandle,ref VROverlayTransformType peTransformType)
+	{
+		EVROverlayError result = FnTable.GetOverlayTransformType(ulOverlayHandle,ref peTransformType);
+		return result;
+	}
+	public EVROverlayError SetOverlayTransformAbsolute(ulong ulOverlayHandle,ETrackingUniverseOrigin eTrackingOrigin,ref HmdMatrix34_t pmatTrackingOriginToOverlayTransform)
+	{
+		EVROverlayError result = FnTable.SetOverlayTransformAbsolute(ulOverlayHandle,eTrackingOrigin,ref pmatTrackingOriginToOverlayTransform);
+		return result;
+	}
+	public EVROverlayError GetOverlayTransformAbsolute(ulong ulOverlayHandle,ref ETrackingUniverseOrigin peTrackingOrigin,ref HmdMatrix34_t pmatTrackingOriginToOverlayTransform)
+	{
+		EVROverlayError result = FnTable.GetOverlayTransformAbsolute(ulOverlayHandle,ref peTrackingOrigin,ref pmatTrackingOriginToOverlayTransform);
+		return result;
+	}
+	public EVROverlayError SetOverlayTransformTrackedDeviceRelative(ulong ulOverlayHandle,uint unTrackedDevice,ref HmdMatrix34_t pmatTrackedDeviceToOverlayTransform)
+	{
+		EVROverlayError result = FnTable.SetOverlayTransformTrackedDeviceRelative(ulOverlayHandle,unTrackedDevice,ref pmatTrackedDeviceToOverlayTransform);
+		return result;
+	}
+	public EVROverlayError GetOverlayTransformTrackedDeviceRelative(ulong ulOverlayHandle,ref uint punTrackedDevice,ref HmdMatrix34_t pmatTrackedDeviceToOverlayTransform)
+	{
+		punTrackedDevice = 0;
+		EVROverlayError result = FnTable.GetOverlayTransformTrackedDeviceRelative(ulOverlayHandle,ref punTrackedDevice,ref pmatTrackedDeviceToOverlayTransform);
+		return result;
+	}
+	public EVROverlayError SetOverlayTransformTrackedDeviceComponent(ulong ulOverlayHandle,uint unDeviceIndex,string pchComponentName)
+	{
+		EVROverlayError result = FnTable.SetOverlayTransformTrackedDeviceComponent(ulOverlayHandle,unDeviceIndex,pchComponentName);
+		return result;
+	}
+	public EVROverlayError GetOverlayTransformTrackedDeviceComponent(ulong ulOverlayHandle,ref uint punDeviceIndex,string pchComponentName,uint unComponentNameSize)
+	{
+		punDeviceIndex = 0;
+		EVROverlayError result = FnTable.GetOverlayTransformTrackedDeviceComponent(ulOverlayHandle,ref punDeviceIndex,pchComponentName,unComponentNameSize);
+		return result;
+	}
+	public EVROverlayError ShowOverlay(ulong ulOverlayHandle)
+	{
+		EVROverlayError result = FnTable.ShowOverlay(ulOverlayHandle);
+		return result;
+	}
+	public EVROverlayError HideOverlay(ulong ulOverlayHandle)
+	{
+		EVROverlayError result = FnTable.HideOverlay(ulOverlayHandle);
+		return result;
+	}
+	public bool IsOverlayVisible(ulong ulOverlayHandle)
+	{
+		bool result = FnTable.IsOverlayVisible(ulOverlayHandle);
+		return result;
+	}
+	public EVROverlayError GetTransformForOverlayCoordinates(ulong ulOverlayHandle,ETrackingUniverseOrigin eTrackingOrigin,HmdVector2_t coordinatesInOverlay,ref HmdMatrix34_t pmatTransform)
+	{
+		EVROverlayError result = FnTable.GetTransformForOverlayCoordinates(ulOverlayHandle,eTrackingOrigin,coordinatesInOverlay,ref pmatTransform);
+		return result;
+	}
+	public bool PollNextOverlayEvent(ulong ulOverlayHandle,ref VREvent_t pEvent,uint uncbVREvent)
+	{
+		bool result = FnTable.PollNextOverlayEvent(ulOverlayHandle,ref pEvent,uncbVREvent);
+		return result;
+	}
+	public EVROverlayError GetOverlayInputMethod(ulong ulOverlayHandle,ref VROverlayInputMethod peInputMethod)
+	{
+		EVROverlayError result = FnTable.GetOverlayInputMethod(ulOverlayHandle,ref peInputMethod);
+		return result;
+	}
+	public EVROverlayError SetOverlayInputMethod(ulong ulOverlayHandle,VROverlayInputMethod eInputMethod)
+	{
+		EVROverlayError result = FnTable.SetOverlayInputMethod(ulOverlayHandle,eInputMethod);
+		return result;
+	}
+	public EVROverlayError GetOverlayMouseScale(ulong ulOverlayHandle,ref HmdVector2_t pvecMouseScale)
+	{
+		EVROverlayError result = FnTable.GetOverlayMouseScale(ulOverlayHandle,ref pvecMouseScale);
+		return result;
+	}
+	public EVROverlayError SetOverlayMouseScale(ulong ulOverlayHandle,ref HmdVector2_t pvecMouseScale)
+	{
+		EVROverlayError result = FnTable.SetOverlayMouseScale(ulOverlayHandle,ref pvecMouseScale);
+		return result;
+	}
+	public bool ComputeOverlayIntersection(ulong ulOverlayHandle,ref VROverlayIntersectionParams_t pParams,ref VROverlayIntersectionResults_t pResults)
+	{
+		bool result = FnTable.ComputeOverlayIntersection(ulOverlayHandle,ref pParams,ref pResults);
+		return result;
+	}
+	public bool HandleControllerOverlayInteractionAsMouse(ulong ulOverlayHandle,uint unControllerDeviceIndex)
+	{
+		bool result = FnTable.HandleControllerOverlayInteractionAsMouse(ulOverlayHandle,unControllerDeviceIndex);
+		return result;
+	}
+	public bool IsHoverTargetOverlay(ulong ulOverlayHandle)
+	{
+		bool result = FnTable.IsHoverTargetOverlay(ulOverlayHandle);
+		return result;
+	}
+	public ulong GetGamepadFocusOverlay()
+	{
+		ulong result = FnTable.GetGamepadFocusOverlay();
+		return result;
+	}
+	public EVROverlayError SetGamepadFocusOverlay(ulong ulNewFocusOverlay)
+	{
+		EVROverlayError result = FnTable.SetGamepadFocusOverlay(ulNewFocusOverlay);
+		return result;
+	}
+	public EVROverlayError SetOverlayNeighbor(EOverlayDirection eDirection,ulong ulFrom,ulong ulTo)
+	{
+		EVROverlayError result = FnTable.SetOverlayNeighbor(eDirection,ulFrom,ulTo);
+		return result;
+	}
+	public EVROverlayError MoveGamepadFocusToNeighbor(EOverlayDirection eDirection,ulong ulFrom)
+	{
+		EVROverlayError result = FnTable.MoveGamepadFocusToNeighbor(eDirection,ulFrom);
+		return result;
+	}
+	public EVROverlayError SetOverlayTexture(ulong ulOverlayHandle,ref Texture_t pTexture)
+	{
+		EVROverlayError result = FnTable.SetOverlayTexture(ulOverlayHandle,ref pTexture);
+		return result;
+	}
+	public EVROverlayError ClearOverlayTexture(ulong ulOverlayHandle)
+	{
+		EVROverlayError result = FnTable.ClearOverlayTexture(ulOverlayHandle);
+		return result;
+	}
+	public EVROverlayError SetOverlayRaw(ulong ulOverlayHandle,IntPtr pvBuffer,uint unWidth,uint unHeight,uint unDepth)
+	{
+		EVROverlayError result = FnTable.SetOverlayRaw(ulOverlayHandle,pvBuffer,unWidth,unHeight,unDepth);
+		return result;
+	}
+	public EVROverlayError SetOverlayFromFile(ulong ulOverlayHandle,string pchFilePath)
+	{
+		EVROverlayError result = FnTable.SetOverlayFromFile(ulOverlayHandle,pchFilePath);
+		return result;
+	}
+	public EVROverlayError GetOverlayTexture(ulong ulOverlayHandle,ref IntPtr pNativeTextureHandle,IntPtr pNativeTextureRef,ref uint pWidth,ref uint pHeight,ref uint pNativeFormat,ref ETextureType pAPIType,ref EColorSpace pColorSpace,ref VRTextureBounds_t pTextureBounds)
+	{
+		pWidth = 0;
+		pHeight = 0;
+		pNativeFormat = 0;
+		EVROverlayError result = FnTable.GetOverlayTexture(ulOverlayHandle,ref pNativeTextureHandle,pNativeTextureRef,ref pWidth,ref pHeight,ref pNativeFormat,ref pAPIType,ref pColorSpace,ref pTextureBounds);
+		return result;
+	}
+	public EVROverlayError ReleaseNativeOverlayHandle(ulong ulOverlayHandle,IntPtr pNativeTextureHandle)
+	{
+		EVROverlayError result = FnTable.ReleaseNativeOverlayHandle(ulOverlayHandle,pNativeTextureHandle);
+		return result;
+	}
+	public EVROverlayError GetOverlayTextureSize(ulong ulOverlayHandle,ref uint pWidth,ref uint pHeight)
+	{
+		pWidth = 0;
+		pHeight = 0;
+		EVROverlayError result = FnTable.GetOverlayTextureSize(ulOverlayHandle,ref pWidth,ref pHeight);
+		return result;
+	}
+	public EVROverlayError CreateDashboardOverlay(string pchOverlayKey,string pchOverlayFriendlyName,ref ulong pMainHandle,ref ulong pThumbnailHandle)
+	{
+		pMainHandle = 0;
+		pThumbnailHandle = 0;
+		EVROverlayError result = FnTable.CreateDashboardOverlay(pchOverlayKey,pchOverlayFriendlyName,ref pMainHandle,ref pThumbnailHandle);
+		return result;
+	}
+	public bool IsDashboardVisible()
+	{
+		bool result = FnTable.IsDashboardVisible();
+		return result;
+	}
+	public bool IsActiveDashboardOverlay(ulong ulOverlayHandle)
+	{
+		bool result = FnTable.IsActiveDashboardOverlay(ulOverlayHandle);
+		return result;
+	}
+	public EVROverlayError SetDashboardOverlaySceneProcess(ulong ulOverlayHandle,uint unProcessId)
+	{
+		EVROverlayError result = FnTable.SetDashboardOverlaySceneProcess(ulOverlayHandle,unProcessId);
+		return result;
+	}
+	public EVROverlayError GetDashboardOverlaySceneProcess(ulong ulOverlayHandle,ref uint punProcessId)
+	{
+		punProcessId = 0;
+		EVROverlayError result = FnTable.GetDashboardOverlaySceneProcess(ulOverlayHandle,ref punProcessId);
+		return result;
+	}
+	public void ShowDashboard(string pchOverlayToShow)
+	{
+		FnTable.ShowDashboard(pchOverlayToShow);
+	}
+	public uint GetPrimaryDashboardDevice()
+	{
+		uint result = FnTable.GetPrimaryDashboardDevice();
+		return result;
+	}
+	public EVROverlayError ShowKeyboard(int eInputMode,int eLineInputMode,string pchDescription,uint unCharMax,string pchExistingText,bool bUseMinimalMode,ulong uUserValue)
+	{
+		EVROverlayError result = FnTable.ShowKeyboard(eInputMode,eLineInputMode,pchDescription,unCharMax,pchExistingText,bUseMinimalMode,uUserValue);
+		return result;
+	}
+	public EVROverlayError ShowKeyboardForOverlay(ulong ulOverlayHandle,int eInputMode,int eLineInputMode,string pchDescription,uint unCharMax,string pchExistingText,bool bUseMinimalMode,ulong uUserValue)
+	{
+		EVROverlayError result = FnTable.ShowKeyboardForOverlay(ulOverlayHandle,eInputMode,eLineInputMode,pchDescription,unCharMax,pchExistingText,bUseMinimalMode,uUserValue);
+		return result;
+	}
+	public uint GetKeyboardText(System.Text.StringBuilder pchText,uint cchText)
+	{
+		uint result = FnTable.GetKeyboardText(pchText,cchText);
+		return result;
+	}
+	public void HideKeyboard()
+	{
+		FnTable.HideKeyboard();
+	}
+	public void SetKeyboardTransformAbsolute(ETrackingUniverseOrigin eTrackingOrigin,ref HmdMatrix34_t pmatTrackingOriginToKeyboardTransform)
+	{
+		FnTable.SetKeyboardTransformAbsolute(eTrackingOrigin,ref pmatTrackingOriginToKeyboardTransform);
+	}
+	public void SetKeyboardPositionForOverlay(ulong ulOverlayHandle,HmdRect2_t avoidRect)
+	{
+		FnTable.SetKeyboardPositionForOverlay(ulOverlayHandle,avoidRect);
+	}
+	public EVROverlayError SetOverlayIntersectionMask(ulong ulOverlayHandle,ref VROverlayIntersectionMaskPrimitive_t pMaskPrimitives,uint unNumMaskPrimitives,uint unPrimitiveSize)
+	{
+		EVROverlayError result = FnTable.SetOverlayIntersectionMask(ulOverlayHandle,ref pMaskPrimitives,unNumMaskPrimitives,unPrimitiveSize);
+		return result;
+	}
+	public EVROverlayError GetOverlayFlags(ulong ulOverlayHandle,ref uint pFlags)
+	{
+		pFlags = 0;
+		EVROverlayError result = FnTable.GetOverlayFlags(ulOverlayHandle,ref pFlags);
+		return result;
+	}
+	public VRMessageOverlayResponse ShowMessageOverlay(string pchText,string pchCaption,string pchButton0Text,string pchButton1Text,string pchButton2Text,string pchButton3Text)
+	{
+		VRMessageOverlayResponse result = FnTable.ShowMessageOverlay(pchText,pchCaption,pchButton0Text,pchButton1Text,pchButton2Text,pchButton3Text);
+		return result;
+	}
+}
+
+
+public class CVRRenderModels
+{
+	IVRRenderModels FnTable;
+	internal CVRRenderModels(IntPtr pInterface)
+	{
+		FnTable = (IVRRenderModels)Marshal.PtrToStructure(pInterface, typeof(IVRRenderModels));
+	}
+	public EVRRenderModelError LoadRenderModel_Async(string pchRenderModelName,ref IntPtr ppRenderModel)
+	{
+		EVRRenderModelError result = FnTable.LoadRenderModel_Async(pchRenderModelName,ref ppRenderModel);
+		return result;
+	}
+	public void FreeRenderModel(IntPtr pRenderModel)
+	{
+		FnTable.FreeRenderModel(pRenderModel);
+	}
+	public EVRRenderModelError LoadTexture_Async(int textureId,ref IntPtr ppTexture)
+	{
+		EVRRenderModelError result = FnTable.LoadTexture_Async(textureId,ref ppTexture);
+		return result;
+	}
+	public void FreeTexture(IntPtr pTexture)
+	{
+		FnTable.FreeTexture(pTexture);
+	}
+	public EVRRenderModelError LoadTextureD3D11_Async(int textureId,IntPtr pD3D11Device,ref IntPtr ppD3D11Texture2D)
+	{
+		EVRRenderModelError result = FnTable.LoadTextureD3D11_Async(textureId,pD3D11Device,ref ppD3D11Texture2D);
+		return result;
+	}
+	public EVRRenderModelError LoadIntoTextureD3D11_Async(int textureId,IntPtr pDstTexture)
+	{
+		EVRRenderModelError result = FnTable.LoadIntoTextureD3D11_Async(textureId,pDstTexture);
+		return result;
+	}
+	public void FreeTextureD3D11(IntPtr pD3D11Texture2D)
+	{
+		FnTable.FreeTextureD3D11(pD3D11Texture2D);
+	}
+	public uint GetRenderModelName(uint unRenderModelIndex,System.Text.StringBuilder pchRenderModelName,uint unRenderModelNameLen)
+	{
+		uint result = FnTable.GetRenderModelName(unRenderModelIndex,pchRenderModelName,unRenderModelNameLen);
+		return result;
+	}
+	public uint GetRenderModelCount()
+	{
+		uint result = FnTable.GetRenderModelCount();
+		return result;
+	}
+	public uint GetComponentCount(string pchRenderModelName)
+	{
+		uint result = FnTable.GetComponentCount(pchRenderModelName);
+		return result;
+	}
+	public uint GetComponentName(string pchRenderModelName,uint unComponentIndex,System.Text.StringBuilder pchComponentName,uint unComponentNameLen)
+	{
+		uint result = FnTable.GetComponentName(pchRenderModelName,unComponentIndex,pchComponentName,unComponentNameLen);
+		return result;
+	}
+	public ulong GetComponentButtonMask(string pchRenderModelName,string pchComponentName)
+	{
+		ulong result = FnTable.GetComponentButtonMask(pchRenderModelName,pchComponentName);
+		return result;
+	}
+	public uint GetComponentRenderModelName(string pchRenderModelName,string pchComponentName,System.Text.StringBuilder pchComponentRenderModelName,uint unComponentRenderModelNameLen)
+	{
+		uint result = FnTable.GetComponentRenderModelName(pchRenderModelName,pchComponentName,pchComponentRenderModelName,unComponentRenderModelNameLen);
+		return result;
+	}
+// This is a terrible hack to workaround the fact that VRControllerState_t was
+// originally mis-compiled with the wrong packing for Linux and OSX.
+	[UnmanagedFunctionPointer(CallingConvention.StdCall)]
+	internal delegate bool _GetComponentStatePacked(string pchRenderModelName,string pchComponentName,ref VRControllerState_t_Packed pControllerState,ref RenderModel_ControllerMode_State_t pState,ref RenderModel_ComponentState_t pComponentState);
+	[StructLayout(LayoutKind.Explicit)]
+	struct GetComponentStateUnion
+	{
+		[FieldOffset(0)]
+		public IVRRenderModels._GetComponentState pGetComponentState;
+		[FieldOffset(0)]
+		public _GetComponentStatePacked pGetComponentStatePacked;
+	}
+	public bool GetComponentState(string pchRenderModelName,string pchComponentName,ref VRControllerState_t pControllerState,ref RenderModel_ControllerMode_State_t pState,ref RenderModel_ComponentState_t pComponentState)
+	{
+		if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) ||
+				(System.Environment.OSVersion.Platform == System.PlatformID.Unix))
+		{
+			GetComponentStateUnion u;
+			VRControllerState_t_Packed state_packed = new VRControllerState_t_Packed();
+			u.pGetComponentStatePacked = null;
+			u.pGetComponentState = FnTable.GetComponentState;
+			bool packed_result = u.pGetComponentStatePacked(pchRenderModelName,pchComponentName,ref state_packed,ref pState,ref pComponentState);
+
+			state_packed.Unpack(ref pControllerState);
+			return packed_result;
+		}
+		bool result = FnTable.GetComponentState(pchRenderModelName,pchComponentName,ref pControllerState,ref pState,ref pComponentState);
+		return result;
+	}
+	public bool RenderModelHasComponent(string pchRenderModelName,string pchComponentName)
+	{
+		bool result = FnTable.RenderModelHasComponent(pchRenderModelName,pchComponentName);
+		return result;
+	}
+	public uint GetRenderModelThumbnailURL(string pchRenderModelName,System.Text.StringBuilder pchThumbnailURL,uint unThumbnailURLLen,ref EVRRenderModelError peError)
+	{
+		uint result = FnTable.GetRenderModelThumbnailURL(pchRenderModelName,pchThumbnailURL,unThumbnailURLLen,ref peError);
+		return result;
+	}
+	public uint GetRenderModelOriginalPath(string pchRenderModelName,System.Text.StringBuilder pchOriginalPath,uint unOriginalPathLen,ref EVRRenderModelError peError)
+	{
+		uint result = FnTable.GetRenderModelOriginalPath(pchRenderModelName,pchOriginalPath,unOriginalPathLen,ref peError);
+		return result;
+	}
+	public string GetRenderModelErrorNameFromEnum(EVRRenderModelError error)
+	{
+		IntPtr result = FnTable.GetRenderModelErrorNameFromEnum(error);
+		return Marshal.PtrToStringAnsi(result);
+	}
+}
+
+
+public class CVRNotifications
+{
+	IVRNotifications FnTable;
+	internal CVRNotifications(IntPtr pInterface)
+	{
+		FnTable = (IVRNotifications)Marshal.PtrToStructure(pInterface, typeof(IVRNotifications));
+	}
+	public EVRNotificationError CreateNotification(ulong ulOverlayHandle,ulong ulUserValue,EVRNotificationType type,string pchText,EVRNotificationStyle style,ref NotificationBitmap_t pImage,ref uint pNotificationId)
+	{
+		pNotificationId = 0;
+		EVRNotificationError result = FnTable.CreateNotification(ulOverlayHandle,ulUserValue,type,pchText,style,ref pImage,ref pNotificationId);
+		return result;
+	}
+	public EVRNotificationError RemoveNotification(uint notificationId)
+	{
+		EVRNotificationError result = FnTable.RemoveNotification(notificationId);
+		return result;
+	}
+}
+
+
+public class CVRSettings
+{
+	IVRSettings FnTable;
+	internal CVRSettings(IntPtr pInterface)
+	{
+		FnTable = (IVRSettings)Marshal.PtrToStructure(pInterface, typeof(IVRSettings));
+	}
+	public string GetSettingsErrorNameFromEnum(EVRSettingsError eError)
+	{
+		IntPtr result = FnTable.GetSettingsErrorNameFromEnum(eError);
+		return Marshal.PtrToStringAnsi(result);
+	}
+	public bool Sync(bool bForce,ref EVRSettingsError peError)
+	{
+		bool result = FnTable.Sync(bForce,ref peError);
+		return result;
+	}
+	public void SetBool(string pchSection,string pchSettingsKey,bool bValue,ref EVRSettingsError peError)
+	{
+		FnTable.SetBool(pchSection,pchSettingsKey,bValue,ref peError);
+	}
+	public void SetInt32(string pchSection,string pchSettingsKey,int nValue,ref EVRSettingsError peError)
+	{
+		FnTable.SetInt32(pchSection,pchSettingsKey,nValue,ref peError);
+	}
+	public void SetFloat(string pchSection,string pchSettingsKey,float flValue,ref EVRSettingsError peError)
+	{
+		FnTable.SetFloat(pchSection,pchSettingsKey,flValue,ref peError);
+	}
+	public void SetString(string pchSection,string pchSettingsKey,string pchValue,ref EVRSettingsError peError)
+	{
+		FnTable.SetString(pchSection,pchSettingsKey,pchValue,ref peError);
+	}
+	public bool GetBool(string pchSection,string pchSettingsKey,ref EVRSettingsError peError)
+	{
+		bool result = FnTable.GetBool(pchSection,pchSettingsKey,ref peError);
+		return result;
+	}
+	public int GetInt32(string pchSection,string pchSettingsKey,ref EVRSettingsError peError)
+	{
+		int result = FnTable.GetInt32(pchSection,pchSettingsKey,ref peError);
+		return result;
+	}
+	public float GetFloat(string pchSection,string pchSettingsKey,ref EVRSettingsError peError)
+	{
+		float result = FnTable.GetFloat(pchSection,pchSettingsKey,ref peError);
+		return result;
+	}
+	public void GetString(string pchSection,string pchSettingsKey,System.Text.StringBuilder pchValue,uint unValueLen,ref EVRSettingsError peError)
+	{
+		FnTable.GetString(pchSection,pchSettingsKey,pchValue,unValueLen,ref peError);
+	}
+	public void RemoveSection(string pchSection,ref EVRSettingsError peError)
+	{
+		FnTable.RemoveSection(pchSection,ref peError);
+	}
+	public void RemoveKeyInSection(string pchSection,string pchSettingsKey,ref EVRSettingsError peError)
+	{
+		FnTable.RemoveKeyInSection(pchSection,pchSettingsKey,ref peError);
+	}
+}
+
+
+public class CVRScreenshots
+{
+	IVRScreenshots FnTable;
+	internal CVRScreenshots(IntPtr pInterface)
+	{
+		FnTable = (IVRScreenshots)Marshal.PtrToStructure(pInterface, typeof(IVRScreenshots));
+	}
+	public EVRScreenshotError RequestScreenshot(ref uint pOutScreenshotHandle,EVRScreenshotType type,string pchPreviewFilename,string pchVRFilename)
+	{
+		pOutScreenshotHandle = 0;
+		EVRScreenshotError result = FnTable.RequestScreenshot(ref pOutScreenshotHandle,type,pchPreviewFilename,pchVRFilename);
+		return result;
+	}
+	public EVRScreenshotError HookScreenshot(EVRScreenshotType [] pSupportedTypes)
+	{
+		EVRScreenshotError result = FnTable.HookScreenshot(pSupportedTypes,(int) pSupportedTypes.Length);
+		return result;
+	}
+	public EVRScreenshotType GetScreenshotPropertyType(uint screenshotHandle,ref EVRScreenshotError pError)
+	{
+		EVRScreenshotType result = FnTable.GetScreenshotPropertyType(screenshotHandle,ref pError);
+		return result;
+	}
+	public uint GetScreenshotPropertyFilename(uint screenshotHandle,EVRScreenshotPropertyFilenames filenameType,System.Text.StringBuilder pchFilename,uint cchFilename,ref EVRScreenshotError pError)
+	{
+		uint result = FnTable.GetScreenshotPropertyFilename(screenshotHandle,filenameType,pchFilename,cchFilename,ref pError);
+		return result;
+	}
+	public EVRScreenshotError UpdateScreenshotProgress(uint screenshotHandle,float flProgress)
+	{
+		EVRScreenshotError result = FnTable.UpdateScreenshotProgress(screenshotHandle,flProgress);
+		return result;
+	}
+	public EVRScreenshotError TakeStereoScreenshot(ref uint pOutScreenshotHandle,string pchPreviewFilename,string pchVRFilename)
+	{
+		pOutScreenshotHandle = 0;
+		EVRScreenshotError result = FnTable.TakeStereoScreenshot(ref pOutScreenshotHandle,pchPreviewFilename,pchVRFilename);
+		return result;
+	}
+	public EVRScreenshotError SubmitScreenshot(uint screenshotHandle,EVRScreenshotType type,string pchSourcePreviewFilename,string pchSourceVRFilename)
+	{
+		EVRScreenshotError result = FnTable.SubmitScreenshot(screenshotHandle,type,pchSourcePreviewFilename,pchSourceVRFilename);
+		return result;
+	}
+}
+
+
+public class CVRResources
+{
+	IVRResources FnTable;
+	internal CVRResources(IntPtr pInterface)
+	{
+		FnTable = (IVRResources)Marshal.PtrToStructure(pInterface, typeof(IVRResources));
+	}
+	public uint LoadSharedResource(string pchResourceName,string pchBuffer,uint unBufferLen)
+	{
+		uint result = FnTable.LoadSharedResource(pchResourceName,pchBuffer,unBufferLen);
+		return result;
+	}
+	public uint GetResourceFullPath(string pchResourceName,string pchResourceTypeDirectory,string pchPathBuffer,uint unBufferLen)
+	{
+		uint result = FnTable.GetResourceFullPath(pchResourceName,pchResourceTypeDirectory,pchPathBuffer,unBufferLen);
+		return result;
+	}
+}
+
+
+public class OpenVRInterop
+{
+	[DllImportAttribute("openvr_api", EntryPoint = "VR_InitInternal", CallingConvention = CallingConvention.Cdecl)]
+	internal static extern uint InitInternal(ref EVRInitError peError, EVRApplicationType eApplicationType);
+	[DllImportAttribute("openvr_api", EntryPoint = "VR_ShutdownInternal", CallingConvention = CallingConvention.Cdecl)]
+	internal static extern void ShutdownInternal();
+	[DllImportAttribute("openvr_api", EntryPoint = "VR_IsHmdPresent", CallingConvention = CallingConvention.Cdecl)]
+	internal static extern bool IsHmdPresent();
+	[DllImportAttribute("openvr_api", EntryPoint = "VR_IsRuntimeInstalled", CallingConvention = CallingConvention.Cdecl)]
+	internal static extern bool IsRuntimeInstalled();
+	[DllImportAttribute("openvr_api", EntryPoint = "VR_GetStringForHmdError", CallingConvention = CallingConvention.Cdecl)]
+	internal static extern IntPtr GetStringForHmdError(EVRInitError error);
+	[DllImportAttribute("openvr_api", EntryPoint = "VR_GetGenericInterface", CallingConvention = CallingConvention.Cdecl)]
+	internal static extern IntPtr GetGenericInterface([In, MarshalAs(UnmanagedType.LPStr)] string pchInterfaceVersion, ref EVRInitError peError);
+	[DllImportAttribute("openvr_api", EntryPoint = "VR_IsInterfaceVersionValid", CallingConvention = CallingConvention.Cdecl)]
+	internal static extern bool IsInterfaceVersionValid([In, MarshalAs(UnmanagedType.LPStr)] string pchInterfaceVersion);
+	[DllImportAttribute("openvr_api", EntryPoint = "VR_GetInitToken", CallingConvention = CallingConvention.Cdecl)]
+	internal static extern uint GetInitToken();
+}
+
+
+public enum EVREye
+{
+	Eye_Left = 0,
+	Eye_Right = 1,
+}
+public enum ETextureType
+{
+	DirectX = 0,
+	OpenGL = 1,
+	Vulkan = 2,
+	IOSurface = 3,
+	DirectX12 = 4,
+}
+public enum EColorSpace
+{
+	Auto = 0,
+	Gamma = 1,
+	Linear = 2,
+}
+public enum ETrackingResult
+{
+	Uninitialized = 1,
+	Calibrating_InProgress = 100,
+	Calibrating_OutOfRange = 101,
+	Running_OK = 200,
+	Running_OutOfRange = 201,
+}
+public enum ETrackedDeviceClass
+{
+	Invalid = 0,
+	HMD = 1,
+	Controller = 2,
+	GenericTracker = 3,
+	TrackingReference = 4,
+}
+public enum ETrackedControllerRole
+{
+	Invalid = 0,
+	LeftHand = 1,
+	RightHand = 2,
+}
+public enum ETrackingUniverseOrigin
+{
+	TrackingUniverseSeated = 0,
+	TrackingUniverseStanding = 1,
+	TrackingUniverseRawAndUncalibrated = 2,
+}
+public enum ETrackedDeviceProperty
+{
+	Prop_Invalid = 0,
+	Prop_TrackingSystemName_String = 1000,
+	Prop_ModelNumber_String = 1001,
+	Prop_SerialNumber_String = 1002,
+	Prop_RenderModelName_String = 1003,
+	Prop_WillDriftInYaw_Bool = 1004,
+	Prop_ManufacturerName_String = 1005,
+	Prop_TrackingFirmwareVersion_String = 1006,
+	Prop_HardwareRevision_String = 1007,
+	Prop_AllWirelessDongleDescriptions_String = 1008,
+	Prop_ConnectedWirelessDongle_String = 1009,
+	Prop_DeviceIsWireless_Bool = 1010,
+	Prop_DeviceIsCharging_Bool = 1011,
+	Prop_DeviceBatteryPercentage_Float = 1012,
+	Prop_StatusDisplayTransform_Matrix34 = 1013,
+	Prop_Firmware_UpdateAvailable_Bool = 1014,
+	Prop_Firmware_ManualUpdate_Bool = 1015,
+	Prop_Firmware_ManualUpdateURL_String = 1016,
+	Prop_HardwareRevision_Uint64 = 1017,
+	Prop_FirmwareVersion_Uint64 = 1018,
+	Prop_FPGAVersion_Uint64 = 1019,
+	Prop_VRCVersion_Uint64 = 1020,
+	Prop_RadioVersion_Uint64 = 1021,
+	Prop_DongleVersion_Uint64 = 1022,
+	Prop_BlockServerShutdown_Bool = 1023,
+	Prop_CanUnifyCoordinateSystemWithHmd_Bool = 1024,
+	Prop_ContainsProximitySensor_Bool = 1025,
+	Prop_DeviceProvidesBatteryStatus_Bool = 1026,
+	Prop_DeviceCanPowerOff_Bool = 1027,
+	Prop_Firmware_ProgrammingTarget_String = 1028,
+	Prop_DeviceClass_Int32 = 1029,
+	Prop_HasCamera_Bool = 1030,
+	Prop_DriverVersion_String = 1031,
+	Prop_Firmware_ForceUpdateRequired_Bool = 1032,
+	Prop_ViveSystemButtonFixRequired_Bool = 1033,
+	Prop_ParentDriver_Uint64 = 1034,
+	Prop_ReportsTimeSinceVSync_Bool = 2000,
+	Prop_SecondsFromVsyncToPhotons_Float = 2001,
+	Prop_DisplayFrequency_Float = 2002,
+	Prop_UserIpdMeters_Float = 2003,
+	Prop_CurrentUniverseId_Uint64 = 2004,
+	Prop_PreviousUniverseId_Uint64 = 2005,
+	Prop_DisplayFirmwareVersion_Uint64 = 2006,
+	Prop_IsOnDesktop_Bool = 2007,
+	Prop_DisplayMCType_Int32 = 2008,
+	Prop_DisplayMCOffset_Float = 2009,
+	Prop_DisplayMCScale_Float = 2010,
+	Prop_EdidVendorID_Int32 = 2011,
+	Prop_DisplayMCImageLeft_String = 2012,
+	Prop_DisplayMCImageRight_String = 2013,
+	Prop_DisplayGCBlackClamp_Float = 2014,
+	Prop_EdidProductID_Int32 = 2015,
+	Prop_CameraToHeadTransform_Matrix34 = 2016,
+	Prop_DisplayGCType_Int32 = 2017,
+	Prop_DisplayGCOffset_Float = 2018,
+	Prop_DisplayGCScale_Float = 2019,
+	Prop_DisplayGCPrescale_Float = 2020,
+	Prop_DisplayGCImage_String = 2021,
+	Prop_LensCenterLeftU_Float = 2022,
+	Prop_LensCenterLeftV_Float = 2023,
+	Prop_LensCenterRightU_Float = 2024,
+	Prop_LensCenterRightV_Float = 2025,
+	Prop_UserHeadToEyeDepthMeters_Float = 2026,
+	Prop_CameraFirmwareVersion_Uint64 = 2027,
+	Prop_CameraFirmwareDescription_String = 2028,
+	Prop_DisplayFPGAVersion_Uint64 = 2029,
+	Prop_DisplayBootloaderVersion_Uint64 = 2030,
+	Prop_DisplayHardwareVersion_Uint64 = 2031,
+	Prop_AudioFirmwareVersion_Uint64 = 2032,
+	Prop_CameraCompatibilityMode_Int32 = 2033,
+	Prop_ScreenshotHorizontalFieldOfViewDegrees_Float = 2034,
+	Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035,
+	Prop_DisplaySuppressed_Bool = 2036,
+	Prop_DisplayAllowNightMode_Bool = 2037,
+	Prop_DisplayMCImageWidth_Int32 = 2038,
+	Prop_DisplayMCImageHeight_Int32 = 2039,
+	Prop_DisplayMCImageNumChannels_Int32 = 2040,
+	Prop_DisplayMCImageData_Binary = 2041,
+	Prop_UsesDriverDirectMode_Bool = 2042,
+	Prop_AttachedDeviceId_String = 3000,
+	Prop_SupportedButtons_Uint64 = 3001,
+	Prop_Axis0Type_Int32 = 3002,
+	Prop_Axis1Type_Int32 = 3003,
+	Prop_Axis2Type_Int32 = 3004,
+	Prop_Axis3Type_Int32 = 3005,
+	Prop_Axis4Type_Int32 = 3006,
+	Prop_ControllerRoleHint_Int32 = 3007,
+	Prop_FieldOfViewLeftDegrees_Float = 4000,
+	Prop_FieldOfViewRightDegrees_Float = 4001,
+	Prop_FieldOfViewTopDegrees_Float = 4002,
+	Prop_FieldOfViewBottomDegrees_Float = 4003,
+	Prop_TrackingRangeMinimumMeters_Float = 4004,
+	Prop_TrackingRangeMaximumMeters_Float = 4005,
+	Prop_ModeLabel_String = 4006,
+	Prop_IconPathName_String = 5000,
+	Prop_NamedIconPathDeviceOff_String = 5001,
+	Prop_NamedIconPathDeviceSearching_String = 5002,
+	Prop_NamedIconPathDeviceSearchingAlert_String = 5003,
+	Prop_NamedIconPathDeviceReady_String = 5004,
+	Prop_NamedIconPathDeviceReadyAlert_String = 5005,
+	Prop_NamedIconPathDeviceNotReady_String = 5006,
+	Prop_NamedIconPathDeviceStandby_String = 5007,
+	Prop_NamedIconPathDeviceAlertLow_String = 5008,
+	Prop_DisplayHiddenArea_Binary_Start = 5100,
+	Prop_DisplayHiddenArea_Binary_End = 5150,
+	Prop_UserConfigPath_String = 6000,
+	Prop_InstallPath_String = 6001,
+	Prop_VendorSpecific_Reserved_Start = 10000,
+	Prop_VendorSpecific_Reserved_End = 10999,
+}
+public enum ETrackedPropertyError
+{
+	TrackedProp_Success = 0,
+	TrackedProp_WrongDataType = 1,
+	TrackedProp_WrongDeviceClass = 2,
+	TrackedProp_BufferTooSmall = 3,
+	TrackedProp_UnknownProperty = 4,
+	TrackedProp_InvalidDevice = 5,
+	TrackedProp_CouldNotContactServer = 6,
+	TrackedProp_ValueNotProvidedByDevice = 7,
+	TrackedProp_StringExceedsMaximumLength = 8,
+	TrackedProp_NotYetAvailable = 9,
+	TrackedProp_PermissionDenied = 10,
+	TrackedProp_InvalidOperation = 11,
+}
+public enum EVRSubmitFlags
+{
+	Submit_Default = 0,
+	Submit_LensDistortionAlreadyApplied = 1,
+	Submit_GlRenderBuffer = 2,
+	Submit_Reserved = 4,
+}
+public enum EVRState
+{
+	Undefined = -1,
+	Off = 0,
+	Searching = 1,
+	Searching_Alert = 2,
+	Ready = 3,
+	Ready_Alert = 4,
+	NotReady = 5,
+	Standby = 6,
+	Ready_Alert_Low = 7,
+}
+public enum EVREventType
+{
+	VREvent_None = 0,
+	VREvent_TrackedDeviceActivated = 100,
+	VREvent_TrackedDeviceDeactivated = 101,
+	VREvent_TrackedDeviceUpdated = 102,
+	VREvent_TrackedDeviceUserInteractionStarted = 103,
+	VREvent_TrackedDeviceUserInteractionEnded = 104,
+	VREvent_IpdChanged = 105,
+	VREvent_EnterStandbyMode = 106,
+	VREvent_LeaveStandbyMode = 107,
+	VREvent_TrackedDeviceRoleChanged = 108,
+	VREvent_WatchdogWakeUpRequested = 109,
+	VREvent_LensDistortionChanged = 110,
+	VREvent_PropertyChanged = 111,
+	VREvent_ButtonPress = 200,
+	VREvent_ButtonUnpress = 201,
+	VREvent_ButtonTouch = 202,
+	VREvent_ButtonUntouch = 203,
+	VREvent_MouseMove = 300,
+	VREvent_MouseButtonDown = 301,
+	VREvent_MouseButtonUp = 302,
+	VREvent_FocusEnter = 303,
+	VREvent_FocusLeave = 304,
+	VREvent_Scroll = 305,
+	VREvent_TouchPadMove = 306,
+	VREvent_OverlayFocusChanged = 307,
+	VREvent_InputFocusCaptured = 400,
+	VREvent_InputFocusReleased = 401,
+	VREvent_SceneFocusLost = 402,
+	VREvent_SceneFocusGained = 403,
+	VREvent_SceneApplicationChanged = 404,
+	VREvent_SceneFocusChanged = 405,
+	VREvent_InputFocusChanged = 406,
+	VREvent_SceneApplicationSecondaryRenderingStarted = 407,
+	VREvent_HideRenderModels = 410,
+	VREvent_ShowRenderModels = 411,
+	VREvent_OverlayShown = 500,
+	VREvent_OverlayHidden = 501,
+	VREvent_DashboardActivated = 502,
+	VREvent_DashboardDeactivated = 503,
+	VREvent_DashboardThumbSelected = 504,
+	VREvent_DashboardRequested = 505,
+	VREvent_ResetDashboard = 506,
+	VREvent_RenderToast = 507,
+	VREvent_ImageLoaded = 508,
+	VREvent_ShowKeyboard = 509,
+	VREvent_HideKeyboard = 510,
+	VREvent_OverlayGamepadFocusGained = 511,
+	VREvent_OverlayGamepadFocusLost = 512,
+	VREvent_OverlaySharedTextureChanged = 513,
+	VREvent_DashboardGuideButtonDown = 514,
+	VREvent_DashboardGuideButtonUp = 515,
+	VREvent_ScreenshotTriggered = 516,
+	VREvent_ImageFailed = 517,
+	VREvent_DashboardOverlayCreated = 518,
+	VREvent_RequestScreenshot = 520,
+	VREvent_ScreenshotTaken = 521,
+	VREvent_ScreenshotFailed = 522,
+	VREvent_SubmitScreenshotToDashboard = 523,
+	VREvent_ScreenshotProgressToDashboard = 524,
+	VREvent_PrimaryDashboardDeviceChanged = 525,
+	VREvent_Notification_Shown = 600,
+	VREvent_Notification_Hidden = 601,
+	VREvent_Notification_BeginInteraction = 602,
+	VREvent_Notification_Destroyed = 603,
+	VREvent_Quit = 700,
+	VREvent_ProcessQuit = 701,
+	VREvent_QuitAborted_UserPrompt = 702,
+	VREvent_QuitAcknowledged = 703,
+	VREvent_DriverRequestedQuit = 704,
+	VREvent_ChaperoneDataHasChanged = 800,
+	VREvent_ChaperoneUniverseHasChanged = 801,
+	VREvent_ChaperoneTempDataHasChanged = 802,
+	VREvent_ChaperoneSettingsHaveChanged = 803,
+	VREvent_SeatedZeroPoseReset = 804,
+	VREvent_AudioSettingsHaveChanged = 820,
+	VREvent_BackgroundSettingHasChanged = 850,
+	VREvent_CameraSettingsHaveChanged = 851,
+	VREvent_ReprojectionSettingHasChanged = 852,
+	VREvent_ModelSkinSettingsHaveChanged = 853,
+	VREvent_EnvironmentSettingsHaveChanged = 854,
+	VREvent_PowerSettingsHaveChanged = 855,
+	VREvent_StatusUpdate = 900,
+	VREvent_MCImageUpdated = 1000,
+	VREvent_FirmwareUpdateStarted = 1100,
+	VREvent_FirmwareUpdateFinished = 1101,
+	VREvent_KeyboardClosed = 1200,
+	VREvent_KeyboardCharInput = 1201,
+	VREvent_KeyboardDone = 1202,
+	VREvent_ApplicationTransitionStarted = 1300,
+	VREvent_ApplicationTransitionAborted = 1301,
+	VREvent_ApplicationTransitionNewAppStarted = 1302,
+	VREvent_ApplicationListUpdated = 1303,
+	VREvent_ApplicationMimeTypeLoad = 1304,
+	VREvent_ApplicationTransitionNewAppLaunchComplete = 1305,
+	VREvent_Compositor_MirrorWindowShown = 1400,
+	VREvent_Compositor_MirrorWindowHidden = 1401,
+	VREvent_Compositor_ChaperoneBoundsShown = 1410,
+	VREvent_Compositor_ChaperoneBoundsHidden = 1411,
+	VREvent_TrackedCamera_StartVideoStream = 1500,
+	VREvent_TrackedCamera_StopVideoStream = 1501,
+	VREvent_TrackedCamera_PauseVideoStream = 1502,
+	VREvent_TrackedCamera_ResumeVideoStream = 1503,
+	VREvent_TrackedCamera_EditingSurface = 1550,
+	VREvent_PerformanceTest_EnableCapture = 1600,
+	VREvent_PerformanceTest_DisableCapture = 1601,
+	VREvent_PerformanceTest_FidelityLevel = 1602,
+	VREvent_MessageOverlay_Closed = 1650,
+	VREvent_VendorSpecific_Reserved_Start = 10000,
+	VREvent_VendorSpecific_Reserved_End = 19999,
+}
+public enum EDeviceActivityLevel
+{
+	k_EDeviceActivityLevel_Unknown = -1,
+	k_EDeviceActivityLevel_Idle = 0,
+	k_EDeviceActivityLevel_UserInteraction = 1,
+	k_EDeviceActivityLevel_UserInteraction_Timeout = 2,
+	k_EDeviceActivityLevel_Standby = 3,
+}
+public enum EVRButtonId
+{
+	k_EButton_System = 0,
+	k_EButton_ApplicationMenu = 1,
+	k_EButton_Grip = 2,
+	k_EButton_DPad_Left = 3,
+	k_EButton_DPad_Up = 4,
+	k_EButton_DPad_Right = 5,
+	k_EButton_DPad_Down = 6,
+	k_EButton_A = 7,
+	k_EButton_ProximitySensor = 31,
+	k_EButton_Axis0 = 32,
+	k_EButton_Axis1 = 33,
+	k_EButton_Axis2 = 34,
+	k_EButton_Axis3 = 35,
+	k_EButton_Axis4 = 36,
+	k_EButton_SteamVR_Touchpad = 32,
+	k_EButton_SteamVR_Trigger = 33,
+	k_EButton_Dashboard_Back = 2,
+	k_EButton_Max = 64,
+}
+public enum EVRMouseButton
+{
+	Left = 1,
+	Right = 2,
+	Middle = 4,
+}
+public enum EHiddenAreaMeshType
+{
+	k_eHiddenAreaMesh_Standard = 0,
+	k_eHiddenAreaMesh_Inverse = 1,
+	k_eHiddenAreaMesh_LineLoop = 2,
+	k_eHiddenAreaMesh_Max = 3,
+}
+public enum EVRControllerAxisType
+{
+	k_eControllerAxis_None = 0,
+	k_eControllerAxis_TrackPad = 1,
+	k_eControllerAxis_Joystick = 2,
+	k_eControllerAxis_Trigger = 3,
+}
+public enum EVRControllerEventOutputType
+{
+	ControllerEventOutput_OSEvents = 0,
+	ControllerEventOutput_VREvents = 1,
+}
+public enum ECollisionBoundsStyle
+{
+	COLLISION_BOUNDS_STYLE_BEGINNER = 0,
+	COLLISION_BOUNDS_STYLE_INTERMEDIATE = 1,
+	COLLISION_BOUNDS_STYLE_SQUARES = 2,
+	COLLISION_BOUNDS_STYLE_ADVANCED = 3,
+	COLLISION_BOUNDS_STYLE_NONE = 4,
+	COLLISION_BOUNDS_STYLE_COUNT = 5,
+}
+public enum EVROverlayError
+{
+	None = 0,
+	UnknownOverlay = 10,
+	InvalidHandle = 11,
+	PermissionDenied = 12,
+	OverlayLimitExceeded = 13,
+	WrongVisibilityType = 14,
+	KeyTooLong = 15,
+	NameTooLong = 16,
+	KeyInUse = 17,
+	WrongTransformType = 18,
+	InvalidTrackedDevice = 19,
+	InvalidParameter = 20,
+	ThumbnailCantBeDestroyed = 21,
+	ArrayTooSmall = 22,
+	RequestFailed = 23,
+	InvalidTexture = 24,
+	UnableToLoadFile = 25,
+	KeyboardAlreadyInUse = 26,
+	NoNeighbor = 27,
+	TooManyMaskPrimitives = 29,
+	BadMaskPrimitive = 30,
+}
+public enum EVRApplicationType
+{
+	VRApplication_Other = 0,
+	VRApplication_Scene = 1,
+	VRApplication_Overlay = 2,
+	VRApplication_Background = 3,
+	VRApplication_Utility = 4,
+	VRApplication_VRMonitor = 5,
+	VRApplication_SteamWatchdog = 6,
+	VRApplication_Max = 7,
+}
+public enum EVRFirmwareError
+{
+	None = 0,
+	Success = 1,
+	Fail = 2,
+}
+public enum EVRNotificationError
+{
+	OK = 0,
+	InvalidNotificationId = 100,
+	NotificationQueueFull = 101,
+	InvalidOverlayHandle = 102,
+	SystemWithUserValueAlreadyExists = 103,
+}
+public enum EVRInitError
+{
+	None = 0,
+	Unknown = 1,
+	Init_InstallationNotFound = 100,
+	Init_InstallationCorrupt = 101,
+	Init_VRClientDLLNotFound = 102,
+	Init_FileNotFound = 103,
+	Init_FactoryNotFound = 104,
+	Init_InterfaceNotFound = 105,
+	Init_InvalidInterface = 106,
+	Init_UserConfigDirectoryInvalid = 107,
+	Init_HmdNotFound = 108,
+	Init_NotInitialized = 109,
+	Init_PathRegistryNotFound = 110,
+	Init_NoConfigPath = 111,
+	Init_NoLogPath = 112,
+	Init_PathRegistryNotWritable = 113,
+	Init_AppInfoInitFailed = 114,
+	Init_Retry = 115,
+	Init_InitCanceledByUser = 116,
+	Init_AnotherAppLaunching = 117,
+	Init_SettingsInitFailed = 118,
+	Init_ShuttingDown = 119,
+	Init_TooManyObjects = 120,
+	Init_NoServerForBackgroundApp = 121,
+	Init_NotSupportedWithCompositor = 122,
+	Init_NotAvailableToUtilityApps = 123,
+	Init_Internal = 124,
+	Init_HmdDriverIdIsNone = 125,
+	Init_HmdNotFoundPresenceFailed = 126,
+	Init_VRMonitorNotFound = 127,
+	Init_VRMonitorStartupFailed = 128,
+	Init_LowPowerWatchdogNotSupported = 129,
+	Init_InvalidApplicationType = 130,
+	Init_NotAvailableToWatchdogApps = 131,
+	Init_WatchdogDisabledInSettings = 132,
+	Init_VRDashboardNotFound = 133,
+	Init_VRDashboardStartupFailed = 134,
+	Driver_Failed = 200,
+	Driver_Unknown = 201,
+	Driver_HmdUnknown = 202,
+	Driver_NotLoaded = 203,
+	Driver_RuntimeOutOfDate = 204,
+	Driver_HmdInUse = 205,
+	Driver_NotCalibrated = 206,
+	Driver_CalibrationInvalid = 207,
+	Driver_HmdDisplayNotFound = 208,
+	Driver_TrackedDeviceInterfaceUnknown = 209,
+	Driver_HmdDriverIdOutOfBounds = 211,
+	Driver_HmdDisplayMirrored = 212,
+	IPC_ServerInitFailed = 300,
+	IPC_ConnectFailed = 301,
+	IPC_SharedStateInitFailed = 302,
+	IPC_CompositorInitFailed = 303,
+	IPC_MutexInitFailed = 304,
+	IPC_Failed = 305,
+	IPC_CompositorConnectFailed = 306,
+	IPC_CompositorInvalidConnectResponse = 307,
+	IPC_ConnectFailedAfterMultipleAttempts = 308,
+	Compositor_Failed = 400,
+	Compositor_D3D11HardwareRequired = 401,
+	Compositor_FirmwareRequiresUpdate = 402,
+	Compositor_OverlayInitFailed = 403,
+	Compositor_ScreenshotsInitFailed = 404,
+	VendorSpecific_UnableToConnectToOculusRuntime = 1000,
+	VendorSpecific_HmdFound_CantOpenDevice = 1101,
+	VendorSpecific_HmdFound_UnableToRequestConfigStart = 1102,
+	VendorSpecific_HmdFound_NoStoredConfig = 1103,
+	VendorSpecific_HmdFound_ConfigTooBig = 1104,
+	VendorSpecific_HmdFound_ConfigTooSmall = 1105,
+	VendorSpecific_HmdFound_UnableToInitZLib = 1106,
+	VendorSpecific_HmdFound_CantReadFirmwareVersion = 1107,
+	VendorSpecific_HmdFound_UnableToSendUserDataStart = 1108,
+	VendorSpecific_HmdFound_UnableToGetUserDataStart = 1109,
+	VendorSpecific_HmdFound_UnableToGetUserDataNext = 1110,
+	VendorSpecific_HmdFound_UserDataAddressRange = 1111,
+	VendorSpecific_HmdFound_UserDataError = 1112,
+	VendorSpecific_HmdFound_ConfigFailedSanityCheck = 1113,
+	Steam_SteamInstallationNotFound = 2000,
+}
+public enum EVRScreenshotType
+{
+	None = 0,
+	Mono = 1,
+	Stereo = 2,
+	Cubemap = 3,
+	MonoPanorama = 4,
+	StereoPanorama = 5,
+}
+public enum EVRScreenshotPropertyFilenames
+{
+	Preview = 0,
+	VR = 1,
+}
+public enum EVRTrackedCameraError
+{
+	None = 0,
+	OperationFailed = 100,
+	InvalidHandle = 101,
+	InvalidFrameHeaderVersion = 102,
+	OutOfHandles = 103,
+	IPCFailure = 104,
+	NotSupportedForThisDevice = 105,
+	SharedMemoryFailure = 106,
+	FrameBufferingFailure = 107,
+	StreamSetupFailure = 108,
+	InvalidGLTextureId = 109,
+	InvalidSharedTextureHandle = 110,
+	FailedToGetGLTextureId = 111,
+	SharedTextureFailure = 112,
+	NoFrameAvailable = 113,
+	InvalidArgument = 114,
+	InvalidFrameBufferSize = 115,
+}
+public enum EVRTrackedCameraFrameType
+{
+	Distorted = 0,
+	Undistorted = 1,
+	MaximumUndistorted = 2,
+	MAX_CAMERA_FRAME_TYPES = 3,
+}
+public enum EVRApplicationError
+{
+	None = 0,
+	AppKeyAlreadyExists = 100,
+	NoManifest = 101,
+	NoApplication = 102,
+	InvalidIndex = 103,
+	UnknownApplication = 104,
+	IPCFailed = 105,
+	ApplicationAlreadyRunning = 106,
+	InvalidManifest = 107,
+	InvalidApplication = 108,
+	LaunchFailed = 109,
+	ApplicationAlreadyStarting = 110,
+	LaunchInProgress = 111,
+	OldApplicationQuitting = 112,
+	TransitionAborted = 113,
+	IsTemplate = 114,
+	BufferTooSmall = 200,
+	PropertyNotSet = 201,
+	UnknownProperty = 202,
+	InvalidParameter = 203,
+}
+public enum EVRApplicationProperty
+{
+	Name_String = 0,
+	LaunchType_String = 11,
+	WorkingDirectory_String = 12,
+	BinaryPath_String = 13,
+	Arguments_String = 14,
+	URL_String = 15,
+	Description_String = 50,
+	NewsURL_String = 51,
+	ImagePath_String = 52,
+	Source_String = 53,
+	IsDashboardOverlay_Bool = 60,
+	IsTemplate_Bool = 61,
+	IsInstanced_Bool = 62,
+	IsInternal_Bool = 63,
+	LastLaunchTime_Uint64 = 70,
+}
+public enum EVRApplicationTransitionState
+{
+	VRApplicationTransition_None = 0,
+	VRApplicationTransition_OldAppQuitSent = 10,
+	VRApplicationTransition_WaitingForExternalLaunch = 11,
+	VRApplicationTransition_NewAppLaunched = 20,
+}
+public enum ChaperoneCalibrationState
+{
+	OK = 1,
+	Warning = 100,
+	Warning_BaseStationMayHaveMoved = 101,
+	Warning_BaseStationRemoved = 102,
+	Warning_SeatedBoundsInvalid = 103,
+	Error = 200,
+	Error_BaseStationUninitialized = 201,
+	Error_BaseStationConflict = 202,
+	Error_PlayAreaInvalid = 203,
+	Error_CollisionBoundsInvalid = 204,
+}
+public enum EChaperoneConfigFile
+{
+	Live = 1,
+	Temp = 2,
+}
+public enum EChaperoneImportFlags
+{
+	EChaperoneImport_BoundsOnly = 1,
+}
+public enum EVRCompositorError
+{
+	None = 0,
+	RequestFailed = 1,
+	IncompatibleVersion = 100,
+	DoNotHaveFocus = 101,
+	InvalidTexture = 102,
+	IsNotSceneApplication = 103,
+	TextureIsOnWrongDevice = 104,
+	TextureUsesUnsupportedFormat = 105,
+	SharedTexturesNotSupported = 106,
+	IndexOutOfRange = 107,
+	AlreadySubmitted = 108,
+}
+public enum VROverlayInputMethod
+{
+	None = 0,
+	Mouse = 1,
+}
+public enum VROverlayTransformType
+{
+	VROverlayTransform_Absolute = 0,
+	VROverlayTransform_TrackedDeviceRelative = 1,
+	VROverlayTransform_SystemOverlay = 2,
+	VROverlayTransform_TrackedComponent = 3,
+}
+public enum VROverlayFlags
+{
+	None = 0,
+	Curved = 1,
+	RGSS4X = 2,
+	NoDashboardTab = 3,
+	AcceptsGamepadEvents = 4,
+	ShowGamepadFocus = 5,
+	SendVRScrollEvents = 6,
+	SendVRTouchpadEvents = 7,
+	ShowTouchPadScrollWheel = 8,
+	TransferOwnershipToInternalProcess = 9,
+	SideBySide_Parallel = 10,
+	SideBySide_Crossed = 11,
+	Panorama = 12,
+	StereoPanorama = 13,
+	SortWithNonSceneOverlays = 14,
+	VisibleInDashboard = 15,
+}
+public enum VRMessageOverlayResponse
+{
+	ButtonPress_0 = 0,
+	ButtonPress_1 = 1,
+	ButtonPress_2 = 2,
+	ButtonPress_3 = 3,
+	CouldntFindSystemOverlay = 4,
+	CouldntFindOrCreateClientOverlay = 5,
+	ApplicationQuit = 6,
+}
+public enum EGamepadTextInputMode
+{
+	k_EGamepadTextInputModeNormal = 0,
+	k_EGamepadTextInputModePassword = 1,
+	k_EGamepadTextInputModeSubmit = 2,
+}
+public enum EGamepadTextInputLineMode
+{
+	k_EGamepadTextInputLineModeSingleLine = 0,
+	k_EGamepadTextInputLineModeMultipleLines = 1,
+}
+public enum EOverlayDirection
+{
+	Up = 0,
+	Down = 1,
+	Left = 2,
+	Right = 3,
+	Count = 4,
+}
+public enum EVROverlayIntersectionMaskPrimitiveType
+{
+	OverlayIntersectionPrimitiveType_Rectangle = 0,
+	OverlayIntersectionPrimitiveType_Circle = 1,
+}
+public enum EVRRenderModelError
+{
+	None = 0,
+	Loading = 100,
+	NotSupported = 200,
+	InvalidArg = 300,
+	InvalidModel = 301,
+	NoShapes = 302,
+	MultipleShapes = 303,
+	TooManyVertices = 304,
+	MultipleTextures = 305,
+	BufferTooSmall = 306,
+	NotEnoughNormals = 307,
+	NotEnoughTexCoords = 308,
+	InvalidTexture = 400,
+}
+public enum EVRComponentProperty
+{
+	IsStatic = 1,
+	IsVisible = 2,
+	IsTouched = 4,
+	IsPressed = 8,
+	IsScrolled = 16,
+}
+public enum EVRNotificationType
+{
+	Transient = 0,
+	Persistent = 1,
+	Transient_SystemWithUserValue = 2,
+}
+public enum EVRNotificationStyle
+{
+	None = 0,
+	Application = 100,
+	Contact_Disabled = 200,
+	Contact_Enabled = 201,
+	Contact_Active = 202,
+}
+public enum EVRSettingsError
+{
+	None = 0,
+	IPCFailed = 1,
+	WriteFailed = 2,
+	ReadFailed = 3,
+	JsonParseFailed = 4,
+	UnsetSettingHasNoDefault = 5,
+}
+public enum EVRScreenshotError
+{
+	None = 0,
+	RequestFailed = 1,
+	IncompatibleVersion = 100,
+	NotFound = 101,
+	BufferTooSmall = 102,
+	ScreenshotAlreadyInProgress = 108,
+}
+
+[StructLayout(LayoutKind.Explicit)] public struct VREvent_Data_t
+{
+	[FieldOffset(0)] public VREvent_Reserved_t reserved;
+	[FieldOffset(0)] public VREvent_Controller_t controller;
+	[FieldOffset(0)] public VREvent_Mouse_t mouse;
+	[FieldOffset(0)] public VREvent_Scroll_t scroll;
+	[FieldOffset(0)] public VREvent_Process_t process;
+	[FieldOffset(0)] public VREvent_Notification_t notification;
+	[FieldOffset(0)] public VREvent_Overlay_t overlay;
+	[FieldOffset(0)] public VREvent_Status_t status;
+	[FieldOffset(0)] public VREvent_Ipd_t ipd;
+	[FieldOffset(0)] public VREvent_Chaperone_t chaperone;
+	[FieldOffset(0)] public VREvent_PerformanceTest_t performanceTest;
+	[FieldOffset(0)] public VREvent_TouchPadMove_t touchPadMove;
+	[FieldOffset(0)] public VREvent_SeatedZeroPoseReset_t seatedZeroPoseReset;
+	[FieldOffset(0)] public VREvent_Screenshot_t screenshot;
+	[FieldOffset(0)] public VREvent_ScreenshotProgress_t screenshotProgress;
+	[FieldOffset(0)] public VREvent_ApplicationLaunch_t applicationLaunch;
+	[FieldOffset(0)] public VREvent_EditingCameraSurface_t cameraSurface;
+	[FieldOffset(0)] public VREvent_MessageOverlay_t messageOverlay;
+	[FieldOffset(0)] public VREvent_Keyboard_t keyboard; // This has to be at the end due to a mono bug
+}
+
+
+[StructLayout(LayoutKind.Explicit)] public struct VROverlayIntersectionMaskPrimitive_Data_t
+{
+	[FieldOffset(0)] public IntersectionMaskRectangle_t m_Rectangle;
+	[FieldOffset(0)] public IntersectionMaskCircle_t m_Circle;
+}
+
+[StructLayout(LayoutKind.Sequential)] public struct HmdMatrix34_t
+{
+	public float m0; //float[3][4]
+	public float m1;
+	public float m2;
+	public float m3;
+	public float m4;
+	public float m5;
+	public float m6;
+	public float m7;
+	public float m8;
+	public float m9;
+	public float m10;
+	public float m11;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HmdMatrix44_t
+{
+	public float m0; //float[4][4]
+	public float m1;
+	public float m2;
+	public float m3;
+	public float m4;
+	public float m5;
+	public float m6;
+	public float m7;
+	public float m8;
+	public float m9;
+	public float m10;
+	public float m11;
+	public float m12;
+	public float m13;
+	public float m14;
+	public float m15;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HmdVector3_t
+{
+	public float v0; //float[3]
+	public float v1;
+	public float v2;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HmdVector4_t
+{
+	public float v0; //float[4]
+	public float v1;
+	public float v2;
+	public float v3;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HmdVector3d_t
+{
+	public double v0; //double[3]
+	public double v1;
+	public double v2;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HmdVector2_t
+{
+	public float v0; //float[2]
+	public float v1;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HmdQuaternion_t
+{
+	public double w;
+	public double x;
+	public double y;
+	public double z;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HmdColor_t
+{
+	public float r;
+	public float g;
+	public float b;
+	public float a;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HmdQuad_t
+{
+	public HmdVector3_t vCorners0; //HmdVector3_t[4]
+	public HmdVector3_t vCorners1;
+	public HmdVector3_t vCorners2;
+	public HmdVector3_t vCorners3;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HmdRect2_t
+{
+	public HmdVector2_t vTopLeft;
+	public HmdVector2_t vBottomRight;
+}
+[StructLayout(LayoutKind.Sequential)] public struct DistortionCoordinates_t
+{
+	public float rfRed0; //float[2]
+	public float rfRed1;
+	public float rfGreen0; //float[2]
+	public float rfGreen1;
+	public float rfBlue0; //float[2]
+	public float rfBlue1;
+}
+[StructLayout(LayoutKind.Sequential)] public struct Texture_t
+{
+	public IntPtr handle; // void *
+	public ETextureType eType;
+	public EColorSpace eColorSpace;
+}
+[StructLayout(LayoutKind.Sequential)] public struct TrackedDevicePose_t
+{
+	public HmdMatrix34_t mDeviceToAbsoluteTracking;
+	public HmdVector3_t vVelocity;
+	public HmdVector3_t vAngularVelocity;
+	public ETrackingResult eTrackingResult;
+	[MarshalAs(UnmanagedType.I1)]
+	public bool bPoseIsValid;
+	[MarshalAs(UnmanagedType.I1)]
+	public bool bDeviceIsConnected;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VRTextureBounds_t
+{
+	public float uMin;
+	public float vMin;
+	public float uMax;
+	public float vMax;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VRVulkanTextureData_t
+{
+	public ulong m_nImage;
+	public IntPtr m_pDevice; // struct VkDevice_T *
+	public IntPtr m_pPhysicalDevice; // struct VkPhysicalDevice_T *
+	public IntPtr m_pInstance; // struct VkInstance_T *
+	public IntPtr m_pQueue; // struct VkQueue_T *
+	public uint m_nQueueFamilyIndex;
+	public uint m_nWidth;
+	public uint m_nHeight;
+	public uint m_nFormat;
+	public uint m_nSampleCount;
+}
+[StructLayout(LayoutKind.Sequential)] public struct D3D12TextureData_t
+{
+	public IntPtr m_pResource; // struct ID3D12Resource *
+	public IntPtr m_pCommandQueue; // struct ID3D12CommandQueue *
+	public uint m_nNodeMask;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Controller_t
+{
+	public uint button;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Mouse_t
+{
+	public float x;
+	public float y;
+	public uint button;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Scroll_t
+{
+	public float xdelta;
+	public float ydelta;
+	public uint repeatCount;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_TouchPadMove_t
+{
+	[MarshalAs(UnmanagedType.I1)]
+	public bool bFingerDown;
+	public float flSecondsFingerDown;
+	public float fValueXFirst;
+	public float fValueYFirst;
+	public float fValueXRaw;
+	public float fValueYRaw;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Notification_t
+{
+	public ulong ulUserValue;
+	public uint notificationId;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Process_t
+{
+	public uint pid;
+	public uint oldPid;
+	[MarshalAs(UnmanagedType.I1)]
+	public bool bForced;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Overlay_t
+{
+	public ulong overlayHandle;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Status_t
+{
+	public uint statusState;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Keyboard_t
+{
+	public byte cNewInput0,cNewInput1,cNewInput2,cNewInput3,cNewInput4,cNewInput5,cNewInput6,cNewInput7;
+	public ulong uUserValue;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Ipd_t
+{
+	public float ipdMeters;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Chaperone_t
+{
+	public ulong m_nPreviousUniverse;
+	public ulong m_nCurrentUniverse;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Reserved_t
+{
+	public ulong reserved0;
+	public ulong reserved1;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_PerformanceTest_t
+{
+	public uint m_nFidelityLevel;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_SeatedZeroPoseReset_t
+{
+	[MarshalAs(UnmanagedType.I1)]
+	public bool bResetBySystemMenu;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Screenshot_t
+{
+	public uint handle;
+	public uint type;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_ScreenshotProgress_t
+{
+	public float progress;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_ApplicationLaunch_t
+{
+	public uint pid;
+	public uint unArgsHandle;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_EditingCameraSurface_t
+{
+	public ulong overlayHandle;
+	public uint nVisualMode;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_MessageOverlay_t
+{
+	public uint unVRMessageOverlayResponse;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_Property_t
+{
+	public ulong container;
+	public ETrackedDeviceProperty prop;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VREvent_t
+{
+	public uint eventType;
+	public uint trackedDeviceIndex;
+	public float eventAgeSeconds;
+	public VREvent_Data_t data;
+}
+[StructLayout(LayoutKind.Sequential)] public struct HiddenAreaMesh_t
+{
+	public IntPtr pVertexData; // const struct vr::HmdVector2_t *
+	public uint unTriangleCount;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VRControllerAxis_t
+{
+	public float x;
+	public float y;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VRControllerState_t
+{
+	public uint unPacketNum;
+	public ulong ulButtonPressed;
+	public ulong ulButtonTouched;
+	public VRControllerAxis_t rAxis0; //VRControllerAxis_t[5]
+	public VRControllerAxis_t rAxis1;
+	public VRControllerAxis_t rAxis2;
+	public VRControllerAxis_t rAxis3;
+	public VRControllerAxis_t rAxis4;
+}
+// This structure is for backwards binary compatibility on Linux and OSX only
+[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct VRControllerState_t_Packed
+{
+	public uint unPacketNum;
+	public ulong ulButtonPressed;
+	public ulong ulButtonTouched;
+	public VRControllerAxis_t rAxis0; //VRControllerAxis_t[5]
+	public VRControllerAxis_t rAxis1;
+	public VRControllerAxis_t rAxis2;
+	public VRControllerAxis_t rAxis3;
+	public VRControllerAxis_t rAxis4;
+	public void Unpack(ref VRControllerState_t unpacked)
+	{
+		unpacked.unPacketNum = this.unPacketNum;
+		unpacked.ulButtonPressed = this.ulButtonPressed;
+		unpacked.ulButtonTouched = this.ulButtonTouched;
+		unpacked.rAxis0 = this.rAxis0;
+		unpacked.rAxis1 = this.rAxis1;
+		unpacked.rAxis2 = this.rAxis2;
+		unpacked.rAxis3 = this.rAxis3;
+		unpacked.rAxis4 = this.rAxis4;
+	}
+}
+[StructLayout(LayoutKind.Sequential)] public struct Compositor_OverlaySettings
+{
+	public uint size;
+	[MarshalAs(UnmanagedType.I1)]
+	public bool curved;
+	[MarshalAs(UnmanagedType.I1)]
+	public bool antialias;
+	public float scale;
+	public float distance;
+	public float alpha;
+	public float uOffset;
+	public float vOffset;
+	public float uScale;
+	public float vScale;
+	public float gridDivs;
+	public float gridWidth;
+	public float gridScale;
+	public HmdMatrix44_t transform;
+}
+[StructLayout(LayoutKind.Sequential)] public struct CameraVideoStreamFrameHeader_t
+{
+	public EVRTrackedCameraFrameType eFrameType;
+	public uint nWidth;
+	public uint nHeight;
+	public uint nBytesPerPixel;
+	public uint nFrameSequence;
+	public TrackedDevicePose_t standingTrackedDevicePose;
+}
+[StructLayout(LayoutKind.Sequential)] public struct AppOverrideKeys_t
+{
+	public IntPtr pchKey; // const char *
+	public IntPtr pchValue; // const char *
+}
+[StructLayout(LayoutKind.Sequential)] public struct Compositor_FrameTiming
+{
+	public uint m_nSize;
+	public uint m_nFrameIndex;
+	public uint m_nNumFramePresents;
+	public uint m_nNumMisPresented;
+	public uint m_nNumDroppedFrames;
+	public uint m_nReprojectionFlags;
+	public double m_flSystemTimeInSeconds;
+	public float m_flPreSubmitGpuMs;
+	public float m_flPostSubmitGpuMs;
+	public float m_flTotalRenderGpuMs;
+	public float m_flCompositorRenderGpuMs;
+	public float m_flCompositorRenderCpuMs;
+	public float m_flCompositorIdleCpuMs;
+	public float m_flClientFrameIntervalMs;
+	public float m_flPresentCallCpuMs;
+	public float m_flWaitForPresentCpuMs;
+	public float m_flSubmitFrameMs;
+	public float m_flWaitGetPosesCalledMs;
+	public float m_flNewPosesReadyMs;
+	public float m_flNewFrameReadyMs;
+	public float m_flCompositorUpdateStartMs;
+	public float m_flCompositorUpdateEndMs;
+	public float m_flCompositorRenderStartMs;
+	public TrackedDevicePose_t m_HmdPose;
+}
+[StructLayout(LayoutKind.Sequential)] public struct Compositor_CumulativeStats
+{
+	public uint m_nPid;
+	public uint m_nNumFramePresents;
+	public uint m_nNumDroppedFrames;
+	public uint m_nNumReprojectedFrames;
+	public uint m_nNumFramePresentsOnStartup;
+	public uint m_nNumDroppedFramesOnStartup;
+	public uint m_nNumReprojectedFramesOnStartup;
+	public uint m_nNumLoading;
+	public uint m_nNumFramePresentsLoading;
+	public uint m_nNumDroppedFramesLoading;
+	public uint m_nNumReprojectedFramesLoading;
+	public uint m_nNumTimedOut;
+	public uint m_nNumFramePresentsTimedOut;
+	public uint m_nNumDroppedFramesTimedOut;
+	public uint m_nNumReprojectedFramesTimedOut;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VROverlayIntersectionParams_t
+{
+	public HmdVector3_t vSource;
+	public HmdVector3_t vDirection;
+	public ETrackingUniverseOrigin eOrigin;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VROverlayIntersectionResults_t
+{
+	public HmdVector3_t vPoint;
+	public HmdVector3_t vNormal;
+	public HmdVector2_t vUVs;
+	public float fDistance;
+}
+[StructLayout(LayoutKind.Sequential)] public struct IntersectionMaskRectangle_t
+{
+	public float m_flTopLeftX;
+	public float m_flTopLeftY;
+	public float m_flWidth;
+	public float m_flHeight;
+}
+[StructLayout(LayoutKind.Sequential)] public struct IntersectionMaskCircle_t
+{
+	public float m_flCenterX;
+	public float m_flCenterY;
+	public float m_flRadius;
+}
+[StructLayout(LayoutKind.Sequential)] public struct VROverlayIntersectionMaskPrimitive_t
+{
+	public EVROverlayIntersectionMaskPrimitiveType m_nPrimitiveType;
+	public VROverlayIntersectionMaskPrimitive_Data_t m_Primitive;
+}
+[StructLayout(LayoutKind.Sequential)] public struct RenderModel_ComponentState_t
+{
+	public HmdMatrix34_t mTrackingToComponentRenderModel;
+	public HmdMatrix34_t mTrackingToComponentLocal;
+	public uint uProperties;
+}
+[StructLayout(LayoutKind.Sequential)] public struct RenderModel_Vertex_t
+{
+	public HmdVector3_t vPosition;
+	public HmdVector3_t vNormal;
+	public float rfTextureCoord0; //float[2]
+	public float rfTextureCoord1;
+}
+[StructLayout(LayoutKind.Sequential)] public struct RenderModel_TextureMap_t
+{
+	public char unWidth;
+	public char unHeight;
+	public IntPtr rubTextureMapData; // const uint8_t *
+}
+// This structure is for backwards binary compatibility on Linux and OSX only
+[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct RenderModel_TextureMap_t_Packed
+{
+	public char unWidth;
+	public char unHeight;
+	public IntPtr rubTextureMapData; // const uint8_t *
+	public void Unpack(ref RenderModel_TextureMap_t unpacked)
+	{
+		unpacked.unWidth = this.unWidth;
+		unpacked.unHeight = this.unHeight;
+		unpacked.rubTextureMapData = this.rubTextureMapData;
+	}
+}
+[StructLayout(LayoutKind.Sequential)] public struct RenderModel_t
+{
+	public IntPtr rVertexData; // const struct vr::RenderModel_Vertex_t *
+	public uint unVertexCount;
+	public IntPtr rIndexData; // const uint16_t *
+	public uint unTriangleCount;
+	public int diffuseTextureId;
+}
+// This structure is for backwards binary compatibility on Linux and OSX only
+[StructLayout(LayoutKind.Sequential, Pack = 4)] public struct RenderModel_t_Packed
+{
+	public IntPtr rVertexData; // const struct vr::RenderModel_Vertex_t *
+	public uint unVertexCount;
+	public IntPtr rIndexData; // const uint16_t *
+	public uint unTriangleCount;
+	public int diffuseTextureId;
+	public void Unpack(ref RenderModel_t unpacked)
+	{
+		unpacked.rVertexData = this.rVertexData;
+		unpacked.unVertexCount = this.unVertexCount;
+		unpacked.rIndexData = this.rIndexData;
+		unpacked.unTriangleCount = this.unTriangleCount;
+		unpacked.diffuseTextureId = this.diffuseTextureId;
+	}
+}
+[StructLayout(LayoutKind.Sequential)] public struct RenderModel_ControllerMode_State_t
+{
+	[MarshalAs(UnmanagedType.I1)]
+	public bool bScrollWheelVisible;
+}
+[StructLayout(LayoutKind.Sequential)] public struct NotificationBitmap_t
+{
+	public IntPtr m_pImageData; // void *
+	public int m_nWidth;
+	public int m_nHeight;
+	public int m_nBytesPerPixel;
+}
+[StructLayout(LayoutKind.Sequential)] public struct COpenVRContext
+{
+	public IntPtr m_pVRSystem; // class vr::IVRSystem *
+	public IntPtr m_pVRChaperone; // class vr::IVRChaperone *
+	public IntPtr m_pVRChaperoneSetup; // class vr::IVRChaperoneSetup *
+	public IntPtr m_pVRCompositor; // class vr::IVRCompositor *
+	public IntPtr m_pVROverlay; // class vr::IVROverlay *
+	public IntPtr m_pVRResources; // class vr::IVRResources *
+	public IntPtr m_pVRRenderModels; // class vr::IVRRenderModels *
+	public IntPtr m_pVRExtendedDisplay; // class vr::IVRExtendedDisplay *
+	public IntPtr m_pVRSettings; // class vr::IVRSettings *
+	public IntPtr m_pVRApplications; // class vr::IVRApplications *
+	public IntPtr m_pVRTrackedCamera; // class vr::IVRTrackedCamera *
+	public IntPtr m_pVRScreenshots; // class vr::IVRScreenshots *
+}
+
+public class OpenVR
+{
+
+	public static uint InitInternal(ref EVRInitError peError, EVRApplicationType eApplicationType)
+	{
+		return OpenVRInterop.InitInternal(ref peError, eApplicationType);
+	}
+
+	public static void ShutdownInternal()
+	{
+		OpenVRInterop.ShutdownInternal();
+	}
+
+	public static bool IsHmdPresent()
+	{
+		return OpenVRInterop.IsHmdPresent();
+	}
+
+	public static bool IsRuntimeInstalled()
+	{
+		return OpenVRInterop.IsRuntimeInstalled();
+	}
+
+	public static string GetStringForHmdError(EVRInitError error)
+	{
+		return Marshal.PtrToStringAnsi(OpenVRInterop.GetStringForHmdError(error));
+	}
+
+	public static IntPtr GetGenericInterface(string pchInterfaceVersion, ref EVRInitError peError)
+	{
+		return OpenVRInterop.GetGenericInterface(pchInterfaceVersion, ref peError);
+	}
+
+	public static bool IsInterfaceVersionValid(string pchInterfaceVersion)
+	{
+		return OpenVRInterop.IsInterfaceVersionValid(pchInterfaceVersion);
+	}
+
+	public static uint GetInitToken()
+	{
+		return OpenVRInterop.GetInitToken();
+	}
+
+	public const uint k_unMaxDriverDebugResponseSize = 32768;
+	public const uint k_unTrackedDeviceIndex_Hmd = 0;
+	public const uint k_unMaxTrackedDeviceCount = 16;
+	public const uint k_unTrackedDeviceIndexOther = 4294967294;
+	public const uint k_unTrackedDeviceIndexInvalid = 4294967295;
+	public const ulong k_ulInvalidPropertyContainer = 0;
+	public const uint k_unInvalidPropertyTag = 0;
+	public const uint k_unFloatPropertyTag = 1;
+	public const uint k_unInt32PropertyTag = 2;
+	public const uint k_unUint64PropertyTag = 3;
+	public const uint k_unBoolPropertyTag = 4;
+	public const uint k_unStringPropertyTag = 5;
+	public const uint k_unHmdMatrix34PropertyTag = 20;
+	public const uint k_unHmdMatrix44PropertyTag = 21;
+	public const uint k_unHmdVector3PropertyTag = 22;
+	public const uint k_unHmdVector4PropertyTag = 23;
+	public const uint k_unHiddenAreaPropertyTag = 30;
+	public const uint k_unOpenVRInternalReserved_Start = 1000;
+	public const uint k_unOpenVRInternalReserved_End = 10000;
+	public const uint k_unMaxPropertyStringSize = 32768;
+	public const uint k_unControllerStateAxisCount = 5;
+	public const ulong k_ulOverlayHandleInvalid = 0;
+	public const uint k_unScreenshotHandleInvalid = 0;
+	public const string IVRSystem_Version = "IVRSystem_015";
+	public const string IVRExtendedDisplay_Version = "IVRExtendedDisplay_001";
+	public const string IVRTrackedCamera_Version = "IVRTrackedCamera_003";
+	public const uint k_unMaxApplicationKeyLength = 128;
+	public const string k_pch_MimeType_HomeApp = "vr/home";
+	public const string k_pch_MimeType_GameTheater = "vr/game_theater";
+	public const string IVRApplications_Version = "IVRApplications_006";
+	public const string IVRChaperone_Version = "IVRChaperone_003";
+	public const string IVRChaperoneSetup_Version = "IVRChaperoneSetup_005";
+	public const string IVRCompositor_Version = "IVRCompositor_020";
+	public const uint k_unVROverlayMaxKeyLength = 128;
+	public const uint k_unVROverlayMaxNameLength = 128;
+	public const uint k_unMaxOverlayCount = 64;
+	public const uint k_unMaxOverlayIntersectionMaskPrimitivesCount = 32;
+	public const string IVROverlay_Version = "IVROverlay_014";
+	public const string k_pch_Controller_Component_GDC2015 = "gdc2015";
+	public const string k_pch_Controller_Component_Base = "base";
+	public const string k_pch_Controller_Component_Tip = "tip";
+	public const string k_pch_Controller_Component_HandGrip = "handgrip";
+	public const string k_pch_Controller_Component_Status = "status";
+	public const string IVRRenderModels_Version = "IVRRenderModels_005";
+	public const uint k_unNotificationTextMaxSize = 256;
+	public const string IVRNotifications_Version = "IVRNotifications_002";
+	public const uint k_unMaxSettingsKeyLength = 128;
+	public const string IVRSettings_Version = "IVRSettings_002";
+	public const string k_pch_SteamVR_Section = "steamvr";
+	public const string k_pch_SteamVR_RequireHmd_String = "requireHmd";
+	public const string k_pch_SteamVR_ForcedDriverKey_String = "forcedDriver";
+	public const string k_pch_SteamVR_ForcedHmdKey_String = "forcedHmd";
+	public const string k_pch_SteamVR_DisplayDebug_Bool = "displayDebug";
+	public const string k_pch_SteamVR_DebugProcessPipe_String = "debugProcessPipe";
+	public const string k_pch_SteamVR_EnableDistortion_Bool = "enableDistortion";
+	public const string k_pch_SteamVR_DisplayDebugX_Int32 = "displayDebugX";
+	public const string k_pch_SteamVR_DisplayDebugY_Int32 = "displayDebugY";
+	public const string k_pch_SteamVR_SendSystemButtonToAllApps_Bool = "sendSystemButtonToAllApps";
+	public const string k_pch_SteamVR_LogLevel_Int32 = "loglevel";
+	public const string k_pch_SteamVR_IPD_Float = "ipd";
+	public const string k_pch_SteamVR_Background_String = "background";
+	public const string k_pch_SteamVR_BackgroundUseDomeProjection_Bool = "backgroundUseDomeProjection";
+	public const string k_pch_SteamVR_BackgroundCameraHeight_Float = "backgroundCameraHeight";
+	public const string k_pch_SteamVR_BackgroundDomeRadius_Float = "backgroundDomeRadius";
+	public const string k_pch_SteamVR_GridColor_String = "gridColor";
+	public const string k_pch_SteamVR_PlayAreaColor_String = "playAreaColor";
+	public const string k_pch_SteamVR_ShowStage_Bool = "showStage";
+	public const string k_pch_SteamVR_ActivateMultipleDrivers_Bool = "activateMultipleDrivers";
+	public const string k_pch_SteamVR_DirectMode_Bool = "directMode";
+	public const string k_pch_SteamVR_DirectModeEdidVid_Int32 = "directModeEdidVid";
+	public const string k_pch_SteamVR_DirectModeEdidPid_Int32 = "directModeEdidPid";
+	public const string k_pch_SteamVR_UsingSpeakers_Bool = "usingSpeakers";
+	public const string k_pch_SteamVR_SpeakersForwardYawOffsetDegrees_Float = "speakersForwardYawOffsetDegrees";
+	public const string k_pch_SteamVR_BaseStationPowerManagement_Bool = "basestationPowerManagement";
+	public const string k_pch_SteamVR_NeverKillProcesses_Bool = "neverKillProcesses";
+	public const string k_pch_SteamVR_RenderTargetMultiplier_Float = "renderTargetMultiplier";
+	public const string k_pch_SteamVR_AllowAsyncReprojection_Bool = "allowAsyncReprojection";
+	public const string k_pch_SteamVR_AllowReprojection_Bool = "allowInterleavedReprojection";
+	public const string k_pch_SteamVR_ForceReprojection_Bool = "forceReprojection";
+	public const string k_pch_SteamVR_ForceFadeOnBadTracking_Bool = "forceFadeOnBadTracking";
+	public const string k_pch_SteamVR_DefaultMirrorView_Int32 = "defaultMirrorView";
+	public const string k_pch_SteamVR_ShowMirrorView_Bool = "showMirrorView";
+	public const string k_pch_SteamVR_MirrorViewGeometry_String = "mirrorViewGeometry";
+	public const string k_pch_SteamVR_StartMonitorFromAppLaunch = "startMonitorFromAppLaunch";
+	public const string k_pch_SteamVR_StartCompositorFromAppLaunch_Bool = "startCompositorFromAppLaunch";
+	public const string k_pch_SteamVR_StartDashboardFromAppLaunch_Bool = "startDashboardFromAppLaunch";
+	public const string k_pch_SteamVR_StartOverlayAppsFromDashboard_Bool = "startOverlayAppsFromDashboard";
+	public const string k_pch_SteamVR_EnableHomeApp = "enableHomeApp";
+	public const string k_pch_SteamVR_SetInitialDefaultHomeApp = "setInitialDefaultHomeApp";
+	public const string k_pch_SteamVR_CycleBackgroundImageTimeSec_Int32 = "CycleBackgroundImageTimeSec";
+	public const string k_pch_SteamVR_RetailDemo_Bool = "retailDemo";
+	public const string k_pch_SteamVR_IpdOffset_Float = "ipdOffset";
+	public const string k_pch_Lighthouse_Section = "driver_lighthouse";
+	public const string k_pch_Lighthouse_DisableIMU_Bool = "disableimu";
+	public const string k_pch_Lighthouse_UseDisambiguation_String = "usedisambiguation";
+	public const string k_pch_Lighthouse_DisambiguationDebug_Int32 = "disambiguationdebug";
+	public const string k_pch_Lighthouse_PrimaryBasestation_Int32 = "primarybasestation";
+	public const string k_pch_Lighthouse_DBHistory_Bool = "dbhistory";
+	public const string k_pch_Null_Section = "driver_null";
+	public const string k_pch_Null_SerialNumber_String = "serialNumber";
+	public const string k_pch_Null_ModelNumber_String = "modelNumber";
+	public const string k_pch_Null_WindowX_Int32 = "windowX";
+	public const string k_pch_Null_WindowY_Int32 = "windowY";
+	public const string k_pch_Null_WindowWidth_Int32 = "windowWidth";
+	public const string k_pch_Null_WindowHeight_Int32 = "windowHeight";
+	public const string k_pch_Null_RenderWidth_Int32 = "renderWidth";
+	public const string k_pch_Null_RenderHeight_Int32 = "renderHeight";
+	public const string k_pch_Null_SecondsFromVsyncToPhotons_Float = "secondsFromVsyncToPhotons";
+	public const string k_pch_Null_DisplayFrequency_Float = "displayFrequency";
+	public const string k_pch_UserInterface_Section = "userinterface";
+	public const string k_pch_UserInterface_StatusAlwaysOnTop_Bool = "StatusAlwaysOnTop";
+	public const string k_pch_UserInterface_MinimizeToTray_Bool = "MinimizeToTray";
+	public const string k_pch_UserInterface_Screenshots_Bool = "screenshots";
+	public const string k_pch_UserInterface_ScreenshotType_Int = "screenshotType";
+	public const string k_pch_Notifications_Section = "notifications";
+	public const string k_pch_Notifications_DoNotDisturb_Bool = "DoNotDisturb";
+	public const string k_pch_Keyboard_Section = "keyboard";
+	public const string k_pch_Keyboard_TutorialCompletions = "TutorialCompletions";
+	public const string k_pch_Keyboard_ScaleX = "ScaleX";
+	public const string k_pch_Keyboard_ScaleY = "ScaleY";
+	public const string k_pch_Keyboard_OffsetLeftX = "OffsetLeftX";
+	public const string k_pch_Keyboard_OffsetRightX = "OffsetRightX";
+	public const string k_pch_Keyboard_OffsetY = "OffsetY";
+	public const string k_pch_Keyboard_Smoothing = "Smoothing";
+	public const string k_pch_Perf_Section = "perfcheck";
+	public const string k_pch_Perf_HeuristicActive_Bool = "heuristicActive";
+	public const string k_pch_Perf_NotifyInHMD_Bool = "warnInHMD";
+	public const string k_pch_Perf_NotifyOnlyOnce_Bool = "warnOnlyOnce";
+	public const string k_pch_Perf_AllowTimingStore_Bool = "allowTimingStore";
+	public const string k_pch_Perf_SaveTimingsOnExit_Bool = "saveTimingsOnExit";
+	public const string k_pch_Perf_TestData_Float = "perfTestData";
+	public const string k_pch_CollisionBounds_Section = "collisionBounds";
+	public const string k_pch_CollisionBounds_Style_Int32 = "CollisionBoundsStyle";
+	public const string k_pch_CollisionBounds_GroundPerimeterOn_Bool = "CollisionBoundsGroundPerimeterOn";
+	public const string k_pch_CollisionBounds_CenterMarkerOn_Bool = "CollisionBoundsCenterMarkerOn";
+	public const string k_pch_CollisionBounds_PlaySpaceOn_Bool = "CollisionBoundsPlaySpaceOn";
+	public const string k_pch_CollisionBounds_FadeDistance_Float = "CollisionBoundsFadeDistance";
+	public const string k_pch_CollisionBounds_ColorGammaR_Int32 = "CollisionBoundsColorGammaR";
+	public const string k_pch_CollisionBounds_ColorGammaG_Int32 = "CollisionBoundsColorGammaG";
+	public const string k_pch_CollisionBounds_ColorGammaB_Int32 = "CollisionBoundsColorGammaB";
+	public const string k_pch_CollisionBounds_ColorGammaA_Int32 = "CollisionBoundsColorGammaA";
+	public const string k_pch_Camera_Section = "camera";
+	public const string k_pch_Camera_EnableCamera_Bool = "enableCamera";
+	public const string k_pch_Camera_EnableCameraInDashboard_Bool = "enableCameraInDashboard";
+	public const string k_pch_Camera_EnableCameraForCollisionBounds_Bool = "enableCameraForCollisionBounds";
+	public const string k_pch_Camera_EnableCameraForRoomView_Bool = "enableCameraForRoomView";
+	public const string k_pch_Camera_BoundsColorGammaR_Int32 = "cameraBoundsColorGammaR";
+	public const string k_pch_Camera_BoundsColorGammaG_Int32 = "cameraBoundsColorGammaG";
+	public const string k_pch_Camera_BoundsColorGammaB_Int32 = "cameraBoundsColorGammaB";
+	public const string k_pch_Camera_BoundsColorGammaA_Int32 = "cameraBoundsColorGammaA";
+	public const string k_pch_Camera_BoundsStrength_Int32 = "cameraBoundsStrength";
+	public const string k_pch_audio_Section = "audio";
+	public const string k_pch_audio_OnPlaybackDevice_String = "onPlaybackDevice";
+	public const string k_pch_audio_OnRecordDevice_String = "onRecordDevice";
+	public const string k_pch_audio_OnPlaybackMirrorDevice_String = "onPlaybackMirrorDevice";
+	public const string k_pch_audio_OffPlaybackDevice_String = "offPlaybackDevice";
+	public const string k_pch_audio_OffRecordDevice_String = "offRecordDevice";
+	public const string k_pch_audio_VIVEHDMIGain = "viveHDMIGain";
+	public const string k_pch_Power_Section = "power";
+	public const string k_pch_Power_PowerOffOnExit_Bool = "powerOffOnExit";
+	public const string k_pch_Power_TurnOffScreensTimeout_Float = "turnOffScreensTimeout";
+	public const string k_pch_Power_TurnOffControllersTimeout_Float = "turnOffControllersTimeout";
+	public const string k_pch_Power_ReturnToWatchdogTimeout_Float = "returnToWatchdogTimeout";
+	public const string k_pch_Power_AutoLaunchSteamVROnButtonPress = "autoLaunchSteamVROnButtonPress";
+	public const string k_pch_Dashboard_Section = "dashboard";
+	public const string k_pch_Dashboard_EnableDashboard_Bool = "enableDashboard";
+	public const string k_pch_Dashboard_ArcadeMode_Bool = "arcadeMode";
+	public const string k_pch_modelskin_Section = "modelskins";
+	public const string k_pch_Driver_Enable_Bool = "enable";
+	public const string IVRScreenshots_Version = "IVRScreenshots_001";
+	public const string IVRResources_Version = "IVRResources_001";
+
+	static uint VRToken { get; set; }
+
+	const string FnTable_Prefix = "FnTable:";
+
+	class COpenVRContext
+	{
+		public COpenVRContext() { Clear(); }
+
+		public void Clear()
+		{
+			m_pVRSystem = null;
+			m_pVRChaperone = null;
+			m_pVRChaperoneSetup = null;
+			m_pVRCompositor = null;
+			m_pVROverlay = null;
+			m_pVRRenderModels = null;
+			m_pVRExtendedDisplay = null;
+			m_pVRSettings = null;
+			m_pVRApplications = null;
+			m_pVRScreenshots = null;
+			m_pVRTrackedCamera = null;
+		}
+
+		void CheckClear()
+		{
+			if (VRToken != GetInitToken())
+			{
+				Clear();
+				VRToken = GetInitToken();
+			}
+		}
+
+		public CVRSystem VRSystem()
+		{
+			CheckClear();
+			if (m_pVRSystem == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRSystem_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRSystem = new CVRSystem(pInterface);
+			}
+			return m_pVRSystem;
+		}
+
+		public CVRChaperone VRChaperone()
+		{
+			CheckClear();
+			if (m_pVRChaperone == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRChaperone_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRChaperone = new CVRChaperone(pInterface);
+			}
+			return m_pVRChaperone;
+		}
+
+		public CVRChaperoneSetup VRChaperoneSetup()
+		{
+			CheckClear();
+			if (m_pVRChaperoneSetup == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRChaperoneSetup_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRChaperoneSetup = new CVRChaperoneSetup(pInterface);
+			}
+			return m_pVRChaperoneSetup;
+		}
+
+		public CVRCompositor VRCompositor()
+		{
+			CheckClear();
+			if (m_pVRCompositor == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRCompositor_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRCompositor = new CVRCompositor(pInterface);
+			}
+			return m_pVRCompositor;
+		}
+
+		public CVROverlay VROverlay()
+		{
+			CheckClear();
+			if (m_pVROverlay == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVROverlay_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVROverlay = new CVROverlay(pInterface);
+			}
+			return m_pVROverlay;
+		}
+
+		public CVRRenderModels VRRenderModels()
+		{
+			CheckClear();
+			if (m_pVRRenderModels == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRRenderModels_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRRenderModels = new CVRRenderModels(pInterface);
+			}
+			return m_pVRRenderModels;
+		}
+
+		public CVRExtendedDisplay VRExtendedDisplay()
+		{
+			CheckClear();
+			if (m_pVRExtendedDisplay == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRExtendedDisplay_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRExtendedDisplay = new CVRExtendedDisplay(pInterface);
+			}
+			return m_pVRExtendedDisplay;
+		}
+
+		public CVRSettings VRSettings()
+		{
+			CheckClear();
+			if (m_pVRSettings == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRSettings_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRSettings = new CVRSettings(pInterface);
+			}
+			return m_pVRSettings;
+		}
+
+		public CVRApplications VRApplications()
+		{
+			CheckClear();
+			if (m_pVRApplications == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRApplications_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRApplications = new CVRApplications(pInterface);
+			}
+			return m_pVRApplications;
+		}
+
+		public CVRScreenshots VRScreenshots()
+		{
+			CheckClear();
+			if (m_pVRScreenshots == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRScreenshots_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRScreenshots = new CVRScreenshots(pInterface);
+			}
+			return m_pVRScreenshots;
+		}
+
+		public CVRTrackedCamera VRTrackedCamera()
+		{
+			CheckClear();
+			if (m_pVRTrackedCamera == null)
+			{
+				var eError = EVRInitError.None;
+				var pInterface = OpenVRInterop.GetGenericInterface(FnTable_Prefix+IVRTrackedCamera_Version, ref eError);
+				if (pInterface != IntPtr.Zero && eError == EVRInitError.None)
+					m_pVRTrackedCamera = new CVRTrackedCamera(pInterface);
+			}
+			return m_pVRTrackedCamera;
+		}
+
+		private CVRSystem m_pVRSystem;
+		private CVRChaperone m_pVRChaperone;
+		private CVRChaperoneSetup m_pVRChaperoneSetup;
+		private CVRCompositor m_pVRCompositor;
+		private CVROverlay m_pVROverlay;
+		private CVRRenderModels m_pVRRenderModels;
+		private CVRExtendedDisplay m_pVRExtendedDisplay;
+		private CVRSettings m_pVRSettings;
+		private CVRApplications m_pVRApplications;
+		private CVRScreenshots m_pVRScreenshots;
+		private CVRTrackedCamera m_pVRTrackedCamera;
+	};
+
+	private static COpenVRContext _OpenVRInternal_ModuleContext = null;
+	static COpenVRContext OpenVRInternal_ModuleContext
+	{
+		get
+		{
+			if (_OpenVRInternal_ModuleContext == null)
+				_OpenVRInternal_ModuleContext = new COpenVRContext();
+			return _OpenVRInternal_ModuleContext;
+		}
+	}
+
+	public static CVRSystem System { get { return OpenVRInternal_ModuleContext.VRSystem(); } }
+	public static CVRChaperone Chaperone { get { return OpenVRInternal_ModuleContext.VRChaperone(); } }
+	public static CVRChaperoneSetup ChaperoneSetup { get { return OpenVRInternal_ModuleContext.VRChaperoneSetup(); } }
+	public static CVRCompositor Compositor { get { return OpenVRInternal_ModuleContext.VRCompositor(); } }
+	public static CVROverlay Overlay { get { return OpenVRInternal_ModuleContext.VROverlay(); } }
+	public static CVRRenderModels RenderModels { get { return OpenVRInternal_ModuleContext.VRRenderModels(); } }
+	public static CVRExtendedDisplay ExtendedDisplay { get { return OpenVRInternal_ModuleContext.VRExtendedDisplay(); } }
+	public static CVRSettings Settings { get { return OpenVRInternal_ModuleContext.VRSettings(); } }
+	public static CVRApplications Applications { get { return OpenVRInternal_ModuleContext.VRApplications(); } }
+	public static CVRScreenshots Screenshots { get { return OpenVRInternal_ModuleContext.VRScreenshots(); } }
+	public static CVRTrackedCamera TrackedCamera { get { return OpenVRInternal_ModuleContext.VRTrackedCamera(); } }
+
+	/** Finds the active installation of vrclient.dll and initializes it */
+	public static CVRSystem Init(ref EVRInitError peError, EVRApplicationType eApplicationType = EVRApplicationType.VRApplication_Scene)
+	{
+		VRToken = InitInternal(ref peError, eApplicationType);
+		OpenVRInternal_ModuleContext.Clear();
+
+		if (peError != EVRInitError.None)
+			return null;
+
+		bool bInterfaceValid = IsInterfaceVersionValid(IVRSystem_Version);
+		if (!bInterfaceValid)
+		{
+			ShutdownInternal();
+			peError = EVRInitError.Init_InterfaceNotFound;
+			return null;
+		}
+
+		return OpenVR.System;
+	}
+
+	/** unloads vrclient.dll. Any interface pointers from the interface are
+	* invalid after this point */
+	public static void Shutdown()
+	{
+		ShutdownInternal();
+	}
+
+}
+
+
+
+}
+
diff --git a/third_party/openvr/src/headers/openvr_api.json b/third_party/openvr/src/headers/openvr_api.json
new file mode 100644
index 0000000..688e137
--- /dev/null
+++ b/third_party/openvr/src/headers/openvr_api.json
@@ -0,0 +1,3789 @@
+{"typedefs":[{"typedef": "vr::glSharedTextureHandle_t","type": "void *"}
+,{"typedef": "vr::glInt_t","type": "int32_t"}
+,{"typedef": "vr::glUInt_t","type": "uint32_t"}
+,{"typedef": "vr::SharedTextureHandle_t","type": "uint64_t"}
+,{"typedef": "vr::TrackedDeviceIndex_t","type": "uint32_t"}
+,{"typedef": "vr::PropertyContainerHandle_t","type": "uint64_t"}
+,{"typedef": "vr::PropertyTypeTag_t","type": "uint32_t"}
+,{"typedef": "vr::VREvent_Data_t","type": "union VREvent_Data_t"}
+,{"typedef": "vr::VRControllerState_t","type": "struct vr::VRControllerState001_t"}
+,{"typedef": "vr::VROverlayHandle_t","type": "uint64_t"}
+,{"typedef": "vr::TrackedCameraHandle_t","type": "uint64_t"}
+,{"typedef": "vr::ScreenshotHandle_t","type": "uint32_t"}
+,{"typedef": "vr::VROverlayIntersectionMaskPrimitive_Data_t","type": "union VROverlayIntersectionMaskPrimitive_Data_t"}
+,{"typedef": "vr::VRComponentProperties","type": "uint32_t"}
+,{"typedef": "vr::TextureID_t","type": "int32_t"}
+,{"typedef": "vr::VRNotificationId","type": "uint32_t"}
+,{"typedef": "vr::HmdError","type": "enum vr::EVRInitError"}
+,{"typedef": "vr::Hmd_Eye","type": "enum vr::EVREye"}
+,{"typedef": "vr::ColorSpace","type": "enum vr::EColorSpace"}
+,{"typedef": "vr::HmdTrackingResult","type": "enum vr::ETrackingResult"}
+,{"typedef": "vr::TrackedDeviceClass","type": "enum vr::ETrackedDeviceClass"}
+,{"typedef": "vr::TrackingUniverseOrigin","type": "enum vr::ETrackingUniverseOrigin"}
+,{"typedef": "vr::TrackedDeviceProperty","type": "enum vr::ETrackedDeviceProperty"}
+,{"typedef": "vr::TrackedPropertyError","type": "enum vr::ETrackedPropertyError"}
+,{"typedef": "vr::VRSubmitFlags_t","type": "enum vr::EVRSubmitFlags"}
+,{"typedef": "vr::VRState_t","type": "enum vr::EVRState"}
+,{"typedef": "vr::CollisionBoundsStyle_t","type": "enum vr::ECollisionBoundsStyle"}
+,{"typedef": "vr::VROverlayError","type": "enum vr::EVROverlayError"}
+,{"typedef": "vr::VRFirmwareError","type": "enum vr::EVRFirmwareError"}
+,{"typedef": "vr::VRCompositorError","type": "enum vr::EVRCompositorError"}
+,{"typedef": "vr::VRScreenshotsError","type": "enum vr::EVRScreenshotError"}
+],
+"enums":[
+	{"enumname": "vr::EVREye","values": [ 
+	{"name": "Eye_Left","value": "0"}
+	,{"name": "Eye_Right","value": "1"}
+]}
+,	{"enumname": "vr::ETextureType","values": [ 
+	{"name": "TextureType_DirectX","value": "0"}
+	,{"name": "TextureType_OpenGL","value": "1"}
+	,{"name": "TextureType_Vulkan","value": "2"}
+	,{"name": "TextureType_IOSurface","value": "3"}
+	,{"name": "TextureType_DirectX12","value": "4"}
+]}
+,	{"enumname": "vr::EColorSpace","values": [ 
+	{"name": "ColorSpace_Auto","value": "0"}
+	,{"name": "ColorSpace_Gamma","value": "1"}
+	,{"name": "ColorSpace_Linear","value": "2"}
+]}
+,	{"enumname": "vr::ETrackingResult","values": [ 
+	{"name": "TrackingResult_Uninitialized","value": "1"}
+	,{"name": "TrackingResult_Calibrating_InProgress","value": "100"}
+	,{"name": "TrackingResult_Calibrating_OutOfRange","value": "101"}
+	,{"name": "TrackingResult_Running_OK","value": "200"}
+	,{"name": "TrackingResult_Running_OutOfRange","value": "201"}
+]}
+,	{"enumname": "vr::ETrackedDeviceClass","values": [ 
+	{"name": "TrackedDeviceClass_Invalid","value": "0"}
+	,{"name": "TrackedDeviceClass_HMD","value": "1"}
+	,{"name": "TrackedDeviceClass_Controller","value": "2"}
+	,{"name": "TrackedDeviceClass_GenericTracker","value": "3"}
+	,{"name": "TrackedDeviceClass_TrackingReference","value": "4"}
+]}
+,	{"enumname": "vr::ETrackedControllerRole","values": [ 
+	{"name": "TrackedControllerRole_Invalid","value": "0"}
+	,{"name": "TrackedControllerRole_LeftHand","value": "1"}
+	,{"name": "TrackedControllerRole_RightHand","value": "2"}
+]}
+,	{"enumname": "vr::ETrackingUniverseOrigin","values": [ 
+	{"name": "TrackingUniverseSeated","value": "0"}
+	,{"name": "TrackingUniverseStanding","value": "1"}
+	,{"name": "TrackingUniverseRawAndUncalibrated","value": "2"}
+]}
+,	{"enumname": "vr::ETrackedDeviceProperty","values": [ 
+	{"name": "Prop_Invalid","value": "0"}
+	,{"name": "Prop_TrackingSystemName_String","value": "1000"}
+	,{"name": "Prop_ModelNumber_String","value": "1001"}
+	,{"name": "Prop_SerialNumber_String","value": "1002"}
+	,{"name": "Prop_RenderModelName_String","value": "1003"}
+	,{"name": "Prop_WillDriftInYaw_Bool","value": "1004"}
+	,{"name": "Prop_ManufacturerName_String","value": "1005"}
+	,{"name": "Prop_TrackingFirmwareVersion_String","value": "1006"}
+	,{"name": "Prop_HardwareRevision_String","value": "1007"}
+	,{"name": "Prop_AllWirelessDongleDescriptions_String","value": "1008"}
+	,{"name": "Prop_ConnectedWirelessDongle_String","value": "1009"}
+	,{"name": "Prop_DeviceIsWireless_Bool","value": "1010"}
+	,{"name": "Prop_DeviceIsCharging_Bool","value": "1011"}
+	,{"name": "Prop_DeviceBatteryPercentage_Float","value": "1012"}
+	,{"name": "Prop_StatusDisplayTransform_Matrix34","value": "1013"}
+	,{"name": "Prop_Firmware_UpdateAvailable_Bool","value": "1014"}
+	,{"name": "Prop_Firmware_ManualUpdate_Bool","value": "1015"}
+	,{"name": "Prop_Firmware_ManualUpdateURL_String","value": "1016"}
+	,{"name": "Prop_HardwareRevision_Uint64","value": "1017"}
+	,{"name": "Prop_FirmwareVersion_Uint64","value": "1018"}
+	,{"name": "Prop_FPGAVersion_Uint64","value": "1019"}
+	,{"name": "Prop_VRCVersion_Uint64","value": "1020"}
+	,{"name": "Prop_RadioVersion_Uint64","value": "1021"}
+	,{"name": "Prop_DongleVersion_Uint64","value": "1022"}
+	,{"name": "Prop_BlockServerShutdown_Bool","value": "1023"}
+	,{"name": "Prop_CanUnifyCoordinateSystemWithHmd_Bool","value": "1024"}
+	,{"name": "Prop_ContainsProximitySensor_Bool","value": "1025"}
+	,{"name": "Prop_DeviceProvidesBatteryStatus_Bool","value": "1026"}
+	,{"name": "Prop_DeviceCanPowerOff_Bool","value": "1027"}
+	,{"name": "Prop_Firmware_ProgrammingTarget_String","value": "1028"}
+	,{"name": "Prop_DeviceClass_Int32","value": "1029"}
+	,{"name": "Prop_HasCamera_Bool","value": "1030"}
+	,{"name": "Prop_DriverVersion_String","value": "1031"}
+	,{"name": "Prop_Firmware_ForceUpdateRequired_Bool","value": "1032"}
+	,{"name": "Prop_ViveSystemButtonFixRequired_Bool","value": "1033"}
+	,{"name": "Prop_ParentDriver_Uint64","value": "1034"}
+	,{"name": "Prop_ReportsTimeSinceVSync_Bool","value": "2000"}
+	,{"name": "Prop_SecondsFromVsyncToPhotons_Float","value": "2001"}
+	,{"name": "Prop_DisplayFrequency_Float","value": "2002"}
+	,{"name": "Prop_UserIpdMeters_Float","value": "2003"}
+	,{"name": "Prop_CurrentUniverseId_Uint64","value": "2004"}
+	,{"name": "Prop_PreviousUniverseId_Uint64","value": "2005"}
+	,{"name": "Prop_DisplayFirmwareVersion_Uint64","value": "2006"}
+	,{"name": "Prop_IsOnDesktop_Bool","value": "2007"}
+	,{"name": "Prop_DisplayMCType_Int32","value": "2008"}
+	,{"name": "Prop_DisplayMCOffset_Float","value": "2009"}
+	,{"name": "Prop_DisplayMCScale_Float","value": "2010"}
+	,{"name": "Prop_EdidVendorID_Int32","value": "2011"}
+	,{"name": "Prop_DisplayMCImageLeft_String","value": "2012"}
+	,{"name": "Prop_DisplayMCImageRight_String","value": "2013"}
+	,{"name": "Prop_DisplayGCBlackClamp_Float","value": "2014"}
+	,{"name": "Prop_EdidProductID_Int32","value": "2015"}
+	,{"name": "Prop_CameraToHeadTransform_Matrix34","value": "2016"}
+	,{"name": "Prop_DisplayGCType_Int32","value": "2017"}
+	,{"name": "Prop_DisplayGCOffset_Float","value": "2018"}
+	,{"name": "Prop_DisplayGCScale_Float","value": "2019"}
+	,{"name": "Prop_DisplayGCPrescale_Float","value": "2020"}
+	,{"name": "Prop_DisplayGCImage_String","value": "2021"}
+	,{"name": "Prop_LensCenterLeftU_Float","value": "2022"}
+	,{"name": "Prop_LensCenterLeftV_Float","value": "2023"}
+	,{"name": "Prop_LensCenterRightU_Float","value": "2024"}
+	,{"name": "Prop_LensCenterRightV_Float","value": "2025"}
+	,{"name": "Prop_UserHeadToEyeDepthMeters_Float","value": "2026"}
+	,{"name": "Prop_CameraFirmwareVersion_Uint64","value": "2027"}
+	,{"name": "Prop_CameraFirmwareDescription_String","value": "2028"}
+	,{"name": "Prop_DisplayFPGAVersion_Uint64","value": "2029"}
+	,{"name": "Prop_DisplayBootloaderVersion_Uint64","value": "2030"}
+	,{"name": "Prop_DisplayHardwareVersion_Uint64","value": "2031"}
+	,{"name": "Prop_AudioFirmwareVersion_Uint64","value": "2032"}
+	,{"name": "Prop_CameraCompatibilityMode_Int32","value": "2033"}
+	,{"name": "Prop_ScreenshotHorizontalFieldOfViewDegrees_Float","value": "2034"}
+	,{"name": "Prop_ScreenshotVerticalFieldOfViewDegrees_Float","value": "2035"}
+	,{"name": "Prop_DisplaySuppressed_Bool","value": "2036"}
+	,{"name": "Prop_DisplayAllowNightMode_Bool","value": "2037"}
+	,{"name": "Prop_DisplayMCImageWidth_Int32","value": "2038"}
+	,{"name": "Prop_DisplayMCImageHeight_Int32","value": "2039"}
+	,{"name": "Prop_DisplayMCImageNumChannels_Int32","value": "2040"}
+	,{"name": "Prop_DisplayMCImageData_Binary","value": "2041"}
+	,{"name": "Prop_UsesDriverDirectMode_Bool","value": "2042"}
+	,{"name": "Prop_AttachedDeviceId_String","value": "3000"}
+	,{"name": "Prop_SupportedButtons_Uint64","value": "3001"}
+	,{"name": "Prop_Axis0Type_Int32","value": "3002"}
+	,{"name": "Prop_Axis1Type_Int32","value": "3003"}
+	,{"name": "Prop_Axis2Type_Int32","value": "3004"}
+	,{"name": "Prop_Axis3Type_Int32","value": "3005"}
+	,{"name": "Prop_Axis4Type_Int32","value": "3006"}
+	,{"name": "Prop_ControllerRoleHint_Int32","value": "3007"}
+	,{"name": "Prop_FieldOfViewLeftDegrees_Float","value": "4000"}
+	,{"name": "Prop_FieldOfViewRightDegrees_Float","value": "4001"}
+	,{"name": "Prop_FieldOfViewTopDegrees_Float","value": "4002"}
+	,{"name": "Prop_FieldOfViewBottomDegrees_Float","value": "4003"}
+	,{"name": "Prop_TrackingRangeMinimumMeters_Float","value": "4004"}
+	,{"name": "Prop_TrackingRangeMaximumMeters_Float","value": "4005"}
+	,{"name": "Prop_ModeLabel_String","value": "4006"}
+	,{"name": "Prop_IconPathName_String","value": "5000"}
+	,{"name": "Prop_NamedIconPathDeviceOff_String","value": "5001"}
+	,{"name": "Prop_NamedIconPathDeviceSearching_String","value": "5002"}
+	,{"name": "Prop_NamedIconPathDeviceSearchingAlert_String","value": "5003"}
+	,{"name": "Prop_NamedIconPathDeviceReady_String","value": "5004"}
+	,{"name": "Prop_NamedIconPathDeviceReadyAlert_String","value": "5005"}
+	,{"name": "Prop_NamedIconPathDeviceNotReady_String","value": "5006"}
+	,{"name": "Prop_NamedIconPathDeviceStandby_String","value": "5007"}
+	,{"name": "Prop_NamedIconPathDeviceAlertLow_String","value": "5008"}
+	,{"name": "Prop_DisplayHiddenArea_Binary_Start","value": "5100"}
+	,{"name": "Prop_DisplayHiddenArea_Binary_End","value": "5150"}
+	,{"name": "Prop_UserConfigPath_String","value": "6000"}
+	,{"name": "Prop_InstallPath_String","value": "6001"}
+	,{"name": "Prop_VendorSpecific_Reserved_Start","value": "10000"}
+	,{"name": "Prop_VendorSpecific_Reserved_End","value": "10999"}
+]}
+,	{"enumname": "vr::ETrackedPropertyError","values": [ 
+	{"name": "TrackedProp_Success","value": "0"}
+	,{"name": "TrackedProp_WrongDataType","value": "1"}
+	,{"name": "TrackedProp_WrongDeviceClass","value": "2"}
+	,{"name": "TrackedProp_BufferTooSmall","value": "3"}
+	,{"name": "TrackedProp_UnknownProperty","value": "4"}
+	,{"name": "TrackedProp_InvalidDevice","value": "5"}
+	,{"name": "TrackedProp_CouldNotContactServer","value": "6"}
+	,{"name": "TrackedProp_ValueNotProvidedByDevice","value": "7"}
+	,{"name": "TrackedProp_StringExceedsMaximumLength","value": "8"}
+	,{"name": "TrackedProp_NotYetAvailable","value": "9"}
+	,{"name": "TrackedProp_PermissionDenied","value": "10"}
+	,{"name": "TrackedProp_InvalidOperation","value": "11"}
+]}
+,	{"enumname": "vr::EVRSubmitFlags","values": [ 
+	{"name": "Submit_Default","value": "0"}
+	,{"name": "Submit_LensDistortionAlreadyApplied","value": "1"}
+	,{"name": "Submit_GlRenderBuffer","value": "2"}
+	,{"name": "Submit_Reserved","value": "4"}
+]}
+,	{"enumname": "vr::EVRState","values": [ 
+	{"name": "VRState_Undefined","value": "-1"}
+	,{"name": "VRState_Off","value": "0"}
+	,{"name": "VRState_Searching","value": "1"}
+	,{"name": "VRState_Searching_Alert","value": "2"}
+	,{"name": "VRState_Ready","value": "3"}
+	,{"name": "VRState_Ready_Alert","value": "4"}
+	,{"name": "VRState_NotReady","value": "5"}
+	,{"name": "VRState_Standby","value": "6"}
+	,{"name": "VRState_Ready_Alert_Low","value": "7"}
+]}
+,	{"enumname": "vr::EVREventType","values": [ 
+	{"name": "VREvent_None","value": "0"}
+	,{"name": "VREvent_TrackedDeviceActivated","value": "100"}
+	,{"name": "VREvent_TrackedDeviceDeactivated","value": "101"}
+	,{"name": "VREvent_TrackedDeviceUpdated","value": "102"}
+	,{"name": "VREvent_TrackedDeviceUserInteractionStarted","value": "103"}
+	,{"name": "VREvent_TrackedDeviceUserInteractionEnded","value": "104"}
+	,{"name": "VREvent_IpdChanged","value": "105"}
+	,{"name": "VREvent_EnterStandbyMode","value": "106"}
+	,{"name": "VREvent_LeaveStandbyMode","value": "107"}
+	,{"name": "VREvent_TrackedDeviceRoleChanged","value": "108"}
+	,{"name": "VREvent_WatchdogWakeUpRequested","value": "109"}
+	,{"name": "VREvent_LensDistortionChanged","value": "110"}
+	,{"name": "VREvent_PropertyChanged","value": "111"}
+	,{"name": "VREvent_ButtonPress","value": "200"}
+	,{"name": "VREvent_ButtonUnpress","value": "201"}
+	,{"name": "VREvent_ButtonTouch","value": "202"}
+	,{"name": "VREvent_ButtonUntouch","value": "203"}
+	,{"name": "VREvent_MouseMove","value": "300"}
+	,{"name": "VREvent_MouseButtonDown","value": "301"}
+	,{"name": "VREvent_MouseButtonUp","value": "302"}
+	,{"name": "VREvent_FocusEnter","value": "303"}
+	,{"name": "VREvent_FocusLeave","value": "304"}
+	,{"name": "VREvent_Scroll","value": "305"}
+	,{"name": "VREvent_TouchPadMove","value": "306"}
+	,{"name": "VREvent_OverlayFocusChanged","value": "307"}
+	,{"name": "VREvent_InputFocusCaptured","value": "400"}
+	,{"name": "VREvent_InputFocusReleased","value": "401"}
+	,{"name": "VREvent_SceneFocusLost","value": "402"}
+	,{"name": "VREvent_SceneFocusGained","value": "403"}
+	,{"name": "VREvent_SceneApplicationChanged","value": "404"}
+	,{"name": "VREvent_SceneFocusChanged","value": "405"}
+	,{"name": "VREvent_InputFocusChanged","value": "406"}
+	,{"name": "VREvent_SceneApplicationSecondaryRenderingStarted","value": "407"}
+	,{"name": "VREvent_HideRenderModels","value": "410"}
+	,{"name": "VREvent_ShowRenderModels","value": "411"}
+	,{"name": "VREvent_OverlayShown","value": "500"}
+	,{"name": "VREvent_OverlayHidden","value": "501"}
+	,{"name": "VREvent_DashboardActivated","value": "502"}
+	,{"name": "VREvent_DashboardDeactivated","value": "503"}
+	,{"name": "VREvent_DashboardThumbSelected","value": "504"}
+	,{"name": "VREvent_DashboardRequested","value": "505"}
+	,{"name": "VREvent_ResetDashboard","value": "506"}
+	,{"name": "VREvent_RenderToast","value": "507"}
+	,{"name": "VREvent_ImageLoaded","value": "508"}
+	,{"name": "VREvent_ShowKeyboard","value": "509"}
+	,{"name": "VREvent_HideKeyboard","value": "510"}
+	,{"name": "VREvent_OverlayGamepadFocusGained","value": "511"}
+	,{"name": "VREvent_OverlayGamepadFocusLost","value": "512"}
+	,{"name": "VREvent_OverlaySharedTextureChanged","value": "513"}
+	,{"name": "VREvent_DashboardGuideButtonDown","value": "514"}
+	,{"name": "VREvent_DashboardGuideButtonUp","value": "515"}
+	,{"name": "VREvent_ScreenshotTriggered","value": "516"}
+	,{"name": "VREvent_ImageFailed","value": "517"}
+	,{"name": "VREvent_DashboardOverlayCreated","value": "518"}
+	,{"name": "VREvent_RequestScreenshot","value": "520"}
+	,{"name": "VREvent_ScreenshotTaken","value": "521"}
+	,{"name": "VREvent_ScreenshotFailed","value": "522"}
+	,{"name": "VREvent_SubmitScreenshotToDashboard","value": "523"}
+	,{"name": "VREvent_ScreenshotProgressToDashboard","value": "524"}
+	,{"name": "VREvent_PrimaryDashboardDeviceChanged","value": "525"}
+	,{"name": "VREvent_Notification_Shown","value": "600"}
+	,{"name": "VREvent_Notification_Hidden","value": "601"}
+	,{"name": "VREvent_Notification_BeginInteraction","value": "602"}
+	,{"name": "VREvent_Notification_Destroyed","value": "603"}
+	,{"name": "VREvent_Quit","value": "700"}
+	,{"name": "VREvent_ProcessQuit","value": "701"}
+	,{"name": "VREvent_QuitAborted_UserPrompt","value": "702"}
+	,{"name": "VREvent_QuitAcknowledged","value": "703"}
+	,{"name": "VREvent_DriverRequestedQuit","value": "704"}
+	,{"name": "VREvent_ChaperoneDataHasChanged","value": "800"}
+	,{"name": "VREvent_ChaperoneUniverseHasChanged","value": "801"}
+	,{"name": "VREvent_ChaperoneTempDataHasChanged","value": "802"}
+	,{"name": "VREvent_ChaperoneSettingsHaveChanged","value": "803"}
+	,{"name": "VREvent_SeatedZeroPoseReset","value": "804"}
+	,{"name": "VREvent_AudioSettingsHaveChanged","value": "820"}
+	,{"name": "VREvent_BackgroundSettingHasChanged","value": "850"}
+	,{"name": "VREvent_CameraSettingsHaveChanged","value": "851"}
+	,{"name": "VREvent_ReprojectionSettingHasChanged","value": "852"}
+	,{"name": "VREvent_ModelSkinSettingsHaveChanged","value": "853"}
+	,{"name": "VREvent_EnvironmentSettingsHaveChanged","value": "854"}
+	,{"name": "VREvent_PowerSettingsHaveChanged","value": "855"}
+	,{"name": "VREvent_StatusUpdate","value": "900"}
+	,{"name": "VREvent_MCImageUpdated","value": "1000"}
+	,{"name": "VREvent_FirmwareUpdateStarted","value": "1100"}
+	,{"name": "VREvent_FirmwareUpdateFinished","value": "1101"}
+	,{"name": "VREvent_KeyboardClosed","value": "1200"}
+	,{"name": "VREvent_KeyboardCharInput","value": "1201"}
+	,{"name": "VREvent_KeyboardDone","value": "1202"}
+	,{"name": "VREvent_ApplicationTransitionStarted","value": "1300"}
+	,{"name": "VREvent_ApplicationTransitionAborted","value": "1301"}
+	,{"name": "VREvent_ApplicationTransitionNewAppStarted","value": "1302"}
+	,{"name": "VREvent_ApplicationListUpdated","value": "1303"}
+	,{"name": "VREvent_ApplicationMimeTypeLoad","value": "1304"}
+	,{"name": "VREvent_ApplicationTransitionNewAppLaunchComplete","value": "1305"}
+	,{"name": "VREvent_Compositor_MirrorWindowShown","value": "1400"}
+	,{"name": "VREvent_Compositor_MirrorWindowHidden","value": "1401"}
+	,{"name": "VREvent_Compositor_ChaperoneBoundsShown","value": "1410"}
+	,{"name": "VREvent_Compositor_ChaperoneBoundsHidden","value": "1411"}
+	,{"name": "VREvent_TrackedCamera_StartVideoStream","value": "1500"}
+	,{"name": "VREvent_TrackedCamera_StopVideoStream","value": "1501"}
+	,{"name": "VREvent_TrackedCamera_PauseVideoStream","value": "1502"}
+	,{"name": "VREvent_TrackedCamera_ResumeVideoStream","value": "1503"}
+	,{"name": "VREvent_TrackedCamera_EditingSurface","value": "1550"}
+	,{"name": "VREvent_PerformanceTest_EnableCapture","value": "1600"}
+	,{"name": "VREvent_PerformanceTest_DisableCapture","value": "1601"}
+	,{"name": "VREvent_PerformanceTest_FidelityLevel","value": "1602"}
+	,{"name": "VREvent_MessageOverlay_Closed","value": "1650"}
+	,{"name": "VREvent_VendorSpecific_Reserved_Start","value": "10000"}
+	,{"name": "VREvent_VendorSpecific_Reserved_End","value": "19999"}
+]}
+,	{"enumname": "vr::EDeviceActivityLevel","values": [ 
+	{"name": "k_EDeviceActivityLevel_Unknown","value": "-1"}
+	,{"name": "k_EDeviceActivityLevel_Idle","value": "0"}
+	,{"name": "k_EDeviceActivityLevel_UserInteraction","value": "1"}
+	,{"name": "k_EDeviceActivityLevel_UserInteraction_Timeout","value": "2"}
+	,{"name": "k_EDeviceActivityLevel_Standby","value": "3"}
+]}
+,	{"enumname": "vr::EVRButtonId","values": [ 
+	{"name": "k_EButton_System","value": "0"}
+	,{"name": "k_EButton_ApplicationMenu","value": "1"}
+	,{"name": "k_EButton_Grip","value": "2"}
+	,{"name": "k_EButton_DPad_Left","value": "3"}
+	,{"name": "k_EButton_DPad_Up","value": "4"}
+	,{"name": "k_EButton_DPad_Right","value": "5"}
+	,{"name": "k_EButton_DPad_Down","value": "6"}
+	,{"name": "k_EButton_A","value": "7"}
+	,{"name": "k_EButton_ProximitySensor","value": "31"}
+	,{"name": "k_EButton_Axis0","value": "32"}
+	,{"name": "k_EButton_Axis1","value": "33"}
+	,{"name": "k_EButton_Axis2","value": "34"}
+	,{"name": "k_EButton_Axis3","value": "35"}
+	,{"name": "k_EButton_Axis4","value": "36"}
+	,{"name": "k_EButton_SteamVR_Touchpad","value": "32"}
+	,{"name": "k_EButton_SteamVR_Trigger","value": "33"}
+	,{"name": "k_EButton_Dashboard_Back","value": "2"}
+	,{"name": "k_EButton_Max","value": "64"}
+]}
+,	{"enumname": "vr::EVRMouseButton","values": [ 
+	{"name": "VRMouseButton_Left","value": "1"}
+	,{"name": "VRMouseButton_Right","value": "2"}
+	,{"name": "VRMouseButton_Middle","value": "4"}
+]}
+,	{"enumname": "vr::EHiddenAreaMeshType","values": [ 
+	{"name": "k_eHiddenAreaMesh_Standard","value": "0"}
+	,{"name": "k_eHiddenAreaMesh_Inverse","value": "1"}
+	,{"name": "k_eHiddenAreaMesh_LineLoop","value": "2"}
+	,{"name": "k_eHiddenAreaMesh_Max","value": "3"}
+]}
+,	{"enumname": "vr::EVRControllerAxisType","values": [ 
+	{"name": "k_eControllerAxis_None","value": "0"}
+	,{"name": "k_eControllerAxis_TrackPad","value": "1"}
+	,{"name": "k_eControllerAxis_Joystick","value": "2"}
+	,{"name": "k_eControllerAxis_Trigger","value": "3"}
+]}
+,	{"enumname": "vr::EVRControllerEventOutputType","values": [ 
+	{"name": "ControllerEventOutput_OSEvents","value": "0"}
+	,{"name": "ControllerEventOutput_VREvents","value": "1"}
+]}
+,	{"enumname": "vr::ECollisionBoundsStyle","values": [ 
+	{"name": "COLLISION_BOUNDS_STYLE_BEGINNER","value": "0"}
+	,{"name": "COLLISION_BOUNDS_STYLE_INTERMEDIATE","value": "1"}
+	,{"name": "COLLISION_BOUNDS_STYLE_SQUARES","value": "2"}
+	,{"name": "COLLISION_BOUNDS_STYLE_ADVANCED","value": "3"}
+	,{"name": "COLLISION_BOUNDS_STYLE_NONE","value": "4"}
+	,{"name": "COLLISION_BOUNDS_STYLE_COUNT","value": "5"}
+]}
+,	{"enumname": "vr::EVROverlayError","values": [ 
+	{"name": "VROverlayError_None","value": "0"}
+	,{"name": "VROverlayError_UnknownOverlay","value": "10"}
+	,{"name": "VROverlayError_InvalidHandle","value": "11"}
+	,{"name": "VROverlayError_PermissionDenied","value": "12"}
+	,{"name": "VROverlayError_OverlayLimitExceeded","value": "13"}
+	,{"name": "VROverlayError_WrongVisibilityType","value": "14"}
+	,{"name": "VROverlayError_KeyTooLong","value": "15"}
+	,{"name": "VROverlayError_NameTooLong","value": "16"}
+	,{"name": "VROverlayError_KeyInUse","value": "17"}
+	,{"name": "VROverlayError_WrongTransformType","value": "18"}
+	,{"name": "VROverlayError_InvalidTrackedDevice","value": "19"}
+	,{"name": "VROverlayError_InvalidParameter","value": "20"}
+	,{"name": "VROverlayError_ThumbnailCantBeDestroyed","value": "21"}
+	,{"name": "VROverlayError_ArrayTooSmall","value": "22"}
+	,{"name": "VROverlayError_RequestFailed","value": "23"}
+	,{"name": "VROverlayError_InvalidTexture","value": "24"}
+	,{"name": "VROverlayError_UnableToLoadFile","value": "25"}
+	,{"name": "VROverlayError_KeyboardAlreadyInUse","value": "26"}
+	,{"name": "VROverlayError_NoNeighbor","value": "27"}
+	,{"name": "VROverlayError_TooManyMaskPrimitives","value": "29"}
+	,{"name": "VROverlayError_BadMaskPrimitive","value": "30"}
+]}
+,	{"enumname": "vr::EVRApplicationType","values": [ 
+	{"name": "VRApplication_Other","value": "0"}
+	,{"name": "VRApplication_Scene","value": "1"}
+	,{"name": "VRApplication_Overlay","value": "2"}
+	,{"name": "VRApplication_Background","value": "3"}
+	,{"name": "VRApplication_Utility","value": "4"}
+	,{"name": "VRApplication_VRMonitor","value": "5"}
+	,{"name": "VRApplication_SteamWatchdog","value": "6"}
+	,{"name": "VRApplication_Max","value": "7"}
+]}
+,	{"enumname": "vr::EVRFirmwareError","values": [ 
+	{"name": "VRFirmwareError_None","value": "0"}
+	,{"name": "VRFirmwareError_Success","value": "1"}
+	,{"name": "VRFirmwareError_Fail","value": "2"}
+]}
+,	{"enumname": "vr::EVRNotificationError","values": [ 
+	{"name": "VRNotificationError_OK","value": "0"}
+	,{"name": "VRNotificationError_InvalidNotificationId","value": "100"}
+	,{"name": "VRNotificationError_NotificationQueueFull","value": "101"}
+	,{"name": "VRNotificationError_InvalidOverlayHandle","value": "102"}
+	,{"name": "VRNotificationError_SystemWithUserValueAlreadyExists","value": "103"}
+]}
+,	{"enumname": "vr::EVRInitError","values": [ 
+	{"name": "VRInitError_None","value": "0"}
+	,{"name": "VRInitError_Unknown","value": "1"}
+	,{"name": "VRInitError_Init_InstallationNotFound","value": "100"}
+	,{"name": "VRInitError_Init_InstallationCorrupt","value": "101"}
+	,{"name": "VRInitError_Init_VRClientDLLNotFound","value": "102"}
+	,{"name": "VRInitError_Init_FileNotFound","value": "103"}
+	,{"name": "VRInitError_Init_FactoryNotFound","value": "104"}
+	,{"name": "VRInitError_Init_InterfaceNotFound","value": "105"}
+	,{"name": "VRInitError_Init_InvalidInterface","value": "106"}
+	,{"name": "VRInitError_Init_UserConfigDirectoryInvalid","value": "107"}
+	,{"name": "VRInitError_Init_HmdNotFound","value": "108"}
+	,{"name": "VRInitError_Init_NotInitialized","value": "109"}
+	,{"name": "VRInitError_Init_PathRegistryNotFound","value": "110"}
+	,{"name": "VRInitError_Init_NoConfigPath","value": "111"}
+	,{"name": "VRInitError_Init_NoLogPath","value": "112"}
+	,{"name": "VRInitError_Init_PathRegistryNotWritable","value": "113"}
+	,{"name": "VRInitError_Init_AppInfoInitFailed","value": "114"}
+	,{"name": "VRInitError_Init_Retry","value": "115"}
+	,{"name": "VRInitError_Init_InitCanceledByUser","value": "116"}
+	,{"name": "VRInitError_Init_AnotherAppLaunching","value": "117"}
+	,{"name": "VRInitError_Init_SettingsInitFailed","value": "118"}
+	,{"name": "VRInitError_Init_ShuttingDown","value": "119"}
+	,{"name": "VRInitError_Init_TooManyObjects","value": "120"}
+	,{"name": "VRInitError_Init_NoServerForBackgroundApp","value": "121"}
+	,{"name": "VRInitError_Init_NotSupportedWithCompositor","value": "122"}
+	,{"name": "VRInitError_Init_NotAvailableToUtilityApps","value": "123"}
+	,{"name": "VRInitError_Init_Internal","value": "124"}
+	,{"name": "VRInitError_Init_HmdDriverIdIsNone","value": "125"}
+	,{"name": "VRInitError_Init_HmdNotFoundPresenceFailed","value": "126"}
+	,{"name": "VRInitError_Init_VRMonitorNotFound","value": "127"}
+	,{"name": "VRInitError_Init_VRMonitorStartupFailed","value": "128"}
+	,{"name": "VRInitError_Init_LowPowerWatchdogNotSupported","value": "129"}
+	,{"name": "VRInitError_Init_InvalidApplicationType","value": "130"}
+	,{"name": "VRInitError_Init_NotAvailableToWatchdogApps","value": "131"}
+	,{"name": "VRInitError_Init_WatchdogDisabledInSettings","value": "132"}
+	,{"name": "VRInitError_Init_VRDashboardNotFound","value": "133"}
+	,{"name": "VRInitError_Init_VRDashboardStartupFailed","value": "134"}
+	,{"name": "VRInitError_Driver_Failed","value": "200"}
+	,{"name": "VRInitError_Driver_Unknown","value": "201"}
+	,{"name": "VRInitError_Driver_HmdUnknown","value": "202"}
+	,{"name": "VRInitError_Driver_NotLoaded","value": "203"}
+	,{"name": "VRInitError_Driver_RuntimeOutOfDate","value": "204"}
+	,{"name": "VRInitError_Driver_HmdInUse","value": "205"}
+	,{"name": "VRInitError_Driver_NotCalibrated","value": "206"}
+	,{"name": "VRInitError_Driver_CalibrationInvalid","value": "207"}
+	,{"name": "VRInitError_Driver_HmdDisplayNotFound","value": "208"}
+	,{"name": "VRInitError_Driver_TrackedDeviceInterfaceUnknown","value": "209"}
+	,{"name": "VRInitError_Driver_HmdDriverIdOutOfBounds","value": "211"}
+	,{"name": "VRInitError_Driver_HmdDisplayMirrored","value": "212"}
+	,{"name": "VRInitError_IPC_ServerInitFailed","value": "300"}
+	,{"name": "VRInitError_IPC_ConnectFailed","value": "301"}
+	,{"name": "VRInitError_IPC_SharedStateInitFailed","value": "302"}
+	,{"name": "VRInitError_IPC_CompositorInitFailed","value": "303"}
+	,{"name": "VRInitError_IPC_MutexInitFailed","value": "304"}
+	,{"name": "VRInitError_IPC_Failed","value": "305"}
+	,{"name": "VRInitError_IPC_CompositorConnectFailed","value": "306"}
+	,{"name": "VRInitError_IPC_CompositorInvalidConnectResponse","value": "307"}
+	,{"name": "VRInitError_IPC_ConnectFailedAfterMultipleAttempts","value": "308"}
+	,{"name": "VRInitError_Compositor_Failed","value": "400"}
+	,{"name": "VRInitError_Compositor_D3D11HardwareRequired","value": "401"}
+	,{"name": "VRInitError_Compositor_FirmwareRequiresUpdate","value": "402"}
+	,{"name": "VRInitError_Compositor_OverlayInitFailed","value": "403"}
+	,{"name": "VRInitError_Compositor_ScreenshotsInitFailed","value": "404"}
+	,{"name": "VRInitError_VendorSpecific_UnableToConnectToOculusRuntime","value": "1000"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_CantOpenDevice","value": "1101"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart","value": "1102"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_NoStoredConfig","value": "1103"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_ConfigTooBig","value": "1104"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_ConfigTooSmall","value": "1105"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_UnableToInitZLib","value": "1106"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion","value": "1107"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart","value": "1108"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart","value": "1109"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext","value": "1110"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_UserDataAddressRange","value": "1111"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_UserDataError","value": "1112"}
+	,{"name": "VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck","value": "1113"}
+	,{"name": "VRInitError_Steam_SteamInstallationNotFound","value": "2000"}
+]}
+,	{"enumname": "vr::EVRScreenshotType","values": [ 
+	{"name": "VRScreenshotType_None","value": "0"}
+	,{"name": "VRScreenshotType_Mono","value": "1"}
+	,{"name": "VRScreenshotType_Stereo","value": "2"}
+	,{"name": "VRScreenshotType_Cubemap","value": "3"}
+	,{"name": "VRScreenshotType_MonoPanorama","value": "4"}
+	,{"name": "VRScreenshotType_StereoPanorama","value": "5"}
+]}
+,	{"enumname": "vr::EVRScreenshotPropertyFilenames","values": [ 
+	{"name": "VRScreenshotPropertyFilenames_Preview","value": "0"}
+	,{"name": "VRScreenshotPropertyFilenames_VR","value": "1"}
+]}
+,	{"enumname": "vr::EVRTrackedCameraError","values": [ 
+	{"name": "VRTrackedCameraError_None","value": "0"}
+	,{"name": "VRTrackedCameraError_OperationFailed","value": "100"}
+	,{"name": "VRTrackedCameraError_InvalidHandle","value": "101"}
+	,{"name": "VRTrackedCameraError_InvalidFrameHeaderVersion","value": "102"}
+	,{"name": "VRTrackedCameraError_OutOfHandles","value": "103"}
+	,{"name": "VRTrackedCameraError_IPCFailure","value": "104"}
+	,{"name": "VRTrackedCameraError_NotSupportedForThisDevice","value": "105"}
+	,{"name": "VRTrackedCameraError_SharedMemoryFailure","value": "106"}
+	,{"name": "VRTrackedCameraError_FrameBufferingFailure","value": "107"}
+	,{"name": "VRTrackedCameraError_StreamSetupFailure","value": "108"}
+	,{"name": "VRTrackedCameraError_InvalidGLTextureId","value": "109"}
+	,{"name": "VRTrackedCameraError_InvalidSharedTextureHandle","value": "110"}
+	,{"name": "VRTrackedCameraError_FailedToGetGLTextureId","value": "111"}
+	,{"name": "VRTrackedCameraError_SharedTextureFailure","value": "112"}
+	,{"name": "VRTrackedCameraError_NoFrameAvailable","value": "113"}
+	,{"name": "VRTrackedCameraError_InvalidArgument","value": "114"}
+	,{"name": "VRTrackedCameraError_InvalidFrameBufferSize","value": "115"}
+]}
+,	{"enumname": "vr::EVRTrackedCameraFrameType","values": [ 
+	{"name": "VRTrackedCameraFrameType_Distorted","value": "0"}
+	,{"name": "VRTrackedCameraFrameType_Undistorted","value": "1"}
+	,{"name": "VRTrackedCameraFrameType_MaximumUndistorted","value": "2"}
+	,{"name": "MAX_CAMERA_FRAME_TYPES","value": "3"}
+]}
+,	{"enumname": "vr::EVRApplicationError","values": [ 
+	{"name": "VRApplicationError_None","value": "0"}
+	,{"name": "VRApplicationError_AppKeyAlreadyExists","value": "100"}
+	,{"name": "VRApplicationError_NoManifest","value": "101"}
+	,{"name": "VRApplicationError_NoApplication","value": "102"}
+	,{"name": "VRApplicationError_InvalidIndex","value": "103"}
+	,{"name": "VRApplicationError_UnknownApplication","value": "104"}
+	,{"name": "VRApplicationError_IPCFailed","value": "105"}
+	,{"name": "VRApplicationError_ApplicationAlreadyRunning","value": "106"}
+	,{"name": "VRApplicationError_InvalidManifest","value": "107"}
+	,{"name": "VRApplicationError_InvalidApplication","value": "108"}
+	,{"name": "VRApplicationError_LaunchFailed","value": "109"}
+	,{"name": "VRApplicationError_ApplicationAlreadyStarting","value": "110"}
+	,{"name": "VRApplicationError_LaunchInProgress","value": "111"}
+	,{"name": "VRApplicationError_OldApplicationQuitting","value": "112"}
+	,{"name": "VRApplicationError_TransitionAborted","value": "113"}
+	,{"name": "VRApplicationError_IsTemplate","value": "114"}
+	,{"name": "VRApplicationError_BufferTooSmall","value": "200"}
+	,{"name": "VRApplicationError_PropertyNotSet","value": "201"}
+	,{"name": "VRApplicationError_UnknownProperty","value": "202"}
+	,{"name": "VRApplicationError_InvalidParameter","value": "203"}
+]}
+,	{"enumname": "vr::EVRApplicationProperty","values": [ 
+	{"name": "VRApplicationProperty_Name_String","value": "0"}
+	,{"name": "VRApplicationProperty_LaunchType_String","value": "11"}
+	,{"name": "VRApplicationProperty_WorkingDirectory_String","value": "12"}
+	,{"name": "VRApplicationProperty_BinaryPath_String","value": "13"}
+	,{"name": "VRApplicationProperty_Arguments_String","value": "14"}
+	,{"name": "VRApplicationProperty_URL_String","value": "15"}
+	,{"name": "VRApplicationProperty_Description_String","value": "50"}
+	,{"name": "VRApplicationProperty_NewsURL_String","value": "51"}
+	,{"name": "VRApplicationProperty_ImagePath_String","value": "52"}
+	,{"name": "VRApplicationProperty_Source_String","value": "53"}
+	,{"name": "VRApplicationProperty_IsDashboardOverlay_Bool","value": "60"}
+	,{"name": "VRApplicationProperty_IsTemplate_Bool","value": "61"}
+	,{"name": "VRApplicationProperty_IsInstanced_Bool","value": "62"}
+	,{"name": "VRApplicationProperty_IsInternal_Bool","value": "63"}
+	,{"name": "VRApplicationProperty_LastLaunchTime_Uint64","value": "70"}
+]}
+,	{"enumname": "vr::EVRApplicationTransitionState","values": [ 
+	{"name": "VRApplicationTransition_None","value": "0"}
+	,{"name": "VRApplicationTransition_OldAppQuitSent","value": "10"}
+	,{"name": "VRApplicationTransition_WaitingForExternalLaunch","value": "11"}
+	,{"name": "VRApplicationTransition_NewAppLaunched","value": "20"}
+]}
+,	{"enumname": "vr::ChaperoneCalibrationState","values": [ 
+	{"name": "ChaperoneCalibrationState_OK","value": "1"}
+	,{"name": "ChaperoneCalibrationState_Warning","value": "100"}
+	,{"name": "ChaperoneCalibrationState_Warning_BaseStationMayHaveMoved","value": "101"}
+	,{"name": "ChaperoneCalibrationState_Warning_BaseStationRemoved","value": "102"}
+	,{"name": "ChaperoneCalibrationState_Warning_SeatedBoundsInvalid","value": "103"}
+	,{"name": "ChaperoneCalibrationState_Error","value": "200"}
+	,{"name": "ChaperoneCalibrationState_Error_BaseStationUninitialized","value": "201"}
+	,{"name": "ChaperoneCalibrationState_Error_BaseStationConflict","value": "202"}
+	,{"name": "ChaperoneCalibrationState_Error_PlayAreaInvalid","value": "203"}
+	,{"name": "ChaperoneCalibrationState_Error_CollisionBoundsInvalid","value": "204"}
+]}
+,	{"enumname": "vr::EChaperoneConfigFile","values": [ 
+	{"name": "EChaperoneConfigFile_Live","value": "1"}
+	,{"name": "EChaperoneConfigFile_Temp","value": "2"}
+]}
+,	{"enumname": "vr::EChaperoneImportFlags","values": [ 
+	{"name": "EChaperoneImport_BoundsOnly","value": "1"}
+]}
+,	{"enumname": "vr::EVRCompositorError","values": [ 
+	{"name": "VRCompositorError_None","value": "0"}
+	,{"name": "VRCompositorError_RequestFailed","value": "1"}
+	,{"name": "VRCompositorError_IncompatibleVersion","value": "100"}
+	,{"name": "VRCompositorError_DoNotHaveFocus","value": "101"}
+	,{"name": "VRCompositorError_InvalidTexture","value": "102"}
+	,{"name": "VRCompositorError_IsNotSceneApplication","value": "103"}
+	,{"name": "VRCompositorError_TextureIsOnWrongDevice","value": "104"}
+	,{"name": "VRCompositorError_TextureUsesUnsupportedFormat","value": "105"}
+	,{"name": "VRCompositorError_SharedTexturesNotSupported","value": "106"}
+	,{"name": "VRCompositorError_IndexOutOfRange","value": "107"}
+	,{"name": "VRCompositorError_AlreadySubmitted","value": "108"}
+]}
+,	{"enumname": "vr::VROverlayInputMethod","values": [ 
+	{"name": "VROverlayInputMethod_None","value": "0"}
+	,{"name": "VROverlayInputMethod_Mouse","value": "1"}
+]}
+,	{"enumname": "vr::VROverlayTransformType","values": [ 
+	{"name": "VROverlayTransform_Absolute","value": "0"}
+	,{"name": "VROverlayTransform_TrackedDeviceRelative","value": "1"}
+	,{"name": "VROverlayTransform_SystemOverlay","value": "2"}
+	,{"name": "VROverlayTransform_TrackedComponent","value": "3"}
+]}
+,	{"enumname": "vr::VROverlayFlags","values": [ 
+	{"name": "VROverlayFlags_None","value": "0"}
+	,{"name": "VROverlayFlags_Curved","value": "1"}
+	,{"name": "VROverlayFlags_RGSS4X","value": "2"}
+	,{"name": "VROverlayFlags_NoDashboardTab","value": "3"}
+	,{"name": "VROverlayFlags_AcceptsGamepadEvents","value": "4"}
+	,{"name": "VROverlayFlags_ShowGamepadFocus","value": "5"}
+	,{"name": "VROverlayFlags_SendVRScrollEvents","value": "6"}
+	,{"name": "VROverlayFlags_SendVRTouchpadEvents","value": "7"}
+	,{"name": "VROverlayFlags_ShowTouchPadScrollWheel","value": "8"}
+	,{"name": "VROverlayFlags_TransferOwnershipToInternalProcess","value": "9"}
+	,{"name": "VROverlayFlags_SideBySide_Parallel","value": "10"}
+	,{"name": "VROverlayFlags_SideBySide_Crossed","value": "11"}
+	,{"name": "VROverlayFlags_Panorama","value": "12"}
+	,{"name": "VROverlayFlags_StereoPanorama","value": "13"}
+	,{"name": "VROverlayFlags_SortWithNonSceneOverlays","value": "14"}
+	,{"name": "VROverlayFlags_VisibleInDashboard","value": "15"}
+]}
+,	{"enumname": "vr::VRMessageOverlayResponse","values": [ 
+	{"name": "VRMessageOverlayResponse_ButtonPress_0","value": "0"}
+	,{"name": "VRMessageOverlayResponse_ButtonPress_1","value": "1"}
+	,{"name": "VRMessageOverlayResponse_ButtonPress_2","value": "2"}
+	,{"name": "VRMessageOverlayResponse_ButtonPress_3","value": "3"}
+	,{"name": "VRMessageOverlayResponse_CouldntFindSystemOverlay","value": "4"}
+	,{"name": "VRMessageOverlayResponse_CouldntFindOrCreateClientOverlay","value": "5"}
+	,{"name": "VRMessageOverlayResponse_ApplicationQuit","value": "6"}
+]}
+,	{"enumname": "vr::EGamepadTextInputMode","values": [ 
+	{"name": "k_EGamepadTextInputModeNormal","value": "0"}
+	,{"name": "k_EGamepadTextInputModePassword","value": "1"}
+	,{"name": "k_EGamepadTextInputModeSubmit","value": "2"}
+]}
+,	{"enumname": "vr::EGamepadTextInputLineMode","values": [ 
+	{"name": "k_EGamepadTextInputLineModeSingleLine","value": "0"}
+	,{"name": "k_EGamepadTextInputLineModeMultipleLines","value": "1"}
+]}
+,	{"enumname": "vr::EOverlayDirection","values": [ 
+	{"name": "OverlayDirection_Up","value": "0"}
+	,{"name": "OverlayDirection_Down","value": "1"}
+	,{"name": "OverlayDirection_Left","value": "2"}
+	,{"name": "OverlayDirection_Right","value": "3"}
+	,{"name": "OverlayDirection_Count","value": "4"}
+]}
+,	{"enumname": "vr::EVROverlayIntersectionMaskPrimitiveType","values": [ 
+	{"name": "OverlayIntersectionPrimitiveType_Rectangle","value": "0"}
+	,{"name": "OverlayIntersectionPrimitiveType_Circle","value": "1"}
+]}
+,	{"enumname": "vr::EVRRenderModelError","values": [ 
+	{"name": "VRRenderModelError_None","value": "0"}
+	,{"name": "VRRenderModelError_Loading","value": "100"}
+	,{"name": "VRRenderModelError_NotSupported","value": "200"}
+	,{"name": "VRRenderModelError_InvalidArg","value": "300"}
+	,{"name": "VRRenderModelError_InvalidModel","value": "301"}
+	,{"name": "VRRenderModelError_NoShapes","value": "302"}
+	,{"name": "VRRenderModelError_MultipleShapes","value": "303"}
+	,{"name": "VRRenderModelError_TooManyVertices","value": "304"}
+	,{"name": "VRRenderModelError_MultipleTextures","value": "305"}
+	,{"name": "VRRenderModelError_BufferTooSmall","value": "306"}
+	,{"name": "VRRenderModelError_NotEnoughNormals","value": "307"}
+	,{"name": "VRRenderModelError_NotEnoughTexCoords","value": "308"}
+	,{"name": "VRRenderModelError_InvalidTexture","value": "400"}
+]}
+,	{"enumname": "vr::EVRComponentProperty","values": [ 
+	{"name": "VRComponentProperty_IsStatic","value": "1"}
+	,{"name": "VRComponentProperty_IsVisible","value": "2"}
+	,{"name": "VRComponentProperty_IsTouched","value": "4"}
+	,{"name": "VRComponentProperty_IsPressed","value": "8"}
+	,{"name": "VRComponentProperty_IsScrolled","value": "16"}
+]}
+,	{"enumname": "vr::EVRNotificationType","values": [ 
+	{"name": "EVRNotificationType_Transient","value": "0"}
+	,{"name": "EVRNotificationType_Persistent","value": "1"}
+	,{"name": "EVRNotificationType_Transient_SystemWithUserValue","value": "2"}
+]}
+,	{"enumname": "vr::EVRNotificationStyle","values": [ 
+	{"name": "EVRNotificationStyle_None","value": "0"}
+	,{"name": "EVRNotificationStyle_Application","value": "100"}
+	,{"name": "EVRNotificationStyle_Contact_Disabled","value": "200"}
+	,{"name": "EVRNotificationStyle_Contact_Enabled","value": "201"}
+	,{"name": "EVRNotificationStyle_Contact_Active","value": "202"}
+]}
+,	{"enumname": "vr::EVRSettingsError","values": [ 
+	{"name": "VRSettingsError_None","value": "0"}
+	,{"name": "VRSettingsError_IPCFailed","value": "1"}
+	,{"name": "VRSettingsError_WriteFailed","value": "2"}
+	,{"name": "VRSettingsError_ReadFailed","value": "3"}
+	,{"name": "VRSettingsError_JsonParseFailed","value": "4"}
+	,{"name": "VRSettingsError_UnsetSettingHasNoDefault","value": "5"}
+]}
+,	{"enumname": "vr::EVRScreenshotError","values": [ 
+	{"name": "VRScreenshotError_None","value": "0"}
+	,{"name": "VRScreenshotError_RequestFailed","value": "1"}
+	,{"name": "VRScreenshotError_IncompatibleVersion","value": "100"}
+	,{"name": "VRScreenshotError_NotFound","value": "101"}
+	,{"name": "VRScreenshotError_BufferTooSmall","value": "102"}
+	,{"name": "VRScreenshotError_ScreenshotAlreadyInProgress","value": "108"}
+]}
+],
+"consts":[{
+	"constname": "k_unMaxDriverDebugResponseSize","consttype": "const uint32_t", "constval": "32768"}
+,{
+	"constname": "k_unTrackedDeviceIndex_Hmd","consttype": "const uint32_t", "constval": "0"}
+,{
+	"constname": "k_unMaxTrackedDeviceCount","consttype": "const uint32_t", "constval": "16"}
+,{
+	"constname": "k_unTrackedDeviceIndexOther","consttype": "const uint32_t", "constval": "4294967294"}
+,{
+	"constname": "k_unTrackedDeviceIndexInvalid","consttype": "const uint32_t", "constval": "4294967295"}
+,{
+	"constname": "k_ulInvalidPropertyContainer","consttype": "const PropertyContainerHandle_t", "constval": "0"}
+,{
+	"constname": "k_unInvalidPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "0"}
+,{
+	"constname": "k_unFloatPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "1"}
+,{
+	"constname": "k_unInt32PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "2"}
+,{
+	"constname": "k_unUint64PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "3"}
+,{
+	"constname": "k_unBoolPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "4"}
+,{
+	"constname": "k_unStringPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "5"}
+,{
+	"constname": "k_unHmdMatrix34PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "20"}
+,{
+	"constname": "k_unHmdMatrix44PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "21"}
+,{
+	"constname": "k_unHmdVector3PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "22"}
+,{
+	"constname": "k_unHmdVector4PropertyTag","consttype": "const PropertyTypeTag_t", "constval": "23"}
+,{
+	"constname": "k_unHiddenAreaPropertyTag","consttype": "const PropertyTypeTag_t", "constval": "30"}
+,{
+	"constname": "k_unOpenVRInternalReserved_Start","consttype": "const PropertyTypeTag_t", "constval": "1000"}
+,{
+	"constname": "k_unOpenVRInternalReserved_End","consttype": "const PropertyTypeTag_t", "constval": "10000"}
+,{
+	"constname": "k_unMaxPropertyStringSize","consttype": "const uint32_t", "constval": "32768"}
+,{
+	"constname": "k_unControllerStateAxisCount","consttype": "const uint32_t", "constval": "5"}
+,{
+	"constname": "k_ulOverlayHandleInvalid","consttype": "const VROverlayHandle_t", "constval": "0"}
+,{
+	"constname": "k_unScreenshotHandleInvalid","consttype": "const uint32_t", "constval": "0"}
+,{
+	"constname": "IVRSystem_Version","consttype": "const char *const", "constval": "IVRSystem_015"}
+,{
+	"constname": "IVRExtendedDisplay_Version","consttype": "const char *const", "constval": "IVRExtendedDisplay_001"}
+,{
+	"constname": "IVRTrackedCamera_Version","consttype": "const char *const", "constval": "IVRTrackedCamera_003"}
+,{
+	"constname": "k_unMaxApplicationKeyLength","consttype": "const uint32_t", "constval": "128"}
+,{
+	"constname": "k_pch_MimeType_HomeApp","consttype": "const char *const", "constval": "vr/home"}
+,{
+	"constname": "k_pch_MimeType_GameTheater","consttype": "const char *const", "constval": "vr/game_theater"}
+,{
+	"constname": "IVRApplications_Version","consttype": "const char *const", "constval": "IVRApplications_006"}
+,{
+	"constname": "IVRChaperone_Version","consttype": "const char *const", "constval": "IVRChaperone_003"}
+,{
+	"constname": "IVRChaperoneSetup_Version","consttype": "const char *const", "constval": "IVRChaperoneSetup_005"}
+,{
+	"constname": "IVRCompositor_Version","consttype": "const char *const", "constval": "IVRCompositor_020"}
+,{
+	"constname": "k_unVROverlayMaxKeyLength","consttype": "const uint32_t", "constval": "128"}
+,{
+	"constname": "k_unVROverlayMaxNameLength","consttype": "const uint32_t", "constval": "128"}
+,{
+	"constname": "k_unMaxOverlayCount","consttype": "const uint32_t", "constval": "64"}
+,{
+	"constname": "k_unMaxOverlayIntersectionMaskPrimitivesCount","consttype": "const uint32_t", "constval": "32"}
+,{
+	"constname": "IVROverlay_Version","consttype": "const char *const", "constval": "IVROverlay_014"}
+,{
+	"constname": "k_pch_Controller_Component_GDC2015","consttype": "const char *const", "constval": "gdc2015"}
+,{
+	"constname": "k_pch_Controller_Component_Base","consttype": "const char *const", "constval": "base"}
+,{
+	"constname": "k_pch_Controller_Component_Tip","consttype": "const char *const", "constval": "tip"}
+,{
+	"constname": "k_pch_Controller_Component_HandGrip","consttype": "const char *const", "constval": "handgrip"}
+,{
+	"constname": "k_pch_Controller_Component_Status","consttype": "const char *const", "constval": "status"}
+,{
+	"constname": "IVRRenderModels_Version","consttype": "const char *const", "constval": "IVRRenderModels_005"}
+,{
+	"constname": "k_unNotificationTextMaxSize","consttype": "const uint32_t", "constval": "256"}
+,{
+	"constname": "IVRNotifications_Version","consttype": "const char *const", "constval": "IVRNotifications_002"}
+,{
+	"constname": "k_unMaxSettingsKeyLength","consttype": "const uint32_t", "constval": "128"}
+,{
+	"constname": "IVRSettings_Version","consttype": "const char *const", "constval": "IVRSettings_002"}
+,{
+	"constname": "k_pch_SteamVR_Section","consttype": "const char *const", "constval": "steamvr"}
+,{
+	"constname": "k_pch_SteamVR_RequireHmd_String","consttype": "const char *const", "constval": "requireHmd"}
+,{
+	"constname": "k_pch_SteamVR_ForcedDriverKey_String","consttype": "const char *const", "constval": "forcedDriver"}
+,{
+	"constname": "k_pch_SteamVR_ForcedHmdKey_String","consttype": "const char *const", "constval": "forcedHmd"}
+,{
+	"constname": "k_pch_SteamVR_DisplayDebug_Bool","consttype": "const char *const", "constval": "displayDebug"}
+,{
+	"constname": "k_pch_SteamVR_DebugProcessPipe_String","consttype": "const char *const", "constval": "debugProcessPipe"}
+,{
+	"constname": "k_pch_SteamVR_EnableDistortion_Bool","consttype": "const char *const", "constval": "enableDistortion"}
+,{
+	"constname": "k_pch_SteamVR_DisplayDebugX_Int32","consttype": "const char *const", "constval": "displayDebugX"}
+,{
+	"constname": "k_pch_SteamVR_DisplayDebugY_Int32","consttype": "const char *const", "constval": "displayDebugY"}
+,{
+	"constname": "k_pch_SteamVR_SendSystemButtonToAllApps_Bool","consttype": "const char *const", "constval": "sendSystemButtonToAllApps"}
+,{
+	"constname": "k_pch_SteamVR_LogLevel_Int32","consttype": "const char *const", "constval": "loglevel"}
+,{
+	"constname": "k_pch_SteamVR_IPD_Float","consttype": "const char *const", "constval": "ipd"}
+,{
+	"constname": "k_pch_SteamVR_Background_String","consttype": "const char *const", "constval": "background"}
+,{
+	"constname": "k_pch_SteamVR_BackgroundUseDomeProjection_Bool","consttype": "const char *const", "constval": "backgroundUseDomeProjection"}
+,{
+	"constname": "k_pch_SteamVR_BackgroundCameraHeight_Float","consttype": "const char *const", "constval": "backgroundCameraHeight"}
+,{
+	"constname": "k_pch_SteamVR_BackgroundDomeRadius_Float","consttype": "const char *const", "constval": "backgroundDomeRadius"}
+,{
+	"constname": "k_pch_SteamVR_GridColor_String","consttype": "const char *const", "constval": "gridColor"}
+,{
+	"constname": "k_pch_SteamVR_PlayAreaColor_String","consttype": "const char *const", "constval": "playAreaColor"}
+,{
+	"constname": "k_pch_SteamVR_ShowStage_Bool","consttype": "const char *const", "constval": "showStage"}
+,{
+	"constname": "k_pch_SteamVR_ActivateMultipleDrivers_Bool","consttype": "const char *const", "constval": "activateMultipleDrivers"}
+,{
+	"constname": "k_pch_SteamVR_DirectMode_Bool","consttype": "const char *const", "constval": "directMode"}
+,{
+	"constname": "k_pch_SteamVR_DirectModeEdidVid_Int32","consttype": "const char *const", "constval": "directModeEdidVid"}
+,{
+	"constname": "k_pch_SteamVR_DirectModeEdidPid_Int32","consttype": "const char *const", "constval": "directModeEdidPid"}
+,{
+	"constname": "k_pch_SteamVR_UsingSpeakers_Bool","consttype": "const char *const", "constval": "usingSpeakers"}
+,{
+	"constname": "k_pch_SteamVR_SpeakersForwardYawOffsetDegrees_Float","consttype": "const char *const", "constval": "speakersForwardYawOffsetDegrees"}
+,{
+	"constname": "k_pch_SteamVR_BaseStationPowerManagement_Bool","consttype": "const char *const", "constval": "basestationPowerManagement"}
+,{
+	"constname": "k_pch_SteamVR_NeverKillProcesses_Bool","consttype": "const char *const", "constval": "neverKillProcesses"}
+,{
+	"constname": "k_pch_SteamVR_RenderTargetMultiplier_Float","consttype": "const char *const", "constval": "renderTargetMultiplier"}
+,{
+	"constname": "k_pch_SteamVR_AllowAsyncReprojection_Bool","consttype": "const char *const", "constval": "allowAsyncReprojection"}
+,{
+	"constname": "k_pch_SteamVR_AllowReprojection_Bool","consttype": "const char *const", "constval": "allowInterleavedReprojection"}
+,{
+	"constname": "k_pch_SteamVR_ForceReprojection_Bool","consttype": "const char *const", "constval": "forceReprojection"}
+,{
+	"constname": "k_pch_SteamVR_ForceFadeOnBadTracking_Bool","consttype": "const char *const", "constval": "forceFadeOnBadTracking"}
+,{
+	"constname": "k_pch_SteamVR_DefaultMirrorView_Int32","consttype": "const char *const", "constval": "defaultMirrorView"}
+,{
+	"constname": "k_pch_SteamVR_ShowMirrorView_Bool","consttype": "const char *const", "constval": "showMirrorView"}
+,{
+	"constname": "k_pch_SteamVR_MirrorViewGeometry_String","consttype": "const char *const", "constval": "mirrorViewGeometry"}
+,{
+	"constname": "k_pch_SteamVR_StartMonitorFromAppLaunch","consttype": "const char *const", "constval": "startMonitorFromAppLaunch"}
+,{
+	"constname": "k_pch_SteamVR_StartCompositorFromAppLaunch_Bool","consttype": "const char *const", "constval": "startCompositorFromAppLaunch"}
+,{
+	"constname": "k_pch_SteamVR_StartDashboardFromAppLaunch_Bool","consttype": "const char *const", "constval": "startDashboardFromAppLaunch"}
+,{
+	"constname": "k_pch_SteamVR_StartOverlayAppsFromDashboard_Bool","consttype": "const char *const", "constval": "startOverlayAppsFromDashboard"}
+,{
+	"constname": "k_pch_SteamVR_EnableHomeApp","consttype": "const char *const", "constval": "enableHomeApp"}
+,{
+	"constname": "k_pch_SteamVR_SetInitialDefaultHomeApp","consttype": "const char *const", "constval": "setInitialDefaultHomeApp"}
+,{
+	"constname": "k_pch_SteamVR_CycleBackgroundImageTimeSec_Int32","consttype": "const char *const", "constval": "CycleBackgroundImageTimeSec"}
+,{
+	"constname": "k_pch_SteamVR_RetailDemo_Bool","consttype": "const char *const", "constval": "retailDemo"}
+,{
+	"constname": "k_pch_SteamVR_IpdOffset_Float","consttype": "const char *const", "constval": "ipdOffset"}
+,{
+	"constname": "k_pch_Lighthouse_Section","consttype": "const char *const", "constval": "driver_lighthouse"}
+,{
+	"constname": "k_pch_Lighthouse_DisableIMU_Bool","consttype": "const char *const", "constval": "disableimu"}
+,{
+	"constname": "k_pch_Lighthouse_UseDisambiguation_String","consttype": "const char *const", "constval": "usedisambiguation"}
+,{
+	"constname": "k_pch_Lighthouse_DisambiguationDebug_Int32","consttype": "const char *const", "constval": "disambiguationdebug"}
+,{
+	"constname": "k_pch_Lighthouse_PrimaryBasestation_Int32","consttype": "const char *const", "constval": "primarybasestation"}
+,{
+	"constname": "k_pch_Lighthouse_DBHistory_Bool","consttype": "const char *const", "constval": "dbhistory"}
+,{
+	"constname": "k_pch_Null_Section","consttype": "const char *const", "constval": "driver_null"}
+,{
+	"constname": "k_pch_Null_SerialNumber_String","consttype": "const char *const", "constval": "serialNumber"}
+,{
+	"constname": "k_pch_Null_ModelNumber_String","consttype": "const char *const", "constval": "modelNumber"}
+,{
+	"constname": "k_pch_Null_WindowX_Int32","consttype": "const char *const", "constval": "windowX"}
+,{
+	"constname": "k_pch_Null_WindowY_Int32","consttype": "const char *const", "constval": "windowY"}
+,{
+	"constname": "k_pch_Null_WindowWidth_Int32","consttype": "const char *const", "constval": "windowWidth"}
+,{
+	"constname": "k_pch_Null_WindowHeight_Int32","consttype": "const char *const", "constval": "windowHeight"}
+,{
+	"constname": "k_pch_Null_RenderWidth_Int32","consttype": "const char *const", "constval": "renderWidth"}
+,{
+	"constname": "k_pch_Null_RenderHeight_Int32","consttype": "const char *const", "constval": "renderHeight"}
+,{
+	"constname": "k_pch_Null_SecondsFromVsyncToPhotons_Float","consttype": "const char *const", "constval": "secondsFromVsyncToPhotons"}
+,{
+	"constname": "k_pch_Null_DisplayFrequency_Float","consttype": "const char *const", "constval": "displayFrequency"}
+,{
+	"constname": "k_pch_UserInterface_Section","consttype": "const char *const", "constval": "userinterface"}
+,{
+	"constname": "k_pch_UserInterface_StatusAlwaysOnTop_Bool","consttype": "const char *const", "constval": "StatusAlwaysOnTop"}
+,{
+	"constname": "k_pch_UserInterface_MinimizeToTray_Bool","consttype": "const char *const", "constval": "MinimizeToTray"}
+,{
+	"constname": "k_pch_UserInterface_Screenshots_Bool","consttype": "const char *const", "constval": "screenshots"}
+,{
+	"constname": "k_pch_UserInterface_ScreenshotType_Int","consttype": "const char *const", "constval": "screenshotType"}
+,{
+	"constname": "k_pch_Notifications_Section","consttype": "const char *const", "constval": "notifications"}
+,{
+	"constname": "k_pch_Notifications_DoNotDisturb_Bool","consttype": "const char *const", "constval": "DoNotDisturb"}
+,{
+	"constname": "k_pch_Keyboard_Section","consttype": "const char *const", "constval": "keyboard"}
+,{
+	"constname": "k_pch_Keyboard_TutorialCompletions","consttype": "const char *const", "constval": "TutorialCompletions"}
+,{
+	"constname": "k_pch_Keyboard_ScaleX","consttype": "const char *const", "constval": "ScaleX"}
+,{
+	"constname": "k_pch_Keyboard_ScaleY","consttype": "const char *const", "constval": "ScaleY"}
+,{
+	"constname": "k_pch_Keyboard_OffsetLeftX","consttype": "const char *const", "constval": "OffsetLeftX"}
+,{
+	"constname": "k_pch_Keyboard_OffsetRightX","consttype": "const char *const", "constval": "OffsetRightX"}
+,{
+	"constname": "k_pch_Keyboard_OffsetY","consttype": "const char *const", "constval": "OffsetY"}
+,{
+	"constname": "k_pch_Keyboard_Smoothing","consttype": "const char *const", "constval": "Smoothing"}
+,{
+	"constname": "k_pch_Perf_Section","consttype": "const char *const", "constval": "perfcheck"}
+,{
+	"constname": "k_pch_Perf_HeuristicActive_Bool","consttype": "const char *const", "constval": "heuristicActive"}
+,{
+	"constname": "k_pch_Perf_NotifyInHMD_Bool","consttype": "const char *const", "constval": "warnInHMD"}
+,{
+	"constname": "k_pch_Perf_NotifyOnlyOnce_Bool","consttype": "const char *const", "constval": "warnOnlyOnce"}
+,{
+	"constname": "k_pch_Perf_AllowTimingStore_Bool","consttype": "const char *const", "constval": "allowTimingStore"}
+,{
+	"constname": "k_pch_Perf_SaveTimingsOnExit_Bool","consttype": "const char *const", "constval": "saveTimingsOnExit"}
+,{
+	"constname": "k_pch_Perf_TestData_Float","consttype": "const char *const", "constval": "perfTestData"}
+,{
+	"constname": "k_pch_CollisionBounds_Section","consttype": "const char *const", "constval": "collisionBounds"}
+,{
+	"constname": "k_pch_CollisionBounds_Style_Int32","consttype": "const char *const", "constval": "CollisionBoundsStyle"}
+,{
+	"constname": "k_pch_CollisionBounds_GroundPerimeterOn_Bool","consttype": "const char *const", "constval": "CollisionBoundsGroundPerimeterOn"}
+,{
+	"constname": "k_pch_CollisionBounds_CenterMarkerOn_Bool","consttype": "const char *const", "constval": "CollisionBoundsCenterMarkerOn"}
+,{
+	"constname": "k_pch_CollisionBounds_PlaySpaceOn_Bool","consttype": "const char *const", "constval": "CollisionBoundsPlaySpaceOn"}
+,{
+	"constname": "k_pch_CollisionBounds_FadeDistance_Float","consttype": "const char *const", "constval": "CollisionBoundsFadeDistance"}
+,{
+	"constname": "k_pch_CollisionBounds_ColorGammaR_Int32","consttype": "const char *const", "constval": "CollisionBoundsColorGammaR"}
+,{
+	"constname": "k_pch_CollisionBounds_ColorGammaG_Int32","consttype": "const char *const", "constval": "CollisionBoundsColorGammaG"}
+,{
+	"constname": "k_pch_CollisionBounds_ColorGammaB_Int32","consttype": "const char *const", "constval": "CollisionBoundsColorGammaB"}
+,{
+	"constname": "k_pch_CollisionBounds_ColorGammaA_Int32","consttype": "const char *const", "constval": "CollisionBoundsColorGammaA"}
+,{
+	"constname": "k_pch_Camera_Section","consttype": "const char *const", "constval": "camera"}
+,{
+	"constname": "k_pch_Camera_EnableCamera_Bool","consttype": "const char *const", "constval": "enableCamera"}
+,{
+	"constname": "k_pch_Camera_EnableCameraInDashboard_Bool","consttype": "const char *const", "constval": "enableCameraInDashboard"}
+,{
+	"constname": "k_pch_Camera_EnableCameraForCollisionBounds_Bool","consttype": "const char *const", "constval": "enableCameraForCollisionBounds"}
+,{
+	"constname": "k_pch_Camera_EnableCameraForRoomView_Bool","consttype": "const char *const", "constval": "enableCameraForRoomView"}
+,{
+	"constname": "k_pch_Camera_BoundsColorGammaR_Int32","consttype": "const char *const", "constval": "cameraBoundsColorGammaR"}
+,{
+	"constname": "k_pch_Camera_BoundsColorGammaG_Int32","consttype": "const char *const", "constval": "cameraBoundsColorGammaG"}
+,{
+	"constname": "k_pch_Camera_BoundsColorGammaB_Int32","consttype": "const char *const", "constval": "cameraBoundsColorGammaB"}
+,{
+	"constname": "k_pch_Camera_BoundsColorGammaA_Int32","consttype": "const char *const", "constval": "cameraBoundsColorGammaA"}
+,{
+	"constname": "k_pch_Camera_BoundsStrength_Int32","consttype": "const char *const", "constval": "cameraBoundsStrength"}
+,{
+	"constname": "k_pch_audio_Section","consttype": "const char *const", "constval": "audio"}
+,{
+	"constname": "k_pch_audio_OnPlaybackDevice_String","consttype": "const char *const", "constval": "onPlaybackDevice"}
+,{
+	"constname": "k_pch_audio_OnRecordDevice_String","consttype": "const char *const", "constval": "onRecordDevice"}
+,{
+	"constname": "k_pch_audio_OnPlaybackMirrorDevice_String","consttype": "const char *const", "constval": "onPlaybackMirrorDevice"}
+,{
+	"constname": "k_pch_audio_OffPlaybackDevice_String","consttype": "const char *const", "constval": "offPlaybackDevice"}
+,{
+	"constname": "k_pch_audio_OffRecordDevice_String","consttype": "const char *const", "constval": "offRecordDevice"}
+,{
+	"constname": "k_pch_audio_VIVEHDMIGain","consttype": "const char *const", "constval": "viveHDMIGain"}
+,{
+	"constname": "k_pch_Power_Section","consttype": "const char *const", "constval": "power"}
+,{
+	"constname": "k_pch_Power_PowerOffOnExit_Bool","consttype": "const char *const", "constval": "powerOffOnExit"}
+,{
+	"constname": "k_pch_Power_TurnOffScreensTimeout_Float","consttype": "const char *const", "constval": "turnOffScreensTimeout"}
+,{
+	"constname": "k_pch_Power_TurnOffControllersTimeout_Float","consttype": "const char *const", "constval": "turnOffControllersTimeout"}
+,{
+	"constname": "k_pch_Power_ReturnToWatchdogTimeout_Float","consttype": "const char *const", "constval": "returnToWatchdogTimeout"}
+,{
+	"constname": "k_pch_Power_AutoLaunchSteamVROnButtonPress","consttype": "const char *const", "constval": "autoLaunchSteamVROnButtonPress"}
+,{
+	"constname": "k_pch_Dashboard_Section","consttype": "const char *const", "constval": "dashboard"}
+,{
+	"constname": "k_pch_Dashboard_EnableDashboard_Bool","consttype": "const char *const", "constval": "enableDashboard"}
+,{
+	"constname": "k_pch_Dashboard_ArcadeMode_Bool","consttype": "const char *const", "constval": "arcadeMode"}
+,{
+	"constname": "k_pch_modelskin_Section","consttype": "const char *const", "constval": "modelskins"}
+,{
+	"constname": "k_pch_Driver_Enable_Bool","consttype": "const char *const", "constval": "enable"}
+,{
+	"constname": "IVRScreenshots_Version","consttype": "const char *const", "constval": "IVRScreenshots_001"}
+,{
+	"constname": "IVRResources_Version","consttype": "const char *const", "constval": "IVRResources_001"}
+],
+"structs":[{"struct": "vr::HmdMatrix34_t","fields": [
+{ "fieldname": "m", "fieldtype": "float [3][4]"}]}
+,{"struct": "vr::HmdMatrix44_t","fields": [
+{ "fieldname": "m", "fieldtype": "float [4][4]"}]}
+,{"struct": "vr::HmdVector3_t","fields": [
+{ "fieldname": "v", "fieldtype": "float [3]"}]}
+,{"struct": "vr::HmdVector4_t","fields": [
+{ "fieldname": "v", "fieldtype": "float [4]"}]}
+,{"struct": "vr::HmdVector3d_t","fields": [
+{ "fieldname": "v", "fieldtype": "double [3]"}]}
+,{"struct": "vr::HmdVector2_t","fields": [
+{ "fieldname": "v", "fieldtype": "float [2]"}]}
+,{"struct": "vr::HmdQuaternion_t","fields": [
+{ "fieldname": "w", "fieldtype": "double"},
+{ "fieldname": "x", "fieldtype": "double"},
+{ "fieldname": "y", "fieldtype": "double"},
+{ "fieldname": "z", "fieldtype": "double"}]}
+,{"struct": "vr::HmdColor_t","fields": [
+{ "fieldname": "r", "fieldtype": "float"},
+{ "fieldname": "g", "fieldtype": "float"},
+{ "fieldname": "b", "fieldtype": "float"},
+{ "fieldname": "a", "fieldtype": "float"}]}
+,{"struct": "vr::HmdQuad_t","fields": [
+{ "fieldname": "vCorners", "fieldtype": "struct vr::HmdVector3_t [4]"}]}
+,{"struct": "vr::HmdRect2_t","fields": [
+{ "fieldname": "vTopLeft", "fieldtype": "struct vr::HmdVector2_t"},
+{ "fieldname": "vBottomRight", "fieldtype": "struct vr::HmdVector2_t"}]}
+,{"struct": "vr::DistortionCoordinates_t","fields": [
+{ "fieldname": "rfRed", "fieldtype": "float [2]"},
+{ "fieldname": "rfGreen", "fieldtype": "float [2]"},
+{ "fieldname": "rfBlue", "fieldtype": "float [2]"}]}
+,{"struct": "vr::Texture_t","fields": [
+{ "fieldname": "handle", "fieldtype": "void *"},
+{ "fieldname": "eType", "fieldtype": "enum vr::ETextureType"},
+{ "fieldname": "eColorSpace", "fieldtype": "enum vr::EColorSpace"}]}
+,{"struct": "vr::TrackedDevicePose_t","fields": [
+{ "fieldname": "mDeviceToAbsoluteTracking", "fieldtype": "struct vr::HmdMatrix34_t"},
+{ "fieldname": "vVelocity", "fieldtype": "struct vr::HmdVector3_t"},
+{ "fieldname": "vAngularVelocity", "fieldtype": "struct vr::HmdVector3_t"},
+{ "fieldname": "eTrackingResult", "fieldtype": "enum vr::ETrackingResult"},
+{ "fieldname": "bPoseIsValid", "fieldtype": "_Bool"},
+{ "fieldname": "bDeviceIsConnected", "fieldtype": "_Bool"}]}
+,{"struct": "vr::VRTextureBounds_t","fields": [
+{ "fieldname": "uMin", "fieldtype": "float"},
+{ "fieldname": "vMin", "fieldtype": "float"},
+{ "fieldname": "uMax", "fieldtype": "float"},
+{ "fieldname": "vMax", "fieldtype": "float"}]}
+,{"struct": "vr::VRVulkanTextureData_t","fields": [
+{ "fieldname": "m_nImage", "fieldtype": "uint64_t"},
+{ "fieldname": "m_pDevice", "fieldtype": "struct VkDevice_T *"},
+{ "fieldname": "m_pPhysicalDevice", "fieldtype": "struct VkPhysicalDevice_T *"},
+{ "fieldname": "m_pInstance", "fieldtype": "struct VkInstance_T *"},
+{ "fieldname": "m_pQueue", "fieldtype": "struct VkQueue_T *"},
+{ "fieldname": "m_nQueueFamilyIndex", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nWidth", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nHeight", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nFormat", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nSampleCount", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::D3D12TextureData_t","fields": [
+{ "fieldname": "m_pResource", "fieldtype": "struct ID3D12Resource *"},
+{ "fieldname": "m_pCommandQueue", "fieldtype": "struct ID3D12CommandQueue *"},
+{ "fieldname": "m_nNodeMask", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_Controller_t","fields": [
+{ "fieldname": "button", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_Mouse_t","fields": [
+{ "fieldname": "x", "fieldtype": "float"},
+{ "fieldname": "y", "fieldtype": "float"},
+{ "fieldname": "button", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_Scroll_t","fields": [
+{ "fieldname": "xdelta", "fieldtype": "float"},
+{ "fieldname": "ydelta", "fieldtype": "float"},
+{ "fieldname": "repeatCount", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_TouchPadMove_t","fields": [
+{ "fieldname": "bFingerDown", "fieldtype": "_Bool"},
+{ "fieldname": "flSecondsFingerDown", "fieldtype": "float"},
+{ "fieldname": "fValueXFirst", "fieldtype": "float"},
+{ "fieldname": "fValueYFirst", "fieldtype": "float"},
+{ "fieldname": "fValueXRaw", "fieldtype": "float"},
+{ "fieldname": "fValueYRaw", "fieldtype": "float"}]}
+,{"struct": "vr::VREvent_Notification_t","fields": [
+{ "fieldname": "ulUserValue", "fieldtype": "uint64_t"},
+{ "fieldname": "notificationId", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_Process_t","fields": [
+{ "fieldname": "pid", "fieldtype": "uint32_t"},
+{ "fieldname": "oldPid", "fieldtype": "uint32_t"},
+{ "fieldname": "bForced", "fieldtype": "_Bool"}]}
+,{"struct": "vr::VREvent_Overlay_t","fields": [
+{ "fieldname": "overlayHandle", "fieldtype": "uint64_t"}]}
+,{"struct": "vr::VREvent_Status_t","fields": [
+{ "fieldname": "statusState", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_Keyboard_t","fields": [
+{ "fieldname": "cNewInput", "fieldtype": "char [8]"},
+{ "fieldname": "uUserValue", "fieldtype": "uint64_t"}]}
+,{"struct": "vr::VREvent_Ipd_t","fields": [
+{ "fieldname": "ipdMeters", "fieldtype": "float"}]}
+,{"struct": "vr::VREvent_Chaperone_t","fields": [
+{ "fieldname": "m_nPreviousUniverse", "fieldtype": "uint64_t"},
+{ "fieldname": "m_nCurrentUniverse", "fieldtype": "uint64_t"}]}
+,{"struct": "vr::VREvent_Reserved_t","fields": [
+{ "fieldname": "reserved0", "fieldtype": "uint64_t"},
+{ "fieldname": "reserved1", "fieldtype": "uint64_t"}]}
+,{"struct": "vr::VREvent_PerformanceTest_t","fields": [
+{ "fieldname": "m_nFidelityLevel", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_SeatedZeroPoseReset_t","fields": [
+{ "fieldname": "bResetBySystemMenu", "fieldtype": "_Bool"}]}
+,{"struct": "vr::VREvent_Screenshot_t","fields": [
+{ "fieldname": "handle", "fieldtype": "uint32_t"},
+{ "fieldname": "type", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_ScreenshotProgress_t","fields": [
+{ "fieldname": "progress", "fieldtype": "float"}]}
+,{"struct": "vr::VREvent_ApplicationLaunch_t","fields": [
+{ "fieldname": "pid", "fieldtype": "uint32_t"},
+{ "fieldname": "unArgsHandle", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_EditingCameraSurface_t","fields": [
+{ "fieldname": "overlayHandle", "fieldtype": "uint64_t"},
+{ "fieldname": "nVisualMode", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_MessageOverlay_t","fields": [
+{ "fieldname": "unVRMessageOverlayResponse", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VREvent_Property_t","fields": [
+{ "fieldname": "container", "fieldtype": "PropertyContainerHandle_t"},
+{ "fieldname": "prop", "fieldtype": "enum vr::ETrackedDeviceProperty"}]}
+,{"struct": "vr::(anonymous)","fields": [
+{ "fieldname": "reserved", "fieldtype": "struct vr::VREvent_Reserved_t"},
+{ "fieldname": "controller", "fieldtype": "struct vr::VREvent_Controller_t"},
+{ "fieldname": "mouse", "fieldtype": "struct vr::VREvent_Mouse_t"},
+{ "fieldname": "scroll", "fieldtype": "struct vr::VREvent_Scroll_t"},
+{ "fieldname": "process", "fieldtype": "struct vr::VREvent_Process_t"},
+{ "fieldname": "notification", "fieldtype": "struct vr::VREvent_Notification_t"},
+{ "fieldname": "overlay", "fieldtype": "struct vr::VREvent_Overlay_t"},
+{ "fieldname": "status", "fieldtype": "struct vr::VREvent_Status_t"},
+{ "fieldname": "keyboard", "fieldtype": "struct vr::VREvent_Keyboard_t"},
+{ "fieldname": "ipd", "fieldtype": "struct vr::VREvent_Ipd_t"},
+{ "fieldname": "chaperone", "fieldtype": "struct vr::VREvent_Chaperone_t"},
+{ "fieldname": "performanceTest", "fieldtype": "struct vr::VREvent_PerformanceTest_t"},
+{ "fieldname": "touchPadMove", "fieldtype": "struct vr::VREvent_TouchPadMove_t"},
+{ "fieldname": "seatedZeroPoseReset", "fieldtype": "struct vr::VREvent_SeatedZeroPoseReset_t"},
+{ "fieldname": "screenshot", "fieldtype": "struct vr::VREvent_Screenshot_t"},
+{ "fieldname": "screenshotProgress", "fieldtype": "struct vr::VREvent_ScreenshotProgress_t"},
+{ "fieldname": "applicationLaunch", "fieldtype": "struct vr::VREvent_ApplicationLaunch_t"},
+{ "fieldname": "cameraSurface", "fieldtype": "struct vr::VREvent_EditingCameraSurface_t"},
+{ "fieldname": "messageOverlay", "fieldtype": "struct vr::VREvent_MessageOverlay_t"},
+{ "fieldname": "property", "fieldtype": "struct vr::VREvent_Property_t"}]}
+,{"struct": "vr::VREvent_t","fields": [
+{ "fieldname": "eventType", "fieldtype": "uint32_t"},
+{ "fieldname": "trackedDeviceIndex", "fieldtype": "TrackedDeviceIndex_t"},
+{ "fieldname": "eventAgeSeconds", "fieldtype": "float"},
+{ "fieldname": "data", "fieldtype": "VREvent_Data_t"}]}
+,{"struct": "vr::HiddenAreaMesh_t","fields": [
+{ "fieldname": "pVertexData", "fieldtype": "const struct vr::HmdVector2_t *"},
+{ "fieldname": "unTriangleCount", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VRControllerAxis_t","fields": [
+{ "fieldname": "x", "fieldtype": "float"},
+{ "fieldname": "y", "fieldtype": "float"}]}
+,{"struct": "vr::VRControllerState001_t","fields": [
+{ "fieldname": "unPacketNum", "fieldtype": "uint32_t"},
+{ "fieldname": "ulButtonPressed", "fieldtype": "uint64_t"},
+{ "fieldname": "ulButtonTouched", "fieldtype": "uint64_t"},
+{ "fieldname": "rAxis", "fieldtype": "struct vr::VRControllerAxis_t [5]"}]}
+,{"struct": "vr::Compositor_OverlaySettings","fields": [
+{ "fieldname": "size", "fieldtype": "uint32_t"},
+{ "fieldname": "curved", "fieldtype": "_Bool"},
+{ "fieldname": "antialias", "fieldtype": "_Bool"},
+{ "fieldname": "scale", "fieldtype": "float"},
+{ "fieldname": "distance", "fieldtype": "float"},
+{ "fieldname": "alpha", "fieldtype": "float"},
+{ "fieldname": "uOffset", "fieldtype": "float"},
+{ "fieldname": "vOffset", "fieldtype": "float"},
+{ "fieldname": "uScale", "fieldtype": "float"},
+{ "fieldname": "vScale", "fieldtype": "float"},
+{ "fieldname": "gridDivs", "fieldtype": "float"},
+{ "fieldname": "gridWidth", "fieldtype": "float"},
+{ "fieldname": "gridScale", "fieldtype": "float"},
+{ "fieldname": "transform", "fieldtype": "struct vr::HmdMatrix44_t"}]}
+,{"struct": "vr::CameraVideoStreamFrameHeader_t","fields": [
+{ "fieldname": "eFrameType", "fieldtype": "enum vr::EVRTrackedCameraFrameType"},
+{ "fieldname": "nWidth", "fieldtype": "uint32_t"},
+{ "fieldname": "nHeight", "fieldtype": "uint32_t"},
+{ "fieldname": "nBytesPerPixel", "fieldtype": "uint32_t"},
+{ "fieldname": "nFrameSequence", "fieldtype": "uint32_t"},
+{ "fieldname": "standingTrackedDevicePose", "fieldtype": "struct vr::TrackedDevicePose_t"}]}
+,{"struct": "vr::AppOverrideKeys_t","fields": [
+{ "fieldname": "pchKey", "fieldtype": "const char *"},
+{ "fieldname": "pchValue", "fieldtype": "const char *"}]}
+,{"struct": "vr::Compositor_FrameTiming","fields": [
+{ "fieldname": "m_nSize", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nFrameIndex", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumFramePresents", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumMisPresented", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumDroppedFrames", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nReprojectionFlags", "fieldtype": "uint32_t"},
+{ "fieldname": "m_flSystemTimeInSeconds", "fieldtype": "double"},
+{ "fieldname": "m_flPreSubmitGpuMs", "fieldtype": "float"},
+{ "fieldname": "m_flPostSubmitGpuMs", "fieldtype": "float"},
+{ "fieldname": "m_flTotalRenderGpuMs", "fieldtype": "float"},
+{ "fieldname": "m_flCompositorRenderGpuMs", "fieldtype": "float"},
+{ "fieldname": "m_flCompositorRenderCpuMs", "fieldtype": "float"},
+{ "fieldname": "m_flCompositorIdleCpuMs", "fieldtype": "float"},
+{ "fieldname": "m_flClientFrameIntervalMs", "fieldtype": "float"},
+{ "fieldname": "m_flPresentCallCpuMs", "fieldtype": "float"},
+{ "fieldname": "m_flWaitForPresentCpuMs", "fieldtype": "float"},
+{ "fieldname": "m_flSubmitFrameMs", "fieldtype": "float"},
+{ "fieldname": "m_flWaitGetPosesCalledMs", "fieldtype": "float"},
+{ "fieldname": "m_flNewPosesReadyMs", "fieldtype": "float"},
+{ "fieldname": "m_flNewFrameReadyMs", "fieldtype": "float"},
+{ "fieldname": "m_flCompositorUpdateStartMs", "fieldtype": "float"},
+{ "fieldname": "m_flCompositorUpdateEndMs", "fieldtype": "float"},
+{ "fieldname": "m_flCompositorRenderStartMs", "fieldtype": "float"},
+{ "fieldname": "m_HmdPose", "fieldtype": "vr::TrackedDevicePose_t"}]}
+,{"struct": "vr::Compositor_CumulativeStats","fields": [
+{ "fieldname": "m_nPid", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumFramePresents", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumDroppedFrames", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumReprojectedFrames", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumFramePresentsOnStartup", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumDroppedFramesOnStartup", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumReprojectedFramesOnStartup", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumLoading", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumFramePresentsLoading", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumDroppedFramesLoading", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumReprojectedFramesLoading", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumTimedOut", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumFramePresentsTimedOut", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumDroppedFramesTimedOut", "fieldtype": "uint32_t"},
+{ "fieldname": "m_nNumReprojectedFramesTimedOut", "fieldtype": "uint32_t"}]}
+,{"struct": "vr::VROverlayIntersectionParams_t","fields": [
+{ "fieldname": "vSource", "fieldtype": "struct vr::HmdVector3_t"},
+{ "fieldname": "vDirection", "fieldtype": "struct vr::HmdVector3_t"},
+{ "fieldname": "eOrigin", "fieldtype": "enum vr::ETrackingUniverseOrigin"}]}
+,{"struct": "vr::VROverlayIntersectionResults_t","fields": [
+{ "fieldname": "vPoint", "fieldtype": "struct vr::HmdVector3_t"},
+{ "fieldname": "vNormal", "fieldtype": "struct vr::HmdVector3_t"},
+{ "fieldname": "vUVs", "fieldtype": "struct vr::HmdVector2_t"},
+{ "fieldname": "fDistance", "fieldtype": "float"}]}
+,{"struct": "vr::IntersectionMaskRectangle_t","fields": [
+{ "fieldname": "m_flTopLeftX", "fieldtype": "float"},
+{ "fieldname": "m_flTopLeftY", "fieldtype": "float"},
+{ "fieldname": "m_flWidth", "fieldtype": "float"},
+{ "fieldname": "m_flHeight", "fieldtype": "float"}]}
+,{"struct": "vr::IntersectionMaskCircle_t","fields": [
+{ "fieldname": "m_flCenterX", "fieldtype": "float"},
+{ "fieldname": "m_flCenterY", "fieldtype": "float"},
+{ "fieldname": "m_flRadius", "fieldtype": "float"}]}
+,{"struct": "vr::(anonymous)","fields": [
+{ "fieldname": "m_Rectangle", "fieldtype": "struct vr::IntersectionMaskRectangle_t"},
+{ "fieldname": "m_Circle", "fieldtype": "struct vr::IntersectionMaskCircle_t"}]}
+,{"struct": "vr::VROverlayIntersectionMaskPrimitive_t","fields": [
+{ "fieldname": "m_nPrimitiveType", "fieldtype": "enum vr::EVROverlayIntersectionMaskPrimitiveType"},
+{ "fieldname": "m_Primitive", "fieldtype": "VROverlayIntersectionMaskPrimitive_Data_t"}]}
+,{"struct": "vr::RenderModel_ComponentState_t","fields": [
+{ "fieldname": "mTrackingToComponentRenderModel", "fieldtype": "struct vr::HmdMatrix34_t"},
+{ "fieldname": "mTrackingToComponentLocal", "fieldtype": "struct vr::HmdMatrix34_t"},
+{ "fieldname": "uProperties", "fieldtype": "VRComponentProperties"}]}
+,{"struct": "vr::RenderModel_Vertex_t","fields": [
+{ "fieldname": "vPosition", "fieldtype": "struct vr::HmdVector3_t"},
+{ "fieldname": "vNormal", "fieldtype": "struct vr::HmdVector3_t"},
+{ "fieldname": "rfTextureCoord", "fieldtype": "float [2]"}]}
+,{"struct": "vr::RenderModel_TextureMap_t","fields": [
+{ "fieldname": "unWidth", "fieldtype": "uint16_t"},
+{ "fieldname": "unHeight", "fieldtype": "uint16_t"},
+{ "fieldname": "rubTextureMapData", "fieldtype": "const uint8_t *"}]}
+,{"struct": "vr::RenderModel_t","fields": [
+{ "fieldname": "rVertexData", "fieldtype": "const struct vr::RenderModel_Vertex_t *"},
+{ "fieldname": "unVertexCount", "fieldtype": "uint32_t"},
+{ "fieldname": "rIndexData", "fieldtype": "const uint16_t *"},
+{ "fieldname": "unTriangleCount", "fieldtype": "uint32_t"},
+{ "fieldname": "diffuseTextureId", "fieldtype": "TextureID_t"}]}
+,{"struct": "vr::RenderModel_ControllerMode_State_t","fields": [
+{ "fieldname": "bScrollWheelVisible", "fieldtype": "_Bool"}]}
+,{"struct": "vr::NotificationBitmap_t","fields": [
+{ "fieldname": "m_pImageData", "fieldtype": "void *"},
+{ "fieldname": "m_nWidth", "fieldtype": "int32_t"},
+{ "fieldname": "m_nHeight", "fieldtype": "int32_t"},
+{ "fieldname": "m_nBytesPerPixel", "fieldtype": "int32_t"}]}
+,{"struct": "vr::COpenVRContext","fields": [
+{ "fieldname": "m_pVRSystem", "fieldtype": "class vr::IVRSystem *"},
+{ "fieldname": "m_pVRChaperone", "fieldtype": "class vr::IVRChaperone *"},
+{ "fieldname": "m_pVRChaperoneSetup", "fieldtype": "class vr::IVRChaperoneSetup *"},
+{ "fieldname": "m_pVRCompositor", "fieldtype": "class vr::IVRCompositor *"},
+{ "fieldname": "m_pVROverlay", "fieldtype": "class vr::IVROverlay *"},
+{ "fieldname": "m_pVRResources", "fieldtype": "class vr::IVRResources *"},
+{ "fieldname": "m_pVRRenderModels", "fieldtype": "class vr::IVRRenderModels *"},
+{ "fieldname": "m_pVRExtendedDisplay", "fieldtype": "class vr::IVRExtendedDisplay *"},
+{ "fieldname": "m_pVRSettings", "fieldtype": "class vr::IVRSettings *"},
+{ "fieldname": "m_pVRApplications", "fieldtype": "class vr::IVRApplications *"},
+{ "fieldname": "m_pVRTrackedCamera", "fieldtype": "class vr::IVRTrackedCamera *"},
+{ "fieldname": "m_pVRScreenshots", "fieldtype": "class vr::IVRScreenshots *"}]}
+],
+"methods":[{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetRecommendedRenderTargetSize",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pnWidth" ,"paramtype": "uint32_t *"},
+{	"paramname": "pnHeight" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetProjectionMatrix",
+	"returntype": "struct vr::HmdMatrix44_t",
+	"params": [ 
+{	"paramname": "eEye" ,"paramtype": "vr::EVREye"},
+{	"paramname": "fNearZ" ,"paramtype": "float"},
+{	"paramname": "fFarZ" ,"paramtype": "float"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetProjectionRaw",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "eEye" ,"paramtype": "vr::EVREye"},
+{	"paramname": "pfLeft" ,"paramtype": "float *"},
+{	"paramname": "pfRight" ,"paramtype": "float *"},
+{	"paramname": "pfTop" ,"paramtype": "float *"},
+{	"paramname": "pfBottom" ,"paramtype": "float *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "ComputeDistortion",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "eEye" ,"paramtype": "vr::EVREye"},
+{	"paramname": "fU" ,"paramtype": "float"},
+{	"paramname": "fV" ,"paramtype": "float"},
+{	"paramname": "pDistortionCoordinates" ,"paramtype": "struct vr::DistortionCoordinates_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetEyeToHeadTransform",
+	"returntype": "struct vr::HmdMatrix34_t",
+	"params": [ 
+{	"paramname": "eEye" ,"paramtype": "vr::EVREye"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetTimeSinceLastVsync",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pfSecondsSinceLastVsync" ,"paramtype": "float *"},
+{	"paramname": "pulFrameCounter" ,"paramtype": "uint64_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetD3D9AdapterIndex",
+	"returntype": "int32_t"
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetDXGIOutputInfo",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pnAdapterIndex" ,"paramtype": "int32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "IsDisplayOnDesktop",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "SetDisplayVisibility",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "bIsVisibleOnDesktop" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetDeviceToAbsoluteTrackingPose",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "eOrigin" ,"paramtype": "vr::ETrackingUniverseOrigin"},
+{	"paramname": "fPredictedSecondsToPhotonsFromNow" ,"paramtype": "float"},
+{	"paramname": "pTrackedDevicePoseArray" ,"array_count": "unTrackedDevicePoseArrayCount" ,"paramtype": "struct vr::TrackedDevicePose_t *"},
+{	"paramname": "unTrackedDevicePoseArrayCount" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "ResetSeatedZeroPose",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetSeatedZeroPoseToStandingAbsoluteTrackingPose",
+	"returntype": "struct vr::HmdMatrix34_t"
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetRawZeroPoseToStandingAbsoluteTrackingPose",
+	"returntype": "struct vr::HmdMatrix34_t"
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetSortedTrackedDeviceIndicesOfClass",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "eTrackedDeviceClass" ,"paramtype": "vr::ETrackedDeviceClass"},
+{	"paramname": "punTrackedDeviceIndexArray" ,"array_count": "unTrackedDeviceIndexArrayCount" ,"paramtype": "vr::TrackedDeviceIndex_t *"},
+{	"paramname": "unTrackedDeviceIndexArrayCount" ,"paramtype": "uint32_t"},
+{	"paramname": "unRelativeToTrackedDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetTrackedDeviceActivityLevel",
+	"returntype": "vr::EDeviceActivityLevel",
+	"params": [ 
+{	"paramname": "unDeviceId" ,"paramtype": "vr::TrackedDeviceIndex_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "ApplyTransform",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pOutputPose" ,"paramtype": "struct vr::TrackedDevicePose_t *"},
+{	"paramname": "pTrackedDevicePose" ,"paramtype": "const struct vr::TrackedDevicePose_t *"},
+{	"paramname": "pTransform" ,"paramtype": "const struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetTrackedDeviceIndexForControllerRole",
+	"returntype": "vr::TrackedDeviceIndex_t",
+	"params": [ 
+{	"paramname": "unDeviceType" ,"paramtype": "vr::ETrackedControllerRole"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetControllerRoleForTrackedDeviceIndex",
+	"returntype": "vr::ETrackedControllerRole",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetTrackedDeviceClass",
+	"returntype": "vr::ETrackedDeviceClass",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "IsTrackedDeviceConnected",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetBoolTrackedDeviceProperty",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "prop" ,"paramtype": "vr::ETrackedDeviceProperty"},
+{	"paramname": "pError" ,"paramtype": "vr::ETrackedPropertyError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetFloatTrackedDeviceProperty",
+	"returntype": "float",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "prop" ,"paramtype": "vr::ETrackedDeviceProperty"},
+{	"paramname": "pError" ,"paramtype": "vr::ETrackedPropertyError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetInt32TrackedDeviceProperty",
+	"returntype": "int32_t",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "prop" ,"paramtype": "vr::ETrackedDeviceProperty"},
+{	"paramname": "pError" ,"paramtype": "vr::ETrackedPropertyError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetUint64TrackedDeviceProperty",
+	"returntype": "uint64_t",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "prop" ,"paramtype": "vr::ETrackedDeviceProperty"},
+{	"paramname": "pError" ,"paramtype": "vr::ETrackedPropertyError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetMatrix34TrackedDeviceProperty",
+	"returntype": "struct vr::HmdMatrix34_t",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "prop" ,"paramtype": "vr::ETrackedDeviceProperty"},
+{	"paramname": "pError" ,"paramtype": "vr::ETrackedPropertyError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetStringTrackedDeviceProperty",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "prop" ,"paramtype": "vr::ETrackedDeviceProperty"},
+{	"paramname": "pchValue" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unBufferSize" ,"paramtype": "uint32_t"},
+{	"paramname": "pError" ,"paramtype": "vr::ETrackedPropertyError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetPropErrorNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "error" ,"paramtype": "vr::ETrackedPropertyError"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "PollNextEvent",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pEvent" ,"paramtype": "struct vr::VREvent_t *"},
+{	"paramname": "uncbVREvent" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "PollNextEventWithPose",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "eOrigin" ,"paramtype": "vr::ETrackingUniverseOrigin"},
+{	"paramname": "pEvent" ,"paramtype": "struct vr::VREvent_t *"},
+{	"paramname": "uncbVREvent" ,"paramtype": "uint32_t"},
+{	"paramname": "pTrackedDevicePose" ,"paramtype": "vr::TrackedDevicePose_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetEventTypeNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "eType" ,"paramtype": "vr::EVREventType"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetHiddenAreaMesh",
+	"returntype": "struct vr::HiddenAreaMesh_t",
+	"params": [ 
+{	"paramname": "eEye" ,"paramtype": "vr::EVREye"},
+{	"paramname": "type" ,"paramtype": "vr::EHiddenAreaMeshType"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetControllerState",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "unControllerDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "pControllerState" ,"paramtype": "vr::VRControllerState_t *"},
+{	"paramname": "unControllerStateSize" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetControllerStateWithPose",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "eOrigin" ,"paramtype": "vr::ETrackingUniverseOrigin"},
+{	"paramname": "unControllerDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "pControllerState" ,"paramtype": "vr::VRControllerState_t *"},
+{	"paramname": "unControllerStateSize" ,"paramtype": "uint32_t"},
+{	"paramname": "pTrackedDevicePose" ,"paramtype": "struct vr::TrackedDevicePose_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "TriggerHapticPulse",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "unControllerDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "unAxisId" ,"paramtype": "uint32_t"},
+{	"paramname": "usDurationMicroSec" ,"paramtype": "unsigned short"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetButtonIdNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "eButtonId" ,"paramtype": "vr::EVRButtonId"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "GetControllerAxisTypeNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "eAxisType" ,"paramtype": "vr::EVRControllerAxisType"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "CaptureInputFocus",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "ReleaseInputFocus",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "IsInputFocusCapturedByAnotherProcess",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "DriverDebugRequest",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "pchRequest" ,"paramtype": "const char *"},
+{	"paramname": "pchResponseBuffer" ,"paramtype": "char *"},
+{	"paramname": "unResponseBufferSize" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "PerformFirmwareUpdate",
+	"returntype": "vr::EVRFirmwareError",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "AcknowledgeQuit_Exiting",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRSystem",
+	"methodname": "AcknowledgeQuit_UserPrompt",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRExtendedDisplay",
+	"methodname": "GetWindowBounds",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pnX" ,"paramtype": "int32_t *"},
+{	"paramname": "pnY" ,"paramtype": "int32_t *"},
+{	"paramname": "pnWidth" ,"paramtype": "uint32_t *"},
+{	"paramname": "pnHeight" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRExtendedDisplay",
+	"methodname": "GetEyeOutputViewport",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "eEye" ,"paramtype": "vr::EVREye"},
+{	"paramname": "pnX" ,"paramtype": "uint32_t *"},
+{	"paramname": "pnY" ,"paramtype": "uint32_t *"},
+{	"paramname": "pnWidth" ,"paramtype": "uint32_t *"},
+{	"paramname": "pnHeight" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRExtendedDisplay",
+	"methodname": "GetDXGIOutputInfo",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pnAdapterIndex" ,"paramtype": "int32_t *"},
+{	"paramname": "pnAdapterOutputIndex" ,"paramtype": "int32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "GetCameraErrorNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "eCameraError" ,"paramtype": "vr::EVRTrackedCameraError"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "HasCamera",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "nDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "pHasCamera" ,"paramtype": "bool *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "GetCameraFrameSize",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "nDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "eFrameType" ,"paramtype": "vr::EVRTrackedCameraFrameType"},
+{	"paramname": "pnWidth" ,"paramtype": "uint32_t *"},
+{	"paramname": "pnHeight" ,"paramtype": "uint32_t *"},
+{	"paramname": "pnFrameBufferSize" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "GetCameraIntrinsics",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "nDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "eFrameType" ,"paramtype": "vr::EVRTrackedCameraFrameType"},
+{	"paramname": "pFocalLength" ,"paramtype": "vr::HmdVector2_t *"},
+{	"paramname": "pCenter" ,"paramtype": "vr::HmdVector2_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "GetCameraProjection",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "nDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "eFrameType" ,"paramtype": "vr::EVRTrackedCameraFrameType"},
+{	"paramname": "flZNear" ,"paramtype": "float"},
+{	"paramname": "flZFar" ,"paramtype": "float"},
+{	"paramname": "pProjection" ,"paramtype": "vr::HmdMatrix44_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "AcquireVideoStreamingService",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "nDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "pHandle" ,"paramtype": "vr::TrackedCameraHandle_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "ReleaseVideoStreamingService",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "hTrackedCamera" ,"paramtype": "vr::TrackedCameraHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "GetVideoStreamFrameBuffer",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "hTrackedCamera" ,"paramtype": "vr::TrackedCameraHandle_t"},
+{	"paramname": "eFrameType" ,"paramtype": "vr::EVRTrackedCameraFrameType"},
+{	"paramname": "pFrameBuffer" ,"paramtype": "void *"},
+{	"paramname": "nFrameBufferSize" ,"paramtype": "uint32_t"},
+{	"paramname": "pFrameHeader" ,"paramtype": "vr::CameraVideoStreamFrameHeader_t *"},
+{	"paramname": "nFrameHeaderSize" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "GetVideoStreamTextureSize",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "nDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "eFrameType" ,"paramtype": "vr::EVRTrackedCameraFrameType"},
+{	"paramname": "pTextureBounds" ,"paramtype": "vr::VRTextureBounds_t *"},
+{	"paramname": "pnWidth" ,"paramtype": "uint32_t *"},
+{	"paramname": "pnHeight" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "GetVideoStreamTextureD3D11",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "hTrackedCamera" ,"paramtype": "vr::TrackedCameraHandle_t"},
+{	"paramname": "eFrameType" ,"paramtype": "vr::EVRTrackedCameraFrameType"},
+{	"paramname": "pD3D11DeviceOrResource" ,"paramtype": "void *"},
+{	"paramname": "ppD3D11ShaderResourceView" ,"paramtype": "void **"},
+{	"paramname": "pFrameHeader" ,"paramtype": "vr::CameraVideoStreamFrameHeader_t *"},
+{	"paramname": "nFrameHeaderSize" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "GetVideoStreamTextureGL",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "hTrackedCamera" ,"paramtype": "vr::TrackedCameraHandle_t"},
+{	"paramname": "eFrameType" ,"paramtype": "vr::EVRTrackedCameraFrameType"},
+{	"paramname": "pglTextureId" ,"paramtype": "vr::glUInt_t *"},
+{	"paramname": "pFrameHeader" ,"paramtype": "vr::CameraVideoStreamFrameHeader_t *"},
+{	"paramname": "nFrameHeaderSize" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRTrackedCamera",
+	"methodname": "ReleaseVideoStreamTextureGL",
+	"returntype": "vr::EVRTrackedCameraError",
+	"params": [ 
+{	"paramname": "hTrackedCamera" ,"paramtype": "vr::TrackedCameraHandle_t"},
+{	"paramname": "glTextureId" ,"paramtype": "vr::glUInt_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "AddApplicationManifest",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchApplicationManifestFullPath" ,"paramtype": "const char *"},
+{	"paramname": "bTemporary" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "RemoveApplicationManifest",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchApplicationManifestFullPath" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "IsApplicationInstalled",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationCount",
+	"returntype": "uint32_t"
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationKeyByIndex",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "unApplicationIndex" ,"paramtype": "uint32_t"},
+{	"paramname": "pchAppKeyBuffer" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unAppKeyBufferLen" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationKeyByProcessId",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "unProcessId" ,"paramtype": "uint32_t"},
+{	"paramname": "pchAppKeyBuffer" ,"paramtype": "char *"},
+{	"paramname": "unAppKeyBufferLen" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "LaunchApplication",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "LaunchTemplateApplication",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchTemplateAppKey" ,"paramtype": "const char *"},
+{	"paramname": "pchNewAppKey" ,"paramtype": "const char *"},
+{	"paramname": "pKeys" ,"array_count": "unKeys" ,"paramtype": "const struct vr::AppOverrideKeys_t *"},
+{	"paramname": "unKeys" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "LaunchApplicationFromMimeType",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchMimeType" ,"paramtype": "const char *"},
+{	"paramname": "pchArgs" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "LaunchDashboardOverlay",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "CancelApplicationLaunch",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "IdentifyApplication",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "unProcessId" ,"paramtype": "uint32_t"},
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationProcessId",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationsErrorNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "error" ,"paramtype": "vr::EVRApplicationError"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationPropertyString",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"},
+{	"paramname": "eProperty" ,"paramtype": "vr::EVRApplicationProperty"},
+{	"paramname": "pchPropertyValueBuffer" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unPropertyValueBufferLen" ,"paramtype": "uint32_t"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRApplicationError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationPropertyBool",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"},
+{	"paramname": "eProperty" ,"paramtype": "vr::EVRApplicationProperty"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRApplicationError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationPropertyUint64",
+	"returntype": "uint64_t",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"},
+{	"paramname": "eProperty" ,"paramtype": "vr::EVRApplicationProperty"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRApplicationError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "SetApplicationAutoLaunch",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"},
+{	"paramname": "bAutoLaunch" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationAutoLaunch",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "SetDefaultApplicationForMimeType",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"},
+{	"paramname": "pchMimeType" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetDefaultApplicationForMimeType",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pchMimeType" ,"paramtype": "const char *"},
+{	"paramname": "pchAppKeyBuffer" ,"paramtype": "char *"},
+{	"paramname": "unAppKeyBufferLen" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationSupportedMimeTypes",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"},
+{	"paramname": "pchMimeTypesBuffer" ,"paramtype": "char *"},
+{	"paramname": "unMimeTypesBuffer" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationsThatSupportMimeType",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchMimeType" ,"paramtype": "const char *"},
+{	"paramname": "pchAppKeysThatSupportBuffer" ,"paramtype": "char *"},
+{	"paramname": "unAppKeysThatSupportBuffer" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationLaunchArguments",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "unHandle" ,"paramtype": "uint32_t"},
+{	"paramname": "pchArgs" ,"paramtype": "char *"},
+{	"paramname": "unArgs" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetStartingApplication",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchAppKeyBuffer" ,"paramtype": "char *"},
+{	"paramname": "unAppKeyBufferLen" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetTransitionState",
+	"returntype": "vr::EVRApplicationTransitionState"
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "PerformApplicationPrelaunchCheck",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchAppKey" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetApplicationsTransitionStateNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "state" ,"paramtype": "vr::EVRApplicationTransitionState"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "IsQuitUserPromptRequested",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "LaunchInternalProcess",
+	"returntype": "vr::EVRApplicationError",
+	"params": [ 
+{	"paramname": "pchBinaryPath" ,"paramtype": "const char *"},
+{	"paramname": "pchArguments" ,"paramtype": "const char *"},
+{	"paramname": "pchWorkingDirectory" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRApplications",
+	"methodname": "GetCurrentSceneProcessId",
+	"returntype": "uint32_t"
+}
+,{
+	"classname": "vr::IVRChaperone",
+	"methodname": "GetCalibrationState",
+	"returntype": "vr::ChaperoneCalibrationState"
+}
+,{
+	"classname": "vr::IVRChaperone",
+	"methodname": "GetPlayAreaSize",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pSizeX" ,"paramtype": "float *"},
+{	"paramname": "pSizeZ" ,"paramtype": "float *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperone",
+	"methodname": "GetPlayAreaRect",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "rect" ,"paramtype": "struct vr::HmdQuad_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperone",
+	"methodname": "ReloadInfo",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRChaperone",
+	"methodname": "SetSceneColor",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "color" ,"paramtype": "struct vr::HmdColor_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperone",
+	"methodname": "GetBoundsColor",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pOutputColorArray" ,"paramtype": "struct vr::HmdColor_t *"},
+{	"paramname": "nNumOutputColors" ,"paramtype": "int"},
+{	"paramname": "flCollisionBoundsFadeDistance" ,"paramtype": "float"},
+{	"paramname": "pOutputCameraColor" ,"paramtype": "struct vr::HmdColor_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperone",
+	"methodname": "AreBoundsVisible",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVRChaperone",
+	"methodname": "ForceBoundsVisible",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "bForce" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "CommitWorkingCopy",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "configFile" ,"paramtype": "vr::EChaperoneConfigFile"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "RevertWorkingCopy",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "GetWorkingPlayAreaSize",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pSizeX" ,"paramtype": "float *"},
+{	"paramname": "pSizeZ" ,"paramtype": "float *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "GetWorkingPlayAreaRect",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "rect" ,"paramtype": "struct vr::HmdQuad_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "GetWorkingCollisionBoundsInfo",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pQuadsBuffer" ,"out_array_count": "punQuadsCount" ,"paramtype": "struct vr::HmdQuad_t *"},
+{	"paramname": "punQuadsCount" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "GetLiveCollisionBoundsInfo",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pQuadsBuffer" ,"out_array_count": "punQuadsCount" ,"paramtype": "struct vr::HmdQuad_t *"},
+{	"paramname": "punQuadsCount" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "GetWorkingSeatedZeroPoseToRawTrackingPose",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pmatSeatedZeroPoseToRawTrackingPose" ,"paramtype": "struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "GetWorkingStandingZeroPoseToRawTrackingPose",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pmatStandingZeroPoseToRawTrackingPose" ,"paramtype": "struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "SetWorkingPlayAreaSize",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "sizeX" ,"paramtype": "float"},
+{	"paramname": "sizeZ" ,"paramtype": "float"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "SetWorkingCollisionBoundsInfo",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pQuadsBuffer" ,"array_count": "unQuadsCount" ,"paramtype": "struct vr::HmdQuad_t *"},
+{	"paramname": "unQuadsCount" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "SetWorkingSeatedZeroPoseToRawTrackingPose",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pMatSeatedZeroPoseToRawTrackingPose" ,"paramtype": "const struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "SetWorkingStandingZeroPoseToRawTrackingPose",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pMatStandingZeroPoseToRawTrackingPose" ,"paramtype": "const struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "ReloadFromDisk",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "configFile" ,"paramtype": "vr::EChaperoneConfigFile"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "GetLiveSeatedZeroPoseToRawTrackingPose",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pmatSeatedZeroPoseToRawTrackingPose" ,"paramtype": "struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "SetWorkingCollisionBoundsTagsInfo",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pTagsBuffer" ,"array_count": "unTagCount" ,"paramtype": "uint8_t *"},
+{	"paramname": "unTagCount" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "GetLiveCollisionBoundsTagsInfo",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pTagsBuffer" ,"out_array_count": "punTagCount" ,"paramtype": "uint8_t *"},
+{	"paramname": "punTagCount" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "SetWorkingPhysicalBoundsInfo",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pQuadsBuffer" ,"array_count": "unQuadsCount" ,"paramtype": "struct vr::HmdQuad_t *"},
+{	"paramname": "unQuadsCount" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "GetLivePhysicalBoundsInfo",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pQuadsBuffer" ,"out_array_count": "punQuadsCount" ,"paramtype": "struct vr::HmdQuad_t *"},
+{	"paramname": "punQuadsCount" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "ExportLiveToBuffer",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pBuffer" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "pnBufferLength" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRChaperoneSetup",
+	"methodname": "ImportFromBufferToWorking",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pBuffer" ,"paramtype": "const char *"},
+{	"paramname": "nImportFlags" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "SetTrackingSpace",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "eOrigin" ,"paramtype": "vr::ETrackingUniverseOrigin"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetTrackingSpace",
+	"returntype": "vr::ETrackingUniverseOrigin"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "WaitGetPoses",
+	"returntype": "vr::EVRCompositorError",
+	"params": [ 
+{	"paramname": "pRenderPoseArray" ,"array_count": "unRenderPoseArrayCount" ,"paramtype": "struct vr::TrackedDevicePose_t *"},
+{	"paramname": "unRenderPoseArrayCount" ,"paramtype": "uint32_t"},
+{	"paramname": "pGamePoseArray" ,"array_count": "unGamePoseArrayCount" ,"paramtype": "struct vr::TrackedDevicePose_t *"},
+{	"paramname": "unGamePoseArrayCount" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetLastPoses",
+	"returntype": "vr::EVRCompositorError",
+	"params": [ 
+{	"paramname": "pRenderPoseArray" ,"array_count": "unRenderPoseArrayCount" ,"paramtype": "struct vr::TrackedDevicePose_t *"},
+{	"paramname": "unRenderPoseArrayCount" ,"paramtype": "uint32_t"},
+{	"paramname": "pGamePoseArray" ,"array_count": "unGamePoseArrayCount" ,"paramtype": "struct vr::TrackedDevicePose_t *"},
+{	"paramname": "unGamePoseArrayCount" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetLastPoseForTrackedDeviceIndex",
+	"returntype": "vr::EVRCompositorError",
+	"params": [ 
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "pOutputPose" ,"paramtype": "struct vr::TrackedDevicePose_t *"},
+{	"paramname": "pOutputGamePose" ,"paramtype": "struct vr::TrackedDevicePose_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "Submit",
+	"returntype": "vr::EVRCompositorError",
+	"params": [ 
+{	"paramname": "eEye" ,"paramtype": "vr::EVREye"},
+{	"paramname": "pTexture" ,"paramtype": "const struct vr::Texture_t *"},
+{	"paramname": "pBounds" ,"paramtype": "const struct vr::VRTextureBounds_t *"},
+{	"paramname": "nSubmitFlags" ,"paramtype": "vr::EVRSubmitFlags"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "ClearLastSubmittedFrame",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "PostPresentHandoff",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetFrameTiming",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pTiming" ,"paramtype": "struct vr::Compositor_FrameTiming *"},
+{	"paramname": "unFramesAgo" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetFrameTimings",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pTiming" ,"paramtype": "struct vr::Compositor_FrameTiming *"},
+{	"paramname": "nFrames" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetFrameTimeRemaining",
+	"returntype": "float"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetCumulativeStats",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pStats" ,"paramtype": "struct vr::Compositor_CumulativeStats *"},
+{	"paramname": "nStatsSizeInBytes" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "FadeToColor",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "fSeconds" ,"paramtype": "float"},
+{	"paramname": "fRed" ,"paramtype": "float"},
+{	"paramname": "fGreen" ,"paramtype": "float"},
+{	"paramname": "fBlue" ,"paramtype": "float"},
+{	"paramname": "fAlpha" ,"paramtype": "float"},
+{	"paramname": "bBackground" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetCurrentFadeColor",
+	"returntype": "struct vr::HmdColor_t",
+	"params": [ 
+{	"paramname": "bBackground" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "FadeGrid",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "fSeconds" ,"paramtype": "float"},
+{	"paramname": "bFadeIn" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetCurrentGridAlpha",
+	"returntype": "float"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "SetSkyboxOverride",
+	"returntype": "vr::EVRCompositorError",
+	"params": [ 
+{	"paramname": "pTextures" ,"array_count": "unTextureCount" ,"paramtype": "const struct vr::Texture_t *"},
+{	"paramname": "unTextureCount" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "ClearSkyboxOverride",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "CompositorBringToFront",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "CompositorGoToBack",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "CompositorQuit",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "IsFullscreen",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetCurrentSceneFocusProcess",
+	"returntype": "uint32_t"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetLastFrameRenderer",
+	"returntype": "uint32_t"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "CanRenderScene",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "ShowMirrorWindow",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "HideMirrorWindow",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "IsMirrorWindowVisible",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "CompositorDumpImages",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "ShouldAppRenderWithLowResources",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "ForceInterleavedReprojectionOn",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "bOverride" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "ForceReconnectProcess",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "SuspendRendering",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "bSuspend" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetMirrorTextureD3D11",
+	"returntype": "vr::EVRCompositorError",
+	"params": [ 
+{	"paramname": "eEye" ,"paramtype": "vr::EVREye"},
+{	"paramname": "pD3D11DeviceOrResource" ,"paramtype": "void *"},
+{	"paramname": "ppD3D11ShaderResourceView" ,"paramtype": "void **"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "ReleaseMirrorTextureD3D11",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pD3D11ShaderResourceView" ,"paramtype": "void *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetMirrorTextureGL",
+	"returntype": "vr::EVRCompositorError",
+	"params": [ 
+{	"paramname": "eEye" ,"paramtype": "vr::EVREye"},
+{	"paramname": "pglTextureId" ,"paramtype": "vr::glUInt_t *"},
+{	"paramname": "pglSharedTextureHandle" ,"paramtype": "vr::glSharedTextureHandle_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "ReleaseSharedGLTexture",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "glTextureId" ,"paramtype": "vr::glUInt_t"},
+{	"paramname": "glSharedTextureHandle" ,"paramtype": "vr::glSharedTextureHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "LockGLSharedTextureForAccess",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "glSharedTextureHandle" ,"paramtype": "vr::glSharedTextureHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "UnlockGLSharedTextureForAccess",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "glSharedTextureHandle" ,"paramtype": "vr::glSharedTextureHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetVulkanInstanceExtensionsRequired",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchValue" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unBufferSize" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRCompositor",
+	"methodname": "GetVulkanDeviceExtensionsRequired",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pPhysicalDevice" ,"paramtype": "struct VkPhysicalDevice_T *"},
+{	"paramname": "pchValue" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unBufferSize" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "FindOverlay",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "pchOverlayKey" ,"paramtype": "const char *"},
+{	"paramname": "pOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "CreateOverlay",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "pchOverlayKey" ,"paramtype": "const char *"},
+{	"paramname": "pchOverlayFriendlyName" ,"paramtype": "const char *"},
+{	"paramname": "pOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "DestroyOverlay",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetHighQualityOverlay",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetHighQualityOverlay",
+	"returntype": "vr::VROverlayHandle_t"
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayKey",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pchValue" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unBufferSize" ,"paramtype": "uint32_t"},
+{	"paramname": "pError" ,"paramtype": "vr::EVROverlayError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayName",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pchValue" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unBufferSize" ,"paramtype": "uint32_t"},
+{	"paramname": "pError" ,"paramtype": "vr::EVROverlayError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayImageData",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pvBuffer" ,"paramtype": "void *"},
+{	"paramname": "unBufferSize" ,"paramtype": "uint32_t"},
+{	"paramname": "punWidth" ,"paramtype": "uint32_t *"},
+{	"paramname": "punHeight" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayErrorNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "error" ,"paramtype": "vr::EVROverlayError"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayRenderingPid",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "unPID" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayRenderingPid",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayFlag",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "eOverlayFlag" ,"paramtype": "vr::VROverlayFlags"},
+{	"paramname": "bEnabled" ,"paramtype": "bool"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayFlag",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "eOverlayFlag" ,"paramtype": "vr::VROverlayFlags"},
+{	"paramname": "pbEnabled" ,"paramtype": "bool *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayColor",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "fRed" ,"paramtype": "float"},
+{	"paramname": "fGreen" ,"paramtype": "float"},
+{	"paramname": "fBlue" ,"paramtype": "float"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayColor",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pfRed" ,"paramtype": "float *"},
+{	"paramname": "pfGreen" ,"paramtype": "float *"},
+{	"paramname": "pfBlue" ,"paramtype": "float *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayAlpha",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "fAlpha" ,"paramtype": "float"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayAlpha",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pfAlpha" ,"paramtype": "float *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayTexelAspect",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "fTexelAspect" ,"paramtype": "float"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayTexelAspect",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pfTexelAspect" ,"paramtype": "float *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlaySortOrder",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "unSortOrder" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlaySortOrder",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "punSortOrder" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayWidthInMeters",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "fWidthInMeters" ,"paramtype": "float"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayWidthInMeters",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pfWidthInMeters" ,"paramtype": "float *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayAutoCurveDistanceRangeInMeters",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "fMinDistanceInMeters" ,"paramtype": "float"},
+{	"paramname": "fMaxDistanceInMeters" ,"paramtype": "float"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayAutoCurveDistanceRangeInMeters",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pfMinDistanceInMeters" ,"paramtype": "float *"},
+{	"paramname": "pfMaxDistanceInMeters" ,"paramtype": "float *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayTextureColorSpace",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "eTextureColorSpace" ,"paramtype": "vr::EColorSpace"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayTextureColorSpace",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "peTextureColorSpace" ,"paramtype": "vr::EColorSpace *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayTextureBounds",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pOverlayTextureBounds" ,"paramtype": "const struct vr::VRTextureBounds_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayTextureBounds",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pOverlayTextureBounds" ,"paramtype": "struct vr::VRTextureBounds_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayTransformType",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "peTransformType" ,"paramtype": "vr::VROverlayTransformType *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayTransformAbsolute",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "eTrackingOrigin" ,"paramtype": "vr::ETrackingUniverseOrigin"},
+{	"paramname": "pmatTrackingOriginToOverlayTransform" ,"paramtype": "const struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayTransformAbsolute",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "peTrackingOrigin" ,"paramtype": "vr::ETrackingUniverseOrigin *"},
+{	"paramname": "pmatTrackingOriginToOverlayTransform" ,"paramtype": "struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayTransformTrackedDeviceRelative",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "unTrackedDevice" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "pmatTrackedDeviceToOverlayTransform" ,"paramtype": "const struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayTransformTrackedDeviceRelative",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "punTrackedDevice" ,"paramtype": "vr::TrackedDeviceIndex_t *"},
+{	"paramname": "pmatTrackedDeviceToOverlayTransform" ,"paramtype": "struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayTransformTrackedDeviceComponent",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "unDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"},
+{	"paramname": "pchComponentName" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayTransformTrackedDeviceComponent",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "punDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t *"},
+{	"paramname": "pchComponentName" ,"paramtype": "char *"},
+{	"paramname": "unComponentNameSize" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "ShowOverlay",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "HideOverlay",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "IsOverlayVisible",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetTransformForOverlayCoordinates",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "eTrackingOrigin" ,"paramtype": "vr::ETrackingUniverseOrigin"},
+{	"paramname": "coordinatesInOverlay" ,"paramtype": "struct vr::HmdVector2_t"},
+{	"paramname": "pmatTransform" ,"paramtype": "struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "PollNextOverlayEvent",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pEvent" ,"paramtype": "struct vr::VREvent_t *"},
+{	"paramname": "uncbVREvent" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayInputMethod",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "peInputMethod" ,"paramtype": "vr::VROverlayInputMethod *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayInputMethod",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "eInputMethod" ,"paramtype": "vr::VROverlayInputMethod"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayMouseScale",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pvecMouseScale" ,"paramtype": "struct vr::HmdVector2_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayMouseScale",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pvecMouseScale" ,"paramtype": "const struct vr::HmdVector2_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "ComputeOverlayIntersection",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pParams" ,"paramtype": "const struct vr::VROverlayIntersectionParams_t *"},
+{	"paramname": "pResults" ,"paramtype": "struct vr::VROverlayIntersectionResults_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "HandleControllerOverlayInteractionAsMouse",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "unControllerDeviceIndex" ,"paramtype": "vr::TrackedDeviceIndex_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "IsHoverTargetOverlay",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetGamepadFocusOverlay",
+	"returntype": "vr::VROverlayHandle_t"
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetGamepadFocusOverlay",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulNewFocusOverlay" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayNeighbor",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "eDirection" ,"paramtype": "vr::EOverlayDirection"},
+{	"paramname": "ulFrom" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "ulTo" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "MoveGamepadFocusToNeighbor",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "eDirection" ,"paramtype": "vr::EOverlayDirection"},
+{	"paramname": "ulFrom" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayTexture",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pTexture" ,"paramtype": "const struct vr::Texture_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "ClearOverlayTexture",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayRaw",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pvBuffer" ,"paramtype": "void *"},
+{	"paramname": "unWidth" ,"paramtype": "uint32_t"},
+{	"paramname": "unHeight" ,"paramtype": "uint32_t"},
+{	"paramname": "unDepth" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayFromFile",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pchFilePath" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayTexture",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pNativeTextureHandle" ,"paramtype": "void **"},
+{	"paramname": "pNativeTextureRef" ,"paramtype": "void *"},
+{	"paramname": "pWidth" ,"paramtype": "uint32_t *"},
+{	"paramname": "pHeight" ,"paramtype": "uint32_t *"},
+{	"paramname": "pNativeFormat" ,"paramtype": "uint32_t *"},
+{	"paramname": "pAPIType" ,"paramtype": "vr::ETextureType *"},
+{	"paramname": "pColorSpace" ,"paramtype": "vr::EColorSpace *"},
+{	"paramname": "pTextureBounds" ,"paramtype": "struct vr::VRTextureBounds_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "ReleaseNativeOverlayHandle",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pNativeTextureHandle" ,"paramtype": "void *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayTextureSize",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pWidth" ,"paramtype": "uint32_t *"},
+{	"paramname": "pHeight" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "CreateDashboardOverlay",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "pchOverlayKey" ,"paramtype": "const char *"},
+{	"paramname": "pchOverlayFriendlyName" ,"paramtype": "const char *"},
+{	"paramname": "pMainHandle" ,"paramtype": "vr::VROverlayHandle_t *"},
+{	"paramname": "pThumbnailHandle" ,"paramtype": "vr::VROverlayHandle_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "IsDashboardVisible",
+	"returntype": "bool"
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "IsActiveDashboardOverlay",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetDashboardOverlaySceneProcess",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "unProcessId" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetDashboardOverlaySceneProcess",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "punProcessId" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "ShowDashboard",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pchOverlayToShow" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetPrimaryDashboardDevice",
+	"returntype": "vr::TrackedDeviceIndex_t"
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "ShowKeyboard",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "eInputMode" ,"paramtype": "vr::EGamepadTextInputMode"},
+{	"paramname": "eLineInputMode" ,"paramtype": "vr::EGamepadTextInputLineMode"},
+{	"paramname": "pchDescription" ,"paramtype": "const char *"},
+{	"paramname": "unCharMax" ,"paramtype": "uint32_t"},
+{	"paramname": "pchExistingText" ,"paramtype": "const char *"},
+{	"paramname": "bUseMinimalMode" ,"paramtype": "bool"},
+{	"paramname": "uUserValue" ,"paramtype": "uint64_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "ShowKeyboardForOverlay",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "eInputMode" ,"paramtype": "vr::EGamepadTextInputMode"},
+{	"paramname": "eLineInputMode" ,"paramtype": "vr::EGamepadTextInputLineMode"},
+{	"paramname": "pchDescription" ,"paramtype": "const char *"},
+{	"paramname": "unCharMax" ,"paramtype": "uint32_t"},
+{	"paramname": "pchExistingText" ,"paramtype": "const char *"},
+{	"paramname": "bUseMinimalMode" ,"paramtype": "bool"},
+{	"paramname": "uUserValue" ,"paramtype": "uint64_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetKeyboardText",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchText" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "cchText" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "HideKeyboard",
+	"returntype": "void"
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetKeyboardTransformAbsolute",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "eTrackingOrigin" ,"paramtype": "vr::ETrackingUniverseOrigin"},
+{	"paramname": "pmatTrackingOriginToKeyboardTransform" ,"paramtype": "const struct vr::HmdMatrix34_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetKeyboardPositionForOverlay",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "avoidRect" ,"paramtype": "struct vr::HmdRect2_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "SetOverlayIntersectionMask",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pMaskPrimitives" ,"paramtype": "struct vr::VROverlayIntersectionMaskPrimitive_t *"},
+{	"paramname": "unNumMaskPrimitives" ,"paramtype": "uint32_t"},
+{	"paramname": "unPrimitiveSize" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "GetOverlayFlags",
+	"returntype": "vr::EVROverlayError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "pFlags" ,"paramtype": "uint32_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVROverlay",
+	"methodname": "ShowMessageOverlay",
+	"returntype": "vr::VRMessageOverlayResponse",
+	"params": [ 
+{	"paramname": "pchText" ,"paramtype": "const char *"},
+{	"paramname": "pchCaption" ,"paramtype": "const char *"},
+{	"paramname": "pchButton0Text" ,"paramtype": "const char *"},
+{	"paramname": "pchButton1Text" ,"paramtype": "const char *"},
+{	"paramname": "pchButton2Text" ,"paramtype": "const char *"},
+{	"paramname": "pchButton3Text" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "LoadRenderModel_Async",
+	"returntype": "vr::EVRRenderModelError",
+	"params": [ 
+{	"paramname": "pchRenderModelName" ,"paramtype": "const char *"},
+{	"paramname": "ppRenderModel" ,"paramtype": "struct vr::RenderModel_t **"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "FreeRenderModel",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pRenderModel" ,"paramtype": "struct vr::RenderModel_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "LoadTexture_Async",
+	"returntype": "vr::EVRRenderModelError",
+	"params": [ 
+{	"paramname": "textureId" ,"paramtype": "vr::TextureID_t"},
+{	"paramname": "ppTexture" ,"paramtype": "struct vr::RenderModel_TextureMap_t **"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "FreeTexture",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pTexture" ,"paramtype": "struct vr::RenderModel_TextureMap_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "LoadTextureD3D11_Async",
+	"returntype": "vr::EVRRenderModelError",
+	"params": [ 
+{	"paramname": "textureId" ,"paramtype": "vr::TextureID_t"},
+{	"paramname": "pD3D11Device" ,"paramtype": "void *"},
+{	"paramname": "ppD3D11Texture2D" ,"paramtype": "void **"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "LoadIntoTextureD3D11_Async",
+	"returntype": "vr::EVRRenderModelError",
+	"params": [ 
+{	"paramname": "textureId" ,"paramtype": "vr::TextureID_t"},
+{	"paramname": "pDstTexture" ,"paramtype": "void *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "FreeTextureD3D11",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pD3D11Texture2D" ,"paramtype": "void *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetRenderModelName",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "unRenderModelIndex" ,"paramtype": "uint32_t"},
+{	"paramname": "pchRenderModelName" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unRenderModelNameLen" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetRenderModelCount",
+	"returntype": "uint32_t"
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetComponentCount",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchRenderModelName" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetComponentName",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchRenderModelName" ,"paramtype": "const char *"},
+{	"paramname": "unComponentIndex" ,"paramtype": "uint32_t"},
+{	"paramname": "pchComponentName" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unComponentNameLen" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetComponentButtonMask",
+	"returntype": "uint64_t",
+	"params": [ 
+{	"paramname": "pchRenderModelName" ,"paramtype": "const char *"},
+{	"paramname": "pchComponentName" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetComponentRenderModelName",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchRenderModelName" ,"paramtype": "const char *"},
+{	"paramname": "pchComponentName" ,"paramtype": "const char *"},
+{	"paramname": "pchComponentRenderModelName" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unComponentRenderModelNameLen" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetComponentState",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pchRenderModelName" ,"paramtype": "const char *"},
+{	"paramname": "pchComponentName" ,"paramtype": "const char *"},
+{	"paramname": "pControllerState" ,"paramtype": "const vr::VRControllerState_t *"},
+{	"paramname": "pState" ,"paramtype": "const struct vr::RenderModel_ControllerMode_State_t *"},
+{	"paramname": "pComponentState" ,"paramtype": "struct vr::RenderModel_ComponentState_t *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "RenderModelHasComponent",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pchRenderModelName" ,"paramtype": "const char *"},
+{	"paramname": "pchComponentName" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetRenderModelThumbnailURL",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchRenderModelName" ,"paramtype": "const char *"},
+{	"paramname": "pchThumbnailURL" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unThumbnailURLLen" ,"paramtype": "uint32_t"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRRenderModelError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetRenderModelOriginalPath",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchRenderModelName" ,"paramtype": "const char *"},
+{	"paramname": "pchOriginalPath" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unOriginalPathLen" ,"paramtype": "uint32_t"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRRenderModelError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRRenderModels",
+	"methodname": "GetRenderModelErrorNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "error" ,"paramtype": "vr::EVRRenderModelError"}
+	 ]
+}
+,{
+	"classname": "vr::IVRNotifications",
+	"methodname": "CreateNotification",
+	"returntype": "vr::EVRNotificationError",
+	"params": [ 
+{	"paramname": "ulOverlayHandle" ,"paramtype": "vr::VROverlayHandle_t"},
+{	"paramname": "ulUserValue" ,"paramtype": "uint64_t"},
+{	"paramname": "type" ,"paramtype": "vr::EVRNotificationType"},
+{	"paramname": "pchText" ,"paramtype": "const char *"},
+{	"paramname": "style" ,"paramtype": "vr::EVRNotificationStyle"},
+{	"paramname": "pImage" ,"paramtype": "const struct vr::NotificationBitmap_t *"},
+{	"paramname": "pNotificationId" ,"paramtype": "vr::VRNotificationId *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRNotifications",
+	"methodname": "RemoveNotification",
+	"returntype": "vr::EVRNotificationError",
+	"params": [ 
+{	"paramname": "notificationId" ,"paramtype": "vr::VRNotificationId"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "GetSettingsErrorNameFromEnum",
+	"returntype": "const char *",
+	"params": [ 
+{	"paramname": "eError" ,"paramtype": "vr::EVRSettingsError"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "Sync",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "bForce" ,"paramtype": "bool"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "SetBool",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "pchSettingsKey" ,"paramtype": "const char *"},
+{	"paramname": "bValue" ,"paramtype": "bool"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "SetInt32",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "pchSettingsKey" ,"paramtype": "const char *"},
+{	"paramname": "nValue" ,"paramtype": "int32_t"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "SetFloat",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "pchSettingsKey" ,"paramtype": "const char *"},
+{	"paramname": "flValue" ,"paramtype": "float"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "SetString",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "pchSettingsKey" ,"paramtype": "const char *"},
+{	"paramname": "pchValue" ,"paramtype": "const char *"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "GetBool",
+	"returntype": "bool",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "pchSettingsKey" ,"paramtype": "const char *"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "GetInt32",
+	"returntype": "int32_t",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "pchSettingsKey" ,"paramtype": "const char *"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "GetFloat",
+	"returntype": "float",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "pchSettingsKey" ,"paramtype": "const char *"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "GetString",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "pchSettingsKey" ,"paramtype": "const char *"},
+{	"paramname": "pchValue" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "unValueLen" ,"paramtype": "uint32_t"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "RemoveSection",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRSettings",
+	"methodname": "RemoveKeyInSection",
+	"returntype": "void",
+	"params": [ 
+{	"paramname": "pchSection" ,"paramtype": "const char *"},
+{	"paramname": "pchSettingsKey" ,"paramtype": "const char *"},
+{	"paramname": "peError" ,"paramtype": "vr::EVRSettingsError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRScreenshots",
+	"methodname": "RequestScreenshot",
+	"returntype": "vr::EVRScreenshotError",
+	"params": [ 
+{	"paramname": "pOutScreenshotHandle" ,"paramtype": "vr::ScreenshotHandle_t *"},
+{	"paramname": "type" ,"paramtype": "vr::EVRScreenshotType"},
+{	"paramname": "pchPreviewFilename" ,"paramtype": "const char *"},
+{	"paramname": "pchVRFilename" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRScreenshots",
+	"methodname": "HookScreenshot",
+	"returntype": "vr::EVRScreenshotError",
+	"params": [ 
+{	"paramname": "pSupportedTypes" ,"array_count": "numTypes" ,"paramtype": "const vr::EVRScreenshotType *"},
+{	"paramname": "numTypes" ,"paramtype": "int"}
+	 ]
+}
+,{
+	"classname": "vr::IVRScreenshots",
+	"methodname": "GetScreenshotPropertyType",
+	"returntype": "vr::EVRScreenshotType",
+	"params": [ 
+{	"paramname": "screenshotHandle" ,"paramtype": "vr::ScreenshotHandle_t"},
+{	"paramname": "pError" ,"paramtype": "vr::EVRScreenshotError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRScreenshots",
+	"methodname": "GetScreenshotPropertyFilename",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "screenshotHandle" ,"paramtype": "vr::ScreenshotHandle_t"},
+{	"paramname": "filenameType" ,"paramtype": "vr::EVRScreenshotPropertyFilenames"},
+{	"paramname": "pchFilename" ,"out_string": " " ,"paramtype": "char *"},
+{	"paramname": "cchFilename" ,"paramtype": "uint32_t"},
+{	"paramname": "pError" ,"paramtype": "vr::EVRScreenshotError *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRScreenshots",
+	"methodname": "UpdateScreenshotProgress",
+	"returntype": "vr::EVRScreenshotError",
+	"params": [ 
+{	"paramname": "screenshotHandle" ,"paramtype": "vr::ScreenshotHandle_t"},
+{	"paramname": "flProgress" ,"paramtype": "float"}
+	 ]
+}
+,{
+	"classname": "vr::IVRScreenshots",
+	"methodname": "TakeStereoScreenshot",
+	"returntype": "vr::EVRScreenshotError",
+	"params": [ 
+{	"paramname": "pOutScreenshotHandle" ,"paramtype": "vr::ScreenshotHandle_t *"},
+{	"paramname": "pchPreviewFilename" ,"paramtype": "const char *"},
+{	"paramname": "pchVRFilename" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRScreenshots",
+	"methodname": "SubmitScreenshot",
+	"returntype": "vr::EVRScreenshotError",
+	"params": [ 
+{	"paramname": "screenshotHandle" ,"paramtype": "vr::ScreenshotHandle_t"},
+{	"paramname": "type" ,"paramtype": "vr::EVRScreenshotType"},
+{	"paramname": "pchSourcePreviewFilename" ,"paramtype": "const char *"},
+{	"paramname": "pchSourceVRFilename" ,"paramtype": "const char *"}
+	 ]
+}
+,{
+	"classname": "vr::IVRResources",
+	"methodname": "LoadSharedResource",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchResourceName" ,"paramtype": "const char *"},
+{	"paramname": "pchBuffer" ,"paramtype": "char *"},
+{	"paramname": "unBufferLen" ,"paramtype": "uint32_t"}
+	 ]
+}
+,{
+	"classname": "vr::IVRResources",
+	"methodname": "GetResourceFullPath",
+	"returntype": "uint32_t",
+	"params": [ 
+{	"paramname": "pchResourceName" ,"paramtype": "const char *"},
+{	"paramname": "pchResourceTypeDirectory" ,"paramtype": "const char *"},
+{	"paramname": "pchPathBuffer" ,"paramtype": "char *"},
+{	"paramname": "unBufferLen" ,"paramtype": "uint32_t"}
+	 ]
+}
+]
+}
\ No newline at end of file
diff --git a/third_party/openvr/src/headers/openvr_capi.h b/third_party/openvr/src/headers/openvr_capi.h
new file mode 100644
index 0000000..a7ab2cf
--- /dev/null
+++ b/third_party/openvr/src/headers/openvr_capi.h
@@ -0,0 +1,1869 @@
+//======= Copyright (c) Valve Corporation, All rights reserved. ===============
+//
+// Purpose: Header for flatted SteamAPI. Use this for binding to other languages.
+// This file is auto-generated, do not edit it.
+//
+//=============================================================================
+
+#ifndef __OPENVR_API_FLAT_H__
+#define __OPENVR_API_FLAT_H__
+#if defined( _WIN32 ) || defined( __clang__ )
+#pragma once
+#endif
+
+#ifdef __cplusplus
+#define EXTERN_C extern "C"
+#else
+#define EXTERN_C
+#endif
+
+#define OPENVR_FNTABLE_CALLTYPE __stdcall
+
+// OPENVR API export macro
+#if defined( _WIN32 ) && !defined( _X360 )
+	#if defined( OPENVR_API_EXPORTS )
+	#define S_API EXTERN_C __declspec( dllexport )
+	#elif defined( OPENVR_API_NODLL )
+	#define S_API EXTERN_C
+	#else
+	#define S_API extern "C" __declspec( dllimport ) 
+	#endif // OPENVR_API_EXPORTS
+#elif defined( __GNUC__ )
+	#if defined( OPENVR_API_EXPORTS )
+	#define S_API EXTERN_C __attribute__ ((visibility("default")))
+	#else
+	#define S_API EXTERN_C
+	#endif // OPENVR_API_EXPORTS
+#else // !WIN32
+	#if defined( OPENVR_API_EXPORTS )
+	#define S_API EXTERN_C
+	#else
+	#define S_API EXTERN_C
+	#endif // OPENVR_API_EXPORTS
+#endif
+
+#include <stdint.h>
+
+#if defined( __WIN32 )
+typedef char bool;
+#else
+#include <stdbool.h>
+#endif
+
+typedef uint64_t PropertyContainerHandle_t;
+typedef uint32_t PropertyTypeTag_t;
+
+
+// OpenVR Constants
+
+static const unsigned int k_unMaxDriverDebugResponseSize = 32768;
+static const unsigned int k_unTrackedDeviceIndex_Hmd = 0;
+static const unsigned int k_unMaxTrackedDeviceCount = 16;
+static const unsigned int k_unTrackedDeviceIndexOther = 4294967294;
+static const unsigned int k_unTrackedDeviceIndexInvalid = 4294967295;
+static const unsigned long k_ulInvalidPropertyContainer = 0;
+static const unsigned int k_unInvalidPropertyTag = 0;
+static const unsigned int k_unFloatPropertyTag = 1;
+static const unsigned int k_unInt32PropertyTag = 2;
+static const unsigned int k_unUint64PropertyTag = 3;
+static const unsigned int k_unBoolPropertyTag = 4;
+static const unsigned int k_unStringPropertyTag = 5;
+static const unsigned int k_unHmdMatrix34PropertyTag = 20;
+static const unsigned int k_unHmdMatrix44PropertyTag = 21;
+static const unsigned int k_unHmdVector3PropertyTag = 22;
+static const unsigned int k_unHmdVector4PropertyTag = 23;
+static const unsigned int k_unHiddenAreaPropertyTag = 30;
+static const unsigned int k_unOpenVRInternalReserved_Start = 1000;
+static const unsigned int k_unOpenVRInternalReserved_End = 10000;
+static const unsigned int k_unMaxPropertyStringSize = 32768;
+static const unsigned int k_unControllerStateAxisCount = 5;
+static const unsigned long k_ulOverlayHandleInvalid = 0;
+static const unsigned int k_unScreenshotHandleInvalid = 0;
+static const char * IVRSystem_Version = "IVRSystem_015";
+static const char * IVRExtendedDisplay_Version = "IVRExtendedDisplay_001";
+static const char * IVRTrackedCamera_Version = "IVRTrackedCamera_003";
+static const unsigned int k_unMaxApplicationKeyLength = 128;
+static const char * k_pch_MimeType_HomeApp = "vr/home";
+static const char * k_pch_MimeType_GameTheater = "vr/game_theater";
+static const char * IVRApplications_Version = "IVRApplications_006";
+static const char * IVRChaperone_Version = "IVRChaperone_003";
+static const char * IVRChaperoneSetup_Version = "IVRChaperoneSetup_005";
+static const char * IVRCompositor_Version = "IVRCompositor_020";
+static const unsigned int k_unVROverlayMaxKeyLength = 128;
+static const unsigned int k_unVROverlayMaxNameLength = 128;
+static const unsigned int k_unMaxOverlayCount = 64;
+static const unsigned int k_unMaxOverlayIntersectionMaskPrimitivesCount = 32;
+static const char * IVROverlay_Version = "IVROverlay_014";
+static const char * k_pch_Controller_Component_GDC2015 = "gdc2015";
+static const char * k_pch_Controller_Component_Base = "base";
+static const char * k_pch_Controller_Component_Tip = "tip";
+static const char * k_pch_Controller_Component_HandGrip = "handgrip";
+static const char * k_pch_Controller_Component_Status = "status";
+static const char * IVRRenderModels_Version = "IVRRenderModels_005";
+static const unsigned int k_unNotificationTextMaxSize = 256;
+static const char * IVRNotifications_Version = "IVRNotifications_002";
+static const unsigned int k_unMaxSettingsKeyLength = 128;
+static const char * IVRSettings_Version = "IVRSettings_002";
+static const char * k_pch_SteamVR_Section = "steamvr";
+static const char * k_pch_SteamVR_RequireHmd_String = "requireHmd";
+static const char * k_pch_SteamVR_ForcedDriverKey_String = "forcedDriver";
+static const char * k_pch_SteamVR_ForcedHmdKey_String = "forcedHmd";
+static const char * k_pch_SteamVR_DisplayDebug_Bool = "displayDebug";
+static const char * k_pch_SteamVR_DebugProcessPipe_String = "debugProcessPipe";
+static const char * k_pch_SteamVR_EnableDistortion_Bool = "enableDistortion";
+static const char * k_pch_SteamVR_DisplayDebugX_Int32 = "displayDebugX";
+static const char * k_pch_SteamVR_DisplayDebugY_Int32 = "displayDebugY";
+static const char * k_pch_SteamVR_SendSystemButtonToAllApps_Bool = "sendSystemButtonToAllApps";
+static const char * k_pch_SteamVR_LogLevel_Int32 = "loglevel";
+static const char * k_pch_SteamVR_IPD_Float = "ipd";
+static const char * k_pch_SteamVR_Background_String = "background";
+static const char * k_pch_SteamVR_BackgroundUseDomeProjection_Bool = "backgroundUseDomeProjection";
+static const char * k_pch_SteamVR_BackgroundCameraHeight_Float = "backgroundCameraHeight";
+static const char * k_pch_SteamVR_BackgroundDomeRadius_Float = "backgroundDomeRadius";
+static const char * k_pch_SteamVR_GridColor_String = "gridColor";
+static const char * k_pch_SteamVR_PlayAreaColor_String = "playAreaColor";
+static const char * k_pch_SteamVR_ShowStage_Bool = "showStage";
+static const char * k_pch_SteamVR_ActivateMultipleDrivers_Bool = "activateMultipleDrivers";
+static const char * k_pch_SteamVR_DirectMode_Bool = "directMode";
+static const char * k_pch_SteamVR_DirectModeEdidVid_Int32 = "directModeEdidVid";
+static const char * k_pch_SteamVR_DirectModeEdidPid_Int32 = "directModeEdidPid";
+static const char * k_pch_SteamVR_UsingSpeakers_Bool = "usingSpeakers";
+static const char * k_pch_SteamVR_SpeakersForwardYawOffsetDegrees_Float = "speakersForwardYawOffsetDegrees";
+static const char * k_pch_SteamVR_BaseStationPowerManagement_Bool = "basestationPowerManagement";
+static const char * k_pch_SteamVR_NeverKillProcesses_Bool = "neverKillProcesses";
+static const char * k_pch_SteamVR_RenderTargetMultiplier_Float = "renderTargetMultiplier";
+static const char * k_pch_SteamVR_AllowAsyncReprojection_Bool = "allowAsyncReprojection";
+static const char * k_pch_SteamVR_AllowReprojection_Bool = "allowInterleavedReprojection";
+static const char * k_pch_SteamVR_ForceReprojection_Bool = "forceReprojection";
+static const char * k_pch_SteamVR_ForceFadeOnBadTracking_Bool = "forceFadeOnBadTracking";
+static const char * k_pch_SteamVR_DefaultMirrorView_Int32 = "defaultMirrorView";
+static const char * k_pch_SteamVR_ShowMirrorView_Bool = "showMirrorView";
+static const char * k_pch_SteamVR_MirrorViewGeometry_String = "mirrorViewGeometry";
+static const char * k_pch_SteamVR_StartMonitorFromAppLaunch = "startMonitorFromAppLaunch";
+static const char * k_pch_SteamVR_StartCompositorFromAppLaunch_Bool = "startCompositorFromAppLaunch";
+static const char * k_pch_SteamVR_StartDashboardFromAppLaunch_Bool = "startDashboardFromAppLaunch";
+static const char * k_pch_SteamVR_StartOverlayAppsFromDashboard_Bool = "startOverlayAppsFromDashboard";
+static const char * k_pch_SteamVR_EnableHomeApp = "enableHomeApp";
+static const char * k_pch_SteamVR_SetInitialDefaultHomeApp = "setInitialDefaultHomeApp";
+static const char * k_pch_SteamVR_CycleBackgroundImageTimeSec_Int32 = "CycleBackgroundImageTimeSec";
+static const char * k_pch_SteamVR_RetailDemo_Bool = "retailDemo";
+static const char * k_pch_SteamVR_IpdOffset_Float = "ipdOffset";
+static const char * k_pch_Lighthouse_Section = "driver_lighthouse";
+static const char * k_pch_Lighthouse_DisableIMU_Bool = "disableimu";
+static const char * k_pch_Lighthouse_UseDisambiguation_String = "usedisambiguation";
+static const char * k_pch_Lighthouse_DisambiguationDebug_Int32 = "disambiguationdebug";
+static const char * k_pch_Lighthouse_PrimaryBasestation_Int32 = "primarybasestation";
+static const char * k_pch_Lighthouse_DBHistory_Bool = "dbhistory";
+static const char * k_pch_Null_Section = "driver_null";
+static const char * k_pch_Null_SerialNumber_String = "serialNumber";
+static const char * k_pch_Null_ModelNumber_String = "modelNumber";
+static const char * k_pch_Null_WindowX_Int32 = "windowX";
+static const char * k_pch_Null_WindowY_Int32 = "windowY";
+static const char * k_pch_Null_WindowWidth_Int32 = "windowWidth";
+static const char * k_pch_Null_WindowHeight_Int32 = "windowHeight";
+static const char * k_pch_Null_RenderWidth_Int32 = "renderWidth";
+static const char * k_pch_Null_RenderHeight_Int32 = "renderHeight";
+static const char * k_pch_Null_SecondsFromVsyncToPhotons_Float = "secondsFromVsyncToPhotons";
+static const char * k_pch_Null_DisplayFrequency_Float = "displayFrequency";
+static const char * k_pch_UserInterface_Section = "userinterface";
+static const char * k_pch_UserInterface_StatusAlwaysOnTop_Bool = "StatusAlwaysOnTop";
+static const char * k_pch_UserInterface_MinimizeToTray_Bool = "MinimizeToTray";
+static const char * k_pch_UserInterface_Screenshots_Bool = "screenshots";
+static const char * k_pch_UserInterface_ScreenshotType_Int = "screenshotType";
+static const char * k_pch_Notifications_Section = "notifications";
+static const char * k_pch_Notifications_DoNotDisturb_Bool = "DoNotDisturb";
+static const char * k_pch_Keyboard_Section = "keyboard";
+static const char * k_pch_Keyboard_TutorialCompletions = "TutorialCompletions";
+static const char * k_pch_Keyboard_ScaleX = "ScaleX";
+static const char * k_pch_Keyboard_ScaleY = "ScaleY";
+static const char * k_pch_Keyboard_OffsetLeftX = "OffsetLeftX";
+static const char * k_pch_Keyboard_OffsetRightX = "OffsetRightX";
+static const char * k_pch_Keyboard_OffsetY = "OffsetY";
+static const char * k_pch_Keyboard_Smoothing = "Smoothing";
+static const char * k_pch_Perf_Section = "perfcheck";
+static const char * k_pch_Perf_HeuristicActive_Bool = "heuristicActive";
+static const char * k_pch_Perf_NotifyInHMD_Bool = "warnInHMD";
+static const char * k_pch_Perf_NotifyOnlyOnce_Bool = "warnOnlyOnce";
+static const char * k_pch_Perf_AllowTimingStore_Bool = "allowTimingStore";
+static const char * k_pch_Perf_SaveTimingsOnExit_Bool = "saveTimingsOnExit";
+static const char * k_pch_Perf_TestData_Float = "perfTestData";
+static const char * k_pch_CollisionBounds_Section = "collisionBounds";
+static const char * k_pch_CollisionBounds_Style_Int32 = "CollisionBoundsStyle";
+static const char * k_pch_CollisionBounds_GroundPerimeterOn_Bool = "CollisionBoundsGroundPerimeterOn";
+static const char * k_pch_CollisionBounds_CenterMarkerOn_Bool = "CollisionBoundsCenterMarkerOn";
+static const char * k_pch_CollisionBounds_PlaySpaceOn_Bool = "CollisionBoundsPlaySpaceOn";
+static const char * k_pch_CollisionBounds_FadeDistance_Float = "CollisionBoundsFadeDistance";
+static const char * k_pch_CollisionBounds_ColorGammaR_Int32 = "CollisionBoundsColorGammaR";
+static const char * k_pch_CollisionBounds_ColorGammaG_Int32 = "CollisionBoundsColorGammaG";
+static const char * k_pch_CollisionBounds_ColorGammaB_Int32 = "CollisionBoundsColorGammaB";
+static const char * k_pch_CollisionBounds_ColorGammaA_Int32 = "CollisionBoundsColorGammaA";
+static const char * k_pch_Camera_Section = "camera";
+static const char * k_pch_Camera_EnableCamera_Bool = "enableCamera";
+static const char * k_pch_Camera_EnableCameraInDashboard_Bool = "enableCameraInDashboard";
+static const char * k_pch_Camera_EnableCameraForCollisionBounds_Bool = "enableCameraForCollisionBounds";
+static const char * k_pch_Camera_EnableCameraForRoomView_Bool = "enableCameraForRoomView";
+static const char * k_pch_Camera_BoundsColorGammaR_Int32 = "cameraBoundsColorGammaR";
+static const char * k_pch_Camera_BoundsColorGammaG_Int32 = "cameraBoundsColorGammaG";
+static const char * k_pch_Camera_BoundsColorGammaB_Int32 = "cameraBoundsColorGammaB";
+static const char * k_pch_Camera_BoundsColorGammaA_Int32 = "cameraBoundsColorGammaA";
+static const char * k_pch_Camera_BoundsStrength_Int32 = "cameraBoundsStrength";
+static const char * k_pch_audio_Section = "audio";
+static const char * k_pch_audio_OnPlaybackDevice_String = "onPlaybackDevice";
+static const char * k_pch_audio_OnRecordDevice_String = "onRecordDevice";
+static const char * k_pch_audio_OnPlaybackMirrorDevice_String = "onPlaybackMirrorDevice";
+static const char * k_pch_audio_OffPlaybackDevice_String = "offPlaybackDevice";
+static const char * k_pch_audio_OffRecordDevice_String = "offRecordDevice";
+static const char * k_pch_audio_VIVEHDMIGain = "viveHDMIGain";
+static const char * k_pch_Power_Section = "power";
+static const char * k_pch_Power_PowerOffOnExit_Bool = "powerOffOnExit";
+static const char * k_pch_Power_TurnOffScreensTimeout_Float = "turnOffScreensTimeout";
+static const char * k_pch_Power_TurnOffControllersTimeout_Float = "turnOffControllersTimeout";
+static const char * k_pch_Power_ReturnToWatchdogTimeout_Float = "returnToWatchdogTimeout";
+static const char * k_pch_Power_AutoLaunchSteamVROnButtonPress = "autoLaunchSteamVROnButtonPress";
+static const char * k_pch_Dashboard_Section = "dashboard";
+static const char * k_pch_Dashboard_EnableDashboard_Bool = "enableDashboard";
+static const char * k_pch_Dashboard_ArcadeMode_Bool = "arcadeMode";
+static const char * k_pch_modelskin_Section = "modelskins";
+static const char * k_pch_Driver_Enable_Bool = "enable";
+static const char * IVRScreenshots_Version = "IVRScreenshots_001";
+static const char * IVRResources_Version = "IVRResources_001";
+
+// OpenVR Enums
+
+typedef enum EVREye
+{
+	EVREye_Eye_Left = 0,
+	EVREye_Eye_Right = 1,
+} EVREye;
+
+typedef enum ETextureType
+{
+	ETextureType_TextureType_DirectX = 0,
+	ETextureType_TextureType_OpenGL = 1,
+	ETextureType_TextureType_Vulkan = 2,
+	ETextureType_TextureType_IOSurface = 3,
+	ETextureType_TextureType_DirectX12 = 4,
+} ETextureType;
+
+typedef enum EColorSpace
+{
+	EColorSpace_ColorSpace_Auto = 0,
+	EColorSpace_ColorSpace_Gamma = 1,
+	EColorSpace_ColorSpace_Linear = 2,
+} EColorSpace;
+
+typedef enum ETrackingResult
+{
+	ETrackingResult_TrackingResult_Uninitialized = 1,
+	ETrackingResult_TrackingResult_Calibrating_InProgress = 100,
+	ETrackingResult_TrackingResult_Calibrating_OutOfRange = 101,
+	ETrackingResult_TrackingResult_Running_OK = 200,
+	ETrackingResult_TrackingResult_Running_OutOfRange = 201,
+} ETrackingResult;
+
+typedef enum ETrackedDeviceClass
+{
+	ETrackedDeviceClass_TrackedDeviceClass_Invalid = 0,
+	ETrackedDeviceClass_TrackedDeviceClass_HMD = 1,
+	ETrackedDeviceClass_TrackedDeviceClass_Controller = 2,
+	ETrackedDeviceClass_TrackedDeviceClass_GenericTracker = 3,
+	ETrackedDeviceClass_TrackedDeviceClass_TrackingReference = 4,
+} ETrackedDeviceClass;
+
+typedef enum ETrackedControllerRole
+{
+	ETrackedControllerRole_TrackedControllerRole_Invalid = 0,
+	ETrackedControllerRole_TrackedControllerRole_LeftHand = 1,
+	ETrackedControllerRole_TrackedControllerRole_RightHand = 2,
+} ETrackedControllerRole;
+
+typedef enum ETrackingUniverseOrigin
+{
+	ETrackingUniverseOrigin_TrackingUniverseSeated = 0,
+	ETrackingUniverseOrigin_TrackingUniverseStanding = 1,
+	ETrackingUniverseOrigin_TrackingUniverseRawAndUncalibrated = 2,
+} ETrackingUniverseOrigin;
+
+typedef enum ETrackedDeviceProperty
+{
+	ETrackedDeviceProperty_Prop_Invalid = 0,
+	ETrackedDeviceProperty_Prop_TrackingSystemName_String = 1000,
+	ETrackedDeviceProperty_Prop_ModelNumber_String = 1001,
+	ETrackedDeviceProperty_Prop_SerialNumber_String = 1002,
+	ETrackedDeviceProperty_Prop_RenderModelName_String = 1003,
+	ETrackedDeviceProperty_Prop_WillDriftInYaw_Bool = 1004,
+	ETrackedDeviceProperty_Prop_ManufacturerName_String = 1005,
+	ETrackedDeviceProperty_Prop_TrackingFirmwareVersion_String = 1006,
+	ETrackedDeviceProperty_Prop_HardwareRevision_String = 1007,
+	ETrackedDeviceProperty_Prop_AllWirelessDongleDescriptions_String = 1008,
+	ETrackedDeviceProperty_Prop_ConnectedWirelessDongle_String = 1009,
+	ETrackedDeviceProperty_Prop_DeviceIsWireless_Bool = 1010,
+	ETrackedDeviceProperty_Prop_DeviceIsCharging_Bool = 1011,
+	ETrackedDeviceProperty_Prop_DeviceBatteryPercentage_Float = 1012,
+	ETrackedDeviceProperty_Prop_StatusDisplayTransform_Matrix34 = 1013,
+	ETrackedDeviceProperty_Prop_Firmware_UpdateAvailable_Bool = 1014,
+	ETrackedDeviceProperty_Prop_Firmware_ManualUpdate_Bool = 1015,
+	ETrackedDeviceProperty_Prop_Firmware_ManualUpdateURL_String = 1016,
+	ETrackedDeviceProperty_Prop_HardwareRevision_Uint64 = 1017,
+	ETrackedDeviceProperty_Prop_FirmwareVersion_Uint64 = 1018,
+	ETrackedDeviceProperty_Prop_FPGAVersion_Uint64 = 1019,
+	ETrackedDeviceProperty_Prop_VRCVersion_Uint64 = 1020,
+	ETrackedDeviceProperty_Prop_RadioVersion_Uint64 = 1021,
+	ETrackedDeviceProperty_Prop_DongleVersion_Uint64 = 1022,
+	ETrackedDeviceProperty_Prop_BlockServerShutdown_Bool = 1023,
+	ETrackedDeviceProperty_Prop_CanUnifyCoordinateSystemWithHmd_Bool = 1024,
+	ETrackedDeviceProperty_Prop_ContainsProximitySensor_Bool = 1025,
+	ETrackedDeviceProperty_Prop_DeviceProvidesBatteryStatus_Bool = 1026,
+	ETrackedDeviceProperty_Prop_DeviceCanPowerOff_Bool = 1027,
+	ETrackedDeviceProperty_Prop_Firmware_ProgrammingTarget_String = 1028,
+	ETrackedDeviceProperty_Prop_DeviceClass_Int32 = 1029,
+	ETrackedDeviceProperty_Prop_HasCamera_Bool = 1030,
+	ETrackedDeviceProperty_Prop_DriverVersion_String = 1031,
+	ETrackedDeviceProperty_Prop_Firmware_ForceUpdateRequired_Bool = 1032,
+	ETrackedDeviceProperty_Prop_ViveSystemButtonFixRequired_Bool = 1033,
+	ETrackedDeviceProperty_Prop_ParentDriver_Uint64 = 1034,
+	ETrackedDeviceProperty_Prop_ReportsTimeSinceVSync_Bool = 2000,
+	ETrackedDeviceProperty_Prop_SecondsFromVsyncToPhotons_Float = 2001,
+	ETrackedDeviceProperty_Prop_DisplayFrequency_Float = 2002,
+	ETrackedDeviceProperty_Prop_UserIpdMeters_Float = 2003,
+	ETrackedDeviceProperty_Prop_CurrentUniverseId_Uint64 = 2004,
+	ETrackedDeviceProperty_Prop_PreviousUniverseId_Uint64 = 2005,
+	ETrackedDeviceProperty_Prop_DisplayFirmwareVersion_Uint64 = 2006,
+	ETrackedDeviceProperty_Prop_IsOnDesktop_Bool = 2007,
+	ETrackedDeviceProperty_Prop_DisplayMCType_Int32 = 2008,
+	ETrackedDeviceProperty_Prop_DisplayMCOffset_Float = 2009,
+	ETrackedDeviceProperty_Prop_DisplayMCScale_Float = 2010,
+	ETrackedDeviceProperty_Prop_EdidVendorID_Int32 = 2011,
+	ETrackedDeviceProperty_Prop_DisplayMCImageLeft_String = 2012,
+	ETrackedDeviceProperty_Prop_DisplayMCImageRight_String = 2013,
+	ETrackedDeviceProperty_Prop_DisplayGCBlackClamp_Float = 2014,
+	ETrackedDeviceProperty_Prop_EdidProductID_Int32 = 2015,
+	ETrackedDeviceProperty_Prop_CameraToHeadTransform_Matrix34 = 2016,
+	ETrackedDeviceProperty_Prop_DisplayGCType_Int32 = 2017,
+	ETrackedDeviceProperty_Prop_DisplayGCOffset_Float = 2018,
+	ETrackedDeviceProperty_Prop_DisplayGCScale_Float = 2019,
+	ETrackedDeviceProperty_Prop_DisplayGCPrescale_Float = 2020,
+	ETrackedDeviceProperty_Prop_DisplayGCImage_String = 2021,
+	ETrackedDeviceProperty_Prop_LensCenterLeftU_Float = 2022,
+	ETrackedDeviceProperty_Prop_LensCenterLeftV_Float = 2023,
+	ETrackedDeviceProperty_Prop_LensCenterRightU_Float = 2024,
+	ETrackedDeviceProperty_Prop_LensCenterRightV_Float = 2025,
+	ETrackedDeviceProperty_Prop_UserHeadToEyeDepthMeters_Float = 2026,
+	ETrackedDeviceProperty_Prop_CameraFirmwareVersion_Uint64 = 2027,
+	ETrackedDeviceProperty_Prop_CameraFirmwareDescription_String = 2028,
+	ETrackedDeviceProperty_Prop_DisplayFPGAVersion_Uint64 = 2029,
+	ETrackedDeviceProperty_Prop_DisplayBootloaderVersion_Uint64 = 2030,
+	ETrackedDeviceProperty_Prop_DisplayHardwareVersion_Uint64 = 2031,
+	ETrackedDeviceProperty_Prop_AudioFirmwareVersion_Uint64 = 2032,
+	ETrackedDeviceProperty_Prop_CameraCompatibilityMode_Int32 = 2033,
+	ETrackedDeviceProperty_Prop_ScreenshotHorizontalFieldOfViewDegrees_Float = 2034,
+	ETrackedDeviceProperty_Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035,
+	ETrackedDeviceProperty_Prop_DisplaySuppressed_Bool = 2036,
+	ETrackedDeviceProperty_Prop_DisplayAllowNightMode_Bool = 2037,
+	ETrackedDeviceProperty_Prop_DisplayMCImageWidth_Int32 = 2038,
+	ETrackedDeviceProperty_Prop_DisplayMCImageHeight_Int32 = 2039,
+	ETrackedDeviceProperty_Prop_DisplayMCImageNumChannels_Int32 = 2040,
+	ETrackedDeviceProperty_Prop_DisplayMCImageData_Binary = 2041,
+	ETrackedDeviceProperty_Prop_UsesDriverDirectMode_Bool = 2042,
+	ETrackedDeviceProperty_Prop_AttachedDeviceId_String = 3000,
+	ETrackedDeviceProperty_Prop_SupportedButtons_Uint64 = 3001,
+	ETrackedDeviceProperty_Prop_Axis0Type_Int32 = 3002,
+	ETrackedDeviceProperty_Prop_Axis1Type_Int32 = 3003,
+	ETrackedDeviceProperty_Prop_Axis2Type_Int32 = 3004,
+	ETrackedDeviceProperty_Prop_Axis3Type_Int32 = 3005,
+	ETrackedDeviceProperty_Prop_Axis4Type_Int32 = 3006,
+	ETrackedDeviceProperty_Prop_ControllerRoleHint_Int32 = 3007,
+	ETrackedDeviceProperty_Prop_FieldOfViewLeftDegrees_Float = 4000,
+	ETrackedDeviceProperty_Prop_FieldOfViewRightDegrees_Float = 4001,
+	ETrackedDeviceProperty_Prop_FieldOfViewTopDegrees_Float = 4002,
+	ETrackedDeviceProperty_Prop_FieldOfViewBottomDegrees_Float = 4003,
+	ETrackedDeviceProperty_Prop_TrackingRangeMinimumMeters_Float = 4004,
+	ETrackedDeviceProperty_Prop_TrackingRangeMaximumMeters_Float = 4005,
+	ETrackedDeviceProperty_Prop_ModeLabel_String = 4006,
+	ETrackedDeviceProperty_Prop_IconPathName_String = 5000,
+	ETrackedDeviceProperty_Prop_NamedIconPathDeviceOff_String = 5001,
+	ETrackedDeviceProperty_Prop_NamedIconPathDeviceSearching_String = 5002,
+	ETrackedDeviceProperty_Prop_NamedIconPathDeviceSearchingAlert_String = 5003,
+	ETrackedDeviceProperty_Prop_NamedIconPathDeviceReady_String = 5004,
+	ETrackedDeviceProperty_Prop_NamedIconPathDeviceReadyAlert_String = 5005,
+	ETrackedDeviceProperty_Prop_NamedIconPathDeviceNotReady_String = 5006,
+	ETrackedDeviceProperty_Prop_NamedIconPathDeviceStandby_String = 5007,
+	ETrackedDeviceProperty_Prop_NamedIconPathDeviceAlertLow_String = 5008,
+	ETrackedDeviceProperty_Prop_DisplayHiddenArea_Binary_Start = 5100,
+	ETrackedDeviceProperty_Prop_DisplayHiddenArea_Binary_End = 5150,
+	ETrackedDeviceProperty_Prop_UserConfigPath_String = 6000,
+	ETrackedDeviceProperty_Prop_InstallPath_String = 6001,
+	ETrackedDeviceProperty_Prop_VendorSpecific_Reserved_Start = 10000,
+	ETrackedDeviceProperty_Prop_VendorSpecific_Reserved_End = 10999,
+} ETrackedDeviceProperty;
+
+typedef enum ETrackedPropertyError
+{
+	ETrackedPropertyError_TrackedProp_Success = 0,
+	ETrackedPropertyError_TrackedProp_WrongDataType = 1,
+	ETrackedPropertyError_TrackedProp_WrongDeviceClass = 2,
+	ETrackedPropertyError_TrackedProp_BufferTooSmall = 3,
+	ETrackedPropertyError_TrackedProp_UnknownProperty = 4,
+	ETrackedPropertyError_TrackedProp_InvalidDevice = 5,
+	ETrackedPropertyError_TrackedProp_CouldNotContactServer = 6,
+	ETrackedPropertyError_TrackedProp_ValueNotProvidedByDevice = 7,
+	ETrackedPropertyError_TrackedProp_StringExceedsMaximumLength = 8,
+	ETrackedPropertyError_TrackedProp_NotYetAvailable = 9,
+	ETrackedPropertyError_TrackedProp_PermissionDenied = 10,
+	ETrackedPropertyError_TrackedProp_InvalidOperation = 11,
+} ETrackedPropertyError;
+
+typedef enum EVRSubmitFlags
+{
+	EVRSubmitFlags_Submit_Default = 0,
+	EVRSubmitFlags_Submit_LensDistortionAlreadyApplied = 1,
+	EVRSubmitFlags_Submit_GlRenderBuffer = 2,
+	EVRSubmitFlags_Submit_Reserved = 4,
+} EVRSubmitFlags;
+
+typedef enum EVRState
+{
+	EVRState_VRState_Undefined = -1,
+	EVRState_VRState_Off = 0,
+	EVRState_VRState_Searching = 1,
+	EVRState_VRState_Searching_Alert = 2,
+	EVRState_VRState_Ready = 3,
+	EVRState_VRState_Ready_Alert = 4,
+	EVRState_VRState_NotReady = 5,
+	EVRState_VRState_Standby = 6,
+	EVRState_VRState_Ready_Alert_Low = 7,
+} EVRState;
+
+typedef enum EVREventType
+{
+	EVREventType_VREvent_None = 0,
+	EVREventType_VREvent_TrackedDeviceActivated = 100,
+	EVREventType_VREvent_TrackedDeviceDeactivated = 101,
+	EVREventType_VREvent_TrackedDeviceUpdated = 102,
+	EVREventType_VREvent_TrackedDeviceUserInteractionStarted = 103,
+	EVREventType_VREvent_TrackedDeviceUserInteractionEnded = 104,
+	EVREventType_VREvent_IpdChanged = 105,
+	EVREventType_VREvent_EnterStandbyMode = 106,
+	EVREventType_VREvent_LeaveStandbyMode = 107,
+	EVREventType_VREvent_TrackedDeviceRoleChanged = 108,
+	EVREventType_VREvent_WatchdogWakeUpRequested = 109,
+	EVREventType_VREvent_LensDistortionChanged = 110,
+	EVREventType_VREvent_PropertyChanged = 111,
+	EVREventType_VREvent_ButtonPress = 200,
+	EVREventType_VREvent_ButtonUnpress = 201,
+	EVREventType_VREvent_ButtonTouch = 202,
+	EVREventType_VREvent_ButtonUntouch = 203,
+	EVREventType_VREvent_MouseMove = 300,
+	EVREventType_VREvent_MouseButtonDown = 301,
+	EVREventType_VREvent_MouseButtonUp = 302,
+	EVREventType_VREvent_FocusEnter = 303,
+	EVREventType_VREvent_FocusLeave = 304,
+	EVREventType_VREvent_Scroll = 305,
+	EVREventType_VREvent_TouchPadMove = 306,
+	EVREventType_VREvent_OverlayFocusChanged = 307,
+	EVREventType_VREvent_InputFocusCaptured = 400,
+	EVREventType_VREvent_InputFocusReleased = 401,
+	EVREventType_VREvent_SceneFocusLost = 402,
+	EVREventType_VREvent_SceneFocusGained = 403,
+	EVREventType_VREvent_SceneApplicationChanged = 404,
+	EVREventType_VREvent_SceneFocusChanged = 405,
+	EVREventType_VREvent_InputFocusChanged = 406,
+	EVREventType_VREvent_SceneApplicationSecondaryRenderingStarted = 407,
+	EVREventType_VREvent_HideRenderModels = 410,
+	EVREventType_VREvent_ShowRenderModels = 411,
+	EVREventType_VREvent_OverlayShown = 500,
+	EVREventType_VREvent_OverlayHidden = 501,
+	EVREventType_VREvent_DashboardActivated = 502,
+	EVREventType_VREvent_DashboardDeactivated = 503,
+	EVREventType_VREvent_DashboardThumbSelected = 504,
+	EVREventType_VREvent_DashboardRequested = 505,
+	EVREventType_VREvent_ResetDashboard = 506,
+	EVREventType_VREvent_RenderToast = 507,
+	EVREventType_VREvent_ImageLoaded = 508,
+	EVREventType_VREvent_ShowKeyboard = 509,
+	EVREventType_VREvent_HideKeyboard = 510,
+	EVREventType_VREvent_OverlayGamepadFocusGained = 511,
+	EVREventType_VREvent_OverlayGamepadFocusLost = 512,
+	EVREventType_VREvent_OverlaySharedTextureChanged = 513,
+	EVREventType_VREvent_DashboardGuideButtonDown = 514,
+	EVREventType_VREvent_DashboardGuideButtonUp = 515,
+	EVREventType_VREvent_ScreenshotTriggered = 516,
+	EVREventType_VREvent_ImageFailed = 517,
+	EVREventType_VREvent_DashboardOverlayCreated = 518,
+	EVREventType_VREvent_RequestScreenshot = 520,
+	EVREventType_VREvent_ScreenshotTaken = 521,
+	EVREventType_VREvent_ScreenshotFailed = 522,
+	EVREventType_VREvent_SubmitScreenshotToDashboard = 523,
+	EVREventType_VREvent_ScreenshotProgressToDashboard = 524,
+	EVREventType_VREvent_PrimaryDashboardDeviceChanged = 525,
+	EVREventType_VREvent_Notification_Shown = 600,
+	EVREventType_VREvent_Notification_Hidden = 601,
+	EVREventType_VREvent_Notification_BeginInteraction = 602,
+	EVREventType_VREvent_Notification_Destroyed = 603,
+	EVREventType_VREvent_Quit = 700,
+	EVREventType_VREvent_ProcessQuit = 701,
+	EVREventType_VREvent_QuitAborted_UserPrompt = 702,
+	EVREventType_VREvent_QuitAcknowledged = 703,
+	EVREventType_VREvent_DriverRequestedQuit = 704,
+	EVREventType_VREvent_ChaperoneDataHasChanged = 800,
+	EVREventType_VREvent_ChaperoneUniverseHasChanged = 801,
+	EVREventType_VREvent_ChaperoneTempDataHasChanged = 802,
+	EVREventType_VREvent_ChaperoneSettingsHaveChanged = 803,
+	EVREventType_VREvent_SeatedZeroPoseReset = 804,
+	EVREventType_VREvent_AudioSettingsHaveChanged = 820,
+	EVREventType_VREvent_BackgroundSettingHasChanged = 850,
+	EVREventType_VREvent_CameraSettingsHaveChanged = 851,
+	EVREventType_VREvent_ReprojectionSettingHasChanged = 852,
+	EVREventType_VREvent_ModelSkinSettingsHaveChanged = 853,
+	EVREventType_VREvent_EnvironmentSettingsHaveChanged = 854,
+	EVREventType_VREvent_PowerSettingsHaveChanged = 855,
+	EVREventType_VREvent_StatusUpdate = 900,
+	EVREventType_VREvent_MCImageUpdated = 1000,
+	EVREventType_VREvent_FirmwareUpdateStarted = 1100,
+	EVREventType_VREvent_FirmwareUpdateFinished = 1101,
+	EVREventType_VREvent_KeyboardClosed = 1200,
+	EVREventType_VREvent_KeyboardCharInput = 1201,
+	EVREventType_VREvent_KeyboardDone = 1202,
+	EVREventType_VREvent_ApplicationTransitionStarted = 1300,
+	EVREventType_VREvent_ApplicationTransitionAborted = 1301,
+	EVREventType_VREvent_ApplicationTransitionNewAppStarted = 1302,
+	EVREventType_VREvent_ApplicationListUpdated = 1303,
+	EVREventType_VREvent_ApplicationMimeTypeLoad = 1304,
+	EVREventType_VREvent_ApplicationTransitionNewAppLaunchComplete = 1305,
+	EVREventType_VREvent_Compositor_MirrorWindowShown = 1400,
+	EVREventType_VREvent_Compositor_MirrorWindowHidden = 1401,
+	EVREventType_VREvent_Compositor_ChaperoneBoundsShown = 1410,
+	EVREventType_VREvent_Compositor_ChaperoneBoundsHidden = 1411,
+	EVREventType_VREvent_TrackedCamera_StartVideoStream = 1500,
+	EVREventType_VREvent_TrackedCamera_StopVideoStream = 1501,
+	EVREventType_VREvent_TrackedCamera_PauseVideoStream = 1502,
+	EVREventType_VREvent_TrackedCamera_ResumeVideoStream = 1503,
+	EVREventType_VREvent_TrackedCamera_EditingSurface = 1550,
+	EVREventType_VREvent_PerformanceTest_EnableCapture = 1600,
+	EVREventType_VREvent_PerformanceTest_DisableCapture = 1601,
+	EVREventType_VREvent_PerformanceTest_FidelityLevel = 1602,
+	EVREventType_VREvent_MessageOverlay_Closed = 1650,
+	EVREventType_VREvent_VendorSpecific_Reserved_Start = 10000,
+	EVREventType_VREvent_VendorSpecific_Reserved_End = 19999,
+} EVREventType;
+
+typedef enum EDeviceActivityLevel
+{
+	EDeviceActivityLevel_k_EDeviceActivityLevel_Unknown = -1,
+	EDeviceActivityLevel_k_EDeviceActivityLevel_Idle = 0,
+	EDeviceActivityLevel_k_EDeviceActivityLevel_UserInteraction = 1,
+	EDeviceActivityLevel_k_EDeviceActivityLevel_UserInteraction_Timeout = 2,
+	EDeviceActivityLevel_k_EDeviceActivityLevel_Standby = 3,
+} EDeviceActivityLevel;
+
+typedef enum EVRButtonId
+{
+	EVRButtonId_k_EButton_System = 0,
+	EVRButtonId_k_EButton_ApplicationMenu = 1,
+	EVRButtonId_k_EButton_Grip = 2,
+	EVRButtonId_k_EButton_DPad_Left = 3,
+	EVRButtonId_k_EButton_DPad_Up = 4,
+	EVRButtonId_k_EButton_DPad_Right = 5,
+	EVRButtonId_k_EButton_DPad_Down = 6,
+	EVRButtonId_k_EButton_A = 7,
+	EVRButtonId_k_EButton_ProximitySensor = 31,
+	EVRButtonId_k_EButton_Axis0 = 32,
+	EVRButtonId_k_EButton_Axis1 = 33,
+	EVRButtonId_k_EButton_Axis2 = 34,
+	EVRButtonId_k_EButton_Axis3 = 35,
+	EVRButtonId_k_EButton_Axis4 = 36,
+	EVRButtonId_k_EButton_SteamVR_Touchpad = 32,
+	EVRButtonId_k_EButton_SteamVR_Trigger = 33,
+	EVRButtonId_k_EButton_Dashboard_Back = 2,
+	EVRButtonId_k_EButton_Max = 64,
+} EVRButtonId;
+
+typedef enum EVRMouseButton
+{
+	EVRMouseButton_VRMouseButton_Left = 1,
+	EVRMouseButton_VRMouseButton_Right = 2,
+	EVRMouseButton_VRMouseButton_Middle = 4,
+} EVRMouseButton;
+
+typedef enum EHiddenAreaMeshType
+{
+	EHiddenAreaMeshType_k_eHiddenAreaMesh_Standard = 0,
+	EHiddenAreaMeshType_k_eHiddenAreaMesh_Inverse = 1,
+	EHiddenAreaMeshType_k_eHiddenAreaMesh_LineLoop = 2,
+	EHiddenAreaMeshType_k_eHiddenAreaMesh_Max = 3,
+} EHiddenAreaMeshType;
+
+typedef enum EVRControllerAxisType
+{
+	EVRControllerAxisType_k_eControllerAxis_None = 0,
+	EVRControllerAxisType_k_eControllerAxis_TrackPad = 1,
+	EVRControllerAxisType_k_eControllerAxis_Joystick = 2,
+	EVRControllerAxisType_k_eControllerAxis_Trigger = 3,
+} EVRControllerAxisType;
+
+typedef enum EVRControllerEventOutputType
+{
+	EVRControllerEventOutputType_ControllerEventOutput_OSEvents = 0,
+	EVRControllerEventOutputType_ControllerEventOutput_VREvents = 1,
+} EVRControllerEventOutputType;
+
+typedef enum ECollisionBoundsStyle
+{
+	ECollisionBoundsStyle_COLLISION_BOUNDS_STYLE_BEGINNER = 0,
+	ECollisionBoundsStyle_COLLISION_BOUNDS_STYLE_INTERMEDIATE = 1,
+	ECollisionBoundsStyle_COLLISION_BOUNDS_STYLE_SQUARES = 2,
+	ECollisionBoundsStyle_COLLISION_BOUNDS_STYLE_ADVANCED = 3,
+	ECollisionBoundsStyle_COLLISION_BOUNDS_STYLE_NONE = 4,
+	ECollisionBoundsStyle_COLLISION_BOUNDS_STYLE_COUNT = 5,
+} ECollisionBoundsStyle;
+
+typedef enum EVROverlayError
+{
+	EVROverlayError_VROverlayError_None = 0,
+	EVROverlayError_VROverlayError_UnknownOverlay = 10,
+	EVROverlayError_VROverlayError_InvalidHandle = 11,
+	EVROverlayError_VROverlayError_PermissionDenied = 12,
+	EVROverlayError_VROverlayError_OverlayLimitExceeded = 13,
+	EVROverlayError_VROverlayError_WrongVisibilityType = 14,
+	EVROverlayError_VROverlayError_KeyTooLong = 15,
+	EVROverlayError_VROverlayError_NameTooLong = 16,
+	EVROverlayError_VROverlayError_KeyInUse = 17,
+	EVROverlayError_VROverlayError_WrongTransformType = 18,
+	EVROverlayError_VROverlayError_InvalidTrackedDevice = 19,
+	EVROverlayError_VROverlayError_InvalidParameter = 20,
+	EVROverlayError_VROverlayError_ThumbnailCantBeDestroyed = 21,
+	EVROverlayError_VROverlayError_ArrayTooSmall = 22,
+	EVROverlayError_VROverlayError_RequestFailed = 23,
+	EVROverlayError_VROverlayError_InvalidTexture = 24,
+	EVROverlayError_VROverlayError_UnableToLoadFile = 25,
+	EVROverlayError_VROverlayError_KeyboardAlreadyInUse = 26,
+	EVROverlayError_VROverlayError_NoNeighbor = 27,
+	EVROverlayError_VROverlayError_TooManyMaskPrimitives = 29,
+	EVROverlayError_VROverlayError_BadMaskPrimitive = 30,
+} EVROverlayError;
+
+typedef enum EVRApplicationType
+{
+	EVRApplicationType_VRApplication_Other = 0,
+	EVRApplicationType_VRApplication_Scene = 1,
+	EVRApplicationType_VRApplication_Overlay = 2,
+	EVRApplicationType_VRApplication_Background = 3,
+	EVRApplicationType_VRApplication_Utility = 4,
+	EVRApplicationType_VRApplication_VRMonitor = 5,
+	EVRApplicationType_VRApplication_SteamWatchdog = 6,
+	EVRApplicationType_VRApplication_Max = 7,
+} EVRApplicationType;
+
+typedef enum EVRFirmwareError
+{
+	EVRFirmwareError_VRFirmwareError_None = 0,
+	EVRFirmwareError_VRFirmwareError_Success = 1,
+	EVRFirmwareError_VRFirmwareError_Fail = 2,
+} EVRFirmwareError;
+
+typedef enum EVRNotificationError
+{
+	EVRNotificationError_VRNotificationError_OK = 0,
+	EVRNotificationError_VRNotificationError_InvalidNotificationId = 100,
+	EVRNotificationError_VRNotificationError_NotificationQueueFull = 101,
+	EVRNotificationError_VRNotificationError_InvalidOverlayHandle = 102,
+	EVRNotificationError_VRNotificationError_SystemWithUserValueAlreadyExists = 103,
+} EVRNotificationError;
+
+typedef enum EVRInitError
+{
+	EVRInitError_VRInitError_None = 0,
+	EVRInitError_VRInitError_Unknown = 1,
+	EVRInitError_VRInitError_Init_InstallationNotFound = 100,
+	EVRInitError_VRInitError_Init_InstallationCorrupt = 101,
+	EVRInitError_VRInitError_Init_VRClientDLLNotFound = 102,
+	EVRInitError_VRInitError_Init_FileNotFound = 103,
+	EVRInitError_VRInitError_Init_FactoryNotFound = 104,
+	EVRInitError_VRInitError_Init_InterfaceNotFound = 105,
+	EVRInitError_VRInitError_Init_InvalidInterface = 106,
+	EVRInitError_VRInitError_Init_UserConfigDirectoryInvalid = 107,
+	EVRInitError_VRInitError_Init_HmdNotFound = 108,
+	EVRInitError_VRInitError_Init_NotInitialized = 109,
+	EVRInitError_VRInitError_Init_PathRegistryNotFound = 110,
+	EVRInitError_VRInitError_Init_NoConfigPath = 111,
+	EVRInitError_VRInitError_Init_NoLogPath = 112,
+	EVRInitError_VRInitError_Init_PathRegistryNotWritable = 113,
+	EVRInitError_VRInitError_Init_AppInfoInitFailed = 114,
+	EVRInitError_VRInitError_Init_Retry = 115,
+	EVRInitError_VRInitError_Init_InitCanceledByUser = 116,
+	EVRInitError_VRInitError_Init_AnotherAppLaunching = 117,
+	EVRInitError_VRInitError_Init_SettingsInitFailed = 118,
+	EVRInitError_VRInitError_Init_ShuttingDown = 119,
+	EVRInitError_VRInitError_Init_TooManyObjects = 120,
+	EVRInitError_VRInitError_Init_NoServerForBackgroundApp = 121,
+	EVRInitError_VRInitError_Init_NotSupportedWithCompositor = 122,
+	EVRInitError_VRInitError_Init_NotAvailableToUtilityApps = 123,
+	EVRInitError_VRInitError_Init_Internal = 124,
+	EVRInitError_VRInitError_Init_HmdDriverIdIsNone = 125,
+	EVRInitError_VRInitError_Init_HmdNotFoundPresenceFailed = 126,
+	EVRInitError_VRInitError_Init_VRMonitorNotFound = 127,
+	EVRInitError_VRInitError_Init_VRMonitorStartupFailed = 128,
+	EVRInitError_VRInitError_Init_LowPowerWatchdogNotSupported = 129,
+	EVRInitError_VRInitError_Init_InvalidApplicationType = 130,
+	EVRInitError_VRInitError_Init_NotAvailableToWatchdogApps = 131,
+	EVRInitError_VRInitError_Init_WatchdogDisabledInSettings = 132,
+	EVRInitError_VRInitError_Init_VRDashboardNotFound = 133,
+	EVRInitError_VRInitError_Init_VRDashboardStartupFailed = 134,
+	EVRInitError_VRInitError_Driver_Failed = 200,
+	EVRInitError_VRInitError_Driver_Unknown = 201,
+	EVRInitError_VRInitError_Driver_HmdUnknown = 202,
+	EVRInitError_VRInitError_Driver_NotLoaded = 203,
+	EVRInitError_VRInitError_Driver_RuntimeOutOfDate = 204,
+	EVRInitError_VRInitError_Driver_HmdInUse = 205,
+	EVRInitError_VRInitError_Driver_NotCalibrated = 206,
+	EVRInitError_VRInitError_Driver_CalibrationInvalid = 207,
+	EVRInitError_VRInitError_Driver_HmdDisplayNotFound = 208,
+	EVRInitError_VRInitError_Driver_TrackedDeviceInterfaceUnknown = 209,
+	EVRInitError_VRInitError_Driver_HmdDriverIdOutOfBounds = 211,
+	EVRInitError_VRInitError_Driver_HmdDisplayMirrored = 212,
+	EVRInitError_VRInitError_IPC_ServerInitFailed = 300,
+	EVRInitError_VRInitError_IPC_ConnectFailed = 301,
+	EVRInitError_VRInitError_IPC_SharedStateInitFailed = 302,
+	EVRInitError_VRInitError_IPC_CompositorInitFailed = 303,
+	EVRInitError_VRInitError_IPC_MutexInitFailed = 304,
+	EVRInitError_VRInitError_IPC_Failed = 305,
+	EVRInitError_VRInitError_IPC_CompositorConnectFailed = 306,
+	EVRInitError_VRInitError_IPC_CompositorInvalidConnectResponse = 307,
+	EVRInitError_VRInitError_IPC_ConnectFailedAfterMultipleAttempts = 308,
+	EVRInitError_VRInitError_Compositor_Failed = 400,
+	EVRInitError_VRInitError_Compositor_D3D11HardwareRequired = 401,
+	EVRInitError_VRInitError_Compositor_FirmwareRequiresUpdate = 402,
+	EVRInitError_VRInitError_Compositor_OverlayInitFailed = 403,
+	EVRInitError_VRInitError_Compositor_ScreenshotsInitFailed = 404,
+	EVRInitError_VRInitError_VendorSpecific_UnableToConnectToOculusRuntime = 1000,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_CantOpenDevice = 1101,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart = 1102,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_NoStoredConfig = 1103,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_ConfigTooBig = 1104,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_ConfigTooSmall = 1105,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_UnableToInitZLib = 1106,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion = 1107,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart = 1108,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart = 1109,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext = 1110,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_UserDataAddressRange = 1111,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_UserDataError = 1112,
+	EVRInitError_VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck = 1113,
+	EVRInitError_VRInitError_Steam_SteamInstallationNotFound = 2000,
+} EVRInitError;
+
+typedef enum EVRScreenshotType
+{
+	EVRScreenshotType_VRScreenshotType_None = 0,
+	EVRScreenshotType_VRScreenshotType_Mono = 1,
+	EVRScreenshotType_VRScreenshotType_Stereo = 2,
+	EVRScreenshotType_VRScreenshotType_Cubemap = 3,
+	EVRScreenshotType_VRScreenshotType_MonoPanorama = 4,
+	EVRScreenshotType_VRScreenshotType_StereoPanorama = 5,
+} EVRScreenshotType;
+
+typedef enum EVRScreenshotPropertyFilenames
+{
+	EVRScreenshotPropertyFilenames_VRScreenshotPropertyFilenames_Preview = 0,
+	EVRScreenshotPropertyFilenames_VRScreenshotPropertyFilenames_VR = 1,
+} EVRScreenshotPropertyFilenames;
+
+typedef enum EVRTrackedCameraError
+{
+	EVRTrackedCameraError_VRTrackedCameraError_None = 0,
+	EVRTrackedCameraError_VRTrackedCameraError_OperationFailed = 100,
+	EVRTrackedCameraError_VRTrackedCameraError_InvalidHandle = 101,
+	EVRTrackedCameraError_VRTrackedCameraError_InvalidFrameHeaderVersion = 102,
+	EVRTrackedCameraError_VRTrackedCameraError_OutOfHandles = 103,
+	EVRTrackedCameraError_VRTrackedCameraError_IPCFailure = 104,
+	EVRTrackedCameraError_VRTrackedCameraError_NotSupportedForThisDevice = 105,
+	EVRTrackedCameraError_VRTrackedCameraError_SharedMemoryFailure = 106,
+	EVRTrackedCameraError_VRTrackedCameraError_FrameBufferingFailure = 107,
+	EVRTrackedCameraError_VRTrackedCameraError_StreamSetupFailure = 108,
+	EVRTrackedCameraError_VRTrackedCameraError_InvalidGLTextureId = 109,
+	EVRTrackedCameraError_VRTrackedCameraError_InvalidSharedTextureHandle = 110,
+	EVRTrackedCameraError_VRTrackedCameraError_FailedToGetGLTextureId = 111,
+	EVRTrackedCameraError_VRTrackedCameraError_SharedTextureFailure = 112,
+	EVRTrackedCameraError_VRTrackedCameraError_NoFrameAvailable = 113,
+	EVRTrackedCameraError_VRTrackedCameraError_InvalidArgument = 114,
+	EVRTrackedCameraError_VRTrackedCameraError_InvalidFrameBufferSize = 115,
+} EVRTrackedCameraError;
+
+typedef enum EVRTrackedCameraFrameType
+{
+	EVRTrackedCameraFrameType_VRTrackedCameraFrameType_Distorted = 0,
+	EVRTrackedCameraFrameType_VRTrackedCameraFrameType_Undistorted = 1,
+	EVRTrackedCameraFrameType_VRTrackedCameraFrameType_MaximumUndistorted = 2,
+	EVRTrackedCameraFrameType_MAX_CAMERA_FRAME_TYPES = 3,
+} EVRTrackedCameraFrameType;
+
+typedef enum EVRApplicationError
+{
+	EVRApplicationError_VRApplicationError_None = 0,
+	EVRApplicationError_VRApplicationError_AppKeyAlreadyExists = 100,
+	EVRApplicationError_VRApplicationError_NoManifest = 101,
+	EVRApplicationError_VRApplicationError_NoApplication = 102,
+	EVRApplicationError_VRApplicationError_InvalidIndex = 103,
+	EVRApplicationError_VRApplicationError_UnknownApplication = 104,
+	EVRApplicationError_VRApplicationError_IPCFailed = 105,
+	EVRApplicationError_VRApplicationError_ApplicationAlreadyRunning = 106,
+	EVRApplicationError_VRApplicationError_InvalidManifest = 107,
+	EVRApplicationError_VRApplicationError_InvalidApplication = 108,
+	EVRApplicationError_VRApplicationError_LaunchFailed = 109,
+	EVRApplicationError_VRApplicationError_ApplicationAlreadyStarting = 110,
+	EVRApplicationError_VRApplicationError_LaunchInProgress = 111,
+	EVRApplicationError_VRApplicationError_OldApplicationQuitting = 112,
+	EVRApplicationError_VRApplicationError_TransitionAborted = 113,
+	EVRApplicationError_VRApplicationError_IsTemplate = 114,
+	EVRApplicationError_VRApplicationError_BufferTooSmall = 200,
+	EVRApplicationError_VRApplicationError_PropertyNotSet = 201,
+	EVRApplicationError_VRApplicationError_UnknownProperty = 202,
+	EVRApplicationError_VRApplicationError_InvalidParameter = 203,
+} EVRApplicationError;
+
+typedef enum EVRApplicationProperty
+{
+	EVRApplicationProperty_VRApplicationProperty_Name_String = 0,
+	EVRApplicationProperty_VRApplicationProperty_LaunchType_String = 11,
+	EVRApplicationProperty_VRApplicationProperty_WorkingDirectory_String = 12,
+	EVRApplicationProperty_VRApplicationProperty_BinaryPath_String = 13,
+	EVRApplicationProperty_VRApplicationProperty_Arguments_String = 14,
+	EVRApplicationProperty_VRApplicationProperty_URL_String = 15,
+	EVRApplicationProperty_VRApplicationProperty_Description_String = 50,
+	EVRApplicationProperty_VRApplicationProperty_NewsURL_String = 51,
+	EVRApplicationProperty_VRApplicationProperty_ImagePath_String = 52,
+	EVRApplicationProperty_VRApplicationProperty_Source_String = 53,
+	EVRApplicationProperty_VRApplicationProperty_IsDashboardOverlay_Bool = 60,
+	EVRApplicationProperty_VRApplicationProperty_IsTemplate_Bool = 61,
+	EVRApplicationProperty_VRApplicationProperty_IsInstanced_Bool = 62,
+	EVRApplicationProperty_VRApplicationProperty_IsInternal_Bool = 63,
+	EVRApplicationProperty_VRApplicationProperty_LastLaunchTime_Uint64 = 70,
+} EVRApplicationProperty;
+
+typedef enum EVRApplicationTransitionState
+{
+	EVRApplicationTransitionState_VRApplicationTransition_None = 0,
+	EVRApplicationTransitionState_VRApplicationTransition_OldAppQuitSent = 10,
+	EVRApplicationTransitionState_VRApplicationTransition_WaitingForExternalLaunch = 11,
+	EVRApplicationTransitionState_VRApplicationTransition_NewAppLaunched = 20,
+} EVRApplicationTransitionState;
+
+typedef enum ChaperoneCalibrationState
+{
+	ChaperoneCalibrationState_OK = 1,
+	ChaperoneCalibrationState_Warning = 100,
+	ChaperoneCalibrationState_Warning_BaseStationMayHaveMoved = 101,
+	ChaperoneCalibrationState_Warning_BaseStationRemoved = 102,
+	ChaperoneCalibrationState_Warning_SeatedBoundsInvalid = 103,
+	ChaperoneCalibrationState_Error = 200,
+	ChaperoneCalibrationState_Error_BaseStationUninitialized = 201,
+	ChaperoneCalibrationState_Error_BaseStationConflict = 202,
+	ChaperoneCalibrationState_Error_PlayAreaInvalid = 203,
+	ChaperoneCalibrationState_Error_CollisionBoundsInvalid = 204,
+} ChaperoneCalibrationState;
+
+typedef enum EChaperoneConfigFile
+{
+	EChaperoneConfigFile_Live = 1,
+	EChaperoneConfigFile_Temp = 2,
+} EChaperoneConfigFile;
+
+typedef enum EChaperoneImportFlags
+{
+	EChaperoneImportFlags_EChaperoneImport_BoundsOnly = 1,
+} EChaperoneImportFlags;
+
+typedef enum EVRCompositorError
+{
+	EVRCompositorError_VRCompositorError_None = 0,
+	EVRCompositorError_VRCompositorError_RequestFailed = 1,
+	EVRCompositorError_VRCompositorError_IncompatibleVersion = 100,
+	EVRCompositorError_VRCompositorError_DoNotHaveFocus = 101,
+	EVRCompositorError_VRCompositorError_InvalidTexture = 102,
+	EVRCompositorError_VRCompositorError_IsNotSceneApplication = 103,
+	EVRCompositorError_VRCompositorError_TextureIsOnWrongDevice = 104,
+	EVRCompositorError_VRCompositorError_TextureUsesUnsupportedFormat = 105,
+	EVRCompositorError_VRCompositorError_SharedTexturesNotSupported = 106,
+	EVRCompositorError_VRCompositorError_IndexOutOfRange = 107,
+	EVRCompositorError_VRCompositorError_AlreadySubmitted = 108,
+} EVRCompositorError;
+
+typedef enum VROverlayInputMethod
+{
+	VROverlayInputMethod_None = 0,
+	VROverlayInputMethod_Mouse = 1,
+} VROverlayInputMethod;
+
+typedef enum VROverlayTransformType
+{
+	VROverlayTransformType_VROverlayTransform_Absolute = 0,
+	VROverlayTransformType_VROverlayTransform_TrackedDeviceRelative = 1,
+	VROverlayTransformType_VROverlayTransform_SystemOverlay = 2,
+	VROverlayTransformType_VROverlayTransform_TrackedComponent = 3,
+} VROverlayTransformType;
+
+typedef enum VROverlayFlags
+{
+	VROverlayFlags_None = 0,
+	VROverlayFlags_Curved = 1,
+	VROverlayFlags_RGSS4X = 2,
+	VROverlayFlags_NoDashboardTab = 3,
+	VROverlayFlags_AcceptsGamepadEvents = 4,
+	VROverlayFlags_ShowGamepadFocus = 5,
+	VROverlayFlags_SendVRScrollEvents = 6,
+	VROverlayFlags_SendVRTouchpadEvents = 7,
+	VROverlayFlags_ShowTouchPadScrollWheel = 8,
+	VROverlayFlags_TransferOwnershipToInternalProcess = 9,
+	VROverlayFlags_SideBySide_Parallel = 10,
+	VROverlayFlags_SideBySide_Crossed = 11,
+	VROverlayFlags_Panorama = 12,
+	VROverlayFlags_StereoPanorama = 13,
+	VROverlayFlags_SortWithNonSceneOverlays = 14,
+	VROverlayFlags_VisibleInDashboard = 15,
+} VROverlayFlags;
+
+typedef enum VRMessageOverlayResponse
+{
+	VRMessageOverlayResponse_ButtonPress_0 = 0,
+	VRMessageOverlayResponse_ButtonPress_1 = 1,
+	VRMessageOverlayResponse_ButtonPress_2 = 2,
+	VRMessageOverlayResponse_ButtonPress_3 = 3,
+	VRMessageOverlayResponse_CouldntFindSystemOverlay = 4,
+	VRMessageOverlayResponse_CouldntFindOrCreateClientOverlay = 5,
+	VRMessageOverlayResponse_ApplicationQuit = 6,
+} VRMessageOverlayResponse;
+
+typedef enum EGamepadTextInputMode
+{
+	EGamepadTextInputMode_k_EGamepadTextInputModeNormal = 0,
+	EGamepadTextInputMode_k_EGamepadTextInputModePassword = 1,
+	EGamepadTextInputMode_k_EGamepadTextInputModeSubmit = 2,
+} EGamepadTextInputMode;
+
+typedef enum EGamepadTextInputLineMode
+{
+	EGamepadTextInputLineMode_k_EGamepadTextInputLineModeSingleLine = 0,
+	EGamepadTextInputLineMode_k_EGamepadTextInputLineModeMultipleLines = 1,
+} EGamepadTextInputLineMode;
+
+typedef enum EOverlayDirection
+{
+	EOverlayDirection_OverlayDirection_Up = 0,
+	EOverlayDirection_OverlayDirection_Down = 1,
+	EOverlayDirection_OverlayDirection_Left = 2,
+	EOverlayDirection_OverlayDirection_Right = 3,
+	EOverlayDirection_OverlayDirection_Count = 4,
+} EOverlayDirection;
+
+typedef enum EVROverlayIntersectionMaskPrimitiveType
+{
+	EVROverlayIntersectionMaskPrimitiveType_OverlayIntersectionPrimitiveType_Rectangle = 0,
+	EVROverlayIntersectionMaskPrimitiveType_OverlayIntersectionPrimitiveType_Circle = 1,
+} EVROverlayIntersectionMaskPrimitiveType;
+
+typedef enum EVRRenderModelError
+{
+	EVRRenderModelError_VRRenderModelError_None = 0,
+	EVRRenderModelError_VRRenderModelError_Loading = 100,
+	EVRRenderModelError_VRRenderModelError_NotSupported = 200,
+	EVRRenderModelError_VRRenderModelError_InvalidArg = 300,
+	EVRRenderModelError_VRRenderModelError_InvalidModel = 301,
+	EVRRenderModelError_VRRenderModelError_NoShapes = 302,
+	EVRRenderModelError_VRRenderModelError_MultipleShapes = 303,
+	EVRRenderModelError_VRRenderModelError_TooManyVertices = 304,
+	EVRRenderModelError_VRRenderModelError_MultipleTextures = 305,
+	EVRRenderModelError_VRRenderModelError_BufferTooSmall = 306,
+	EVRRenderModelError_VRRenderModelError_NotEnoughNormals = 307,
+	EVRRenderModelError_VRRenderModelError_NotEnoughTexCoords = 308,
+	EVRRenderModelError_VRRenderModelError_InvalidTexture = 400,
+} EVRRenderModelError;
+
+typedef enum EVRComponentProperty
+{
+	EVRComponentProperty_VRComponentProperty_IsStatic = 1,
+	EVRComponentProperty_VRComponentProperty_IsVisible = 2,
+	EVRComponentProperty_VRComponentProperty_IsTouched = 4,
+	EVRComponentProperty_VRComponentProperty_IsPressed = 8,
+	EVRComponentProperty_VRComponentProperty_IsScrolled = 16,
+} EVRComponentProperty;
+
+typedef enum EVRNotificationType
+{
+	EVRNotificationType_Transient = 0,
+	EVRNotificationType_Persistent = 1,
+	EVRNotificationType_Transient_SystemWithUserValue = 2,
+} EVRNotificationType;
+
+typedef enum EVRNotificationStyle
+{
+	EVRNotificationStyle_None = 0,
+	EVRNotificationStyle_Application = 100,
+	EVRNotificationStyle_Contact_Disabled = 200,
+	EVRNotificationStyle_Contact_Enabled = 201,
+	EVRNotificationStyle_Contact_Active = 202,
+} EVRNotificationStyle;
+
+typedef enum EVRSettingsError
+{
+	EVRSettingsError_VRSettingsError_None = 0,
+	EVRSettingsError_VRSettingsError_IPCFailed = 1,
+	EVRSettingsError_VRSettingsError_WriteFailed = 2,
+	EVRSettingsError_VRSettingsError_ReadFailed = 3,
+	EVRSettingsError_VRSettingsError_JsonParseFailed = 4,
+	EVRSettingsError_VRSettingsError_UnsetSettingHasNoDefault = 5,
+} EVRSettingsError;
+
+typedef enum EVRScreenshotError
+{
+	EVRScreenshotError_VRScreenshotError_None = 0,
+	EVRScreenshotError_VRScreenshotError_RequestFailed = 1,
+	EVRScreenshotError_VRScreenshotError_IncompatibleVersion = 100,
+	EVRScreenshotError_VRScreenshotError_NotFound = 101,
+	EVRScreenshotError_VRScreenshotError_BufferTooSmall = 102,
+	EVRScreenshotError_VRScreenshotError_ScreenshotAlreadyInProgress = 108,
+} EVRScreenshotError;
+
+
+// OpenVR typedefs
+
+typedef uint32_t TrackedDeviceIndex_t;
+typedef uint32_t VRNotificationId;
+typedef uint64_t VROverlayHandle_t;
+
+typedef void * glSharedTextureHandle_t;
+typedef int32_t glInt_t;
+typedef uint32_t glUInt_t;
+typedef uint64_t SharedTextureHandle_t;
+typedef uint32_t TrackedDeviceIndex_t;
+typedef uint64_t PropertyContainerHandle_t;
+typedef uint32_t PropertyTypeTag_t;
+typedef uint64_t VROverlayHandle_t;
+typedef uint64_t TrackedCameraHandle_t;
+typedef uint32_t ScreenshotHandle_t;
+typedef uint32_t VRComponentProperties;
+typedef int32_t TextureID_t;
+typedef uint32_t VRNotificationId;
+typedef EVRInitError HmdError;
+typedef EVREye Hmd_Eye;
+typedef EColorSpace ColorSpace;
+typedef ETrackingResult HmdTrackingResult;
+typedef ETrackedDeviceClass TrackedDeviceClass;
+typedef ETrackingUniverseOrigin TrackingUniverseOrigin;
+typedef ETrackedDeviceProperty TrackedDeviceProperty;
+typedef ETrackedPropertyError TrackedPropertyError;
+typedef EVRSubmitFlags VRSubmitFlags_t;
+typedef EVRState VRState_t;
+typedef ECollisionBoundsStyle CollisionBoundsStyle_t;
+typedef EVROverlayError VROverlayError;
+typedef EVRFirmwareError VRFirmwareError;
+typedef EVRCompositorError VRCompositorError;
+typedef EVRScreenshotError VRScreenshotsError;
+
+// OpenVR Structs
+
+typedef struct HmdMatrix34_t
+{
+	float m[3][4]; //float[3][4]
+} HmdMatrix34_t;
+
+typedef struct HmdMatrix44_t
+{
+	float m[4][4]; //float[4][4]
+} HmdMatrix44_t;
+
+typedef struct HmdVector3_t
+{
+	float v[3]; //float[3]
+} HmdVector3_t;
+
+typedef struct HmdVector4_t
+{
+	float v[4]; //float[4]
+} HmdVector4_t;
+
+typedef struct HmdVector3d_t
+{
+	double v[3]; //double[3]
+} HmdVector3d_t;
+
+typedef struct HmdVector2_t
+{
+	float v[2]; //float[2]
+} HmdVector2_t;
+
+typedef struct HmdQuaternion_t
+{
+	double w;
+	double x;
+	double y;
+	double z;
+} HmdQuaternion_t;
+
+typedef struct HmdColor_t
+{
+	float r;
+	float g;
+	float b;
+	float a;
+} HmdColor_t;
+
+typedef struct HmdQuad_t
+{
+	struct HmdVector3_t vCorners[4]; //struct vr::HmdVector3_t[4]
+} HmdQuad_t;
+
+typedef struct HmdRect2_t
+{
+	struct HmdVector2_t vTopLeft;
+	struct HmdVector2_t vBottomRight;
+} HmdRect2_t;
+
+typedef struct DistortionCoordinates_t
+{
+	float rfRed[2]; //float[2]
+	float rfGreen[2]; //float[2]
+	float rfBlue[2]; //float[2]
+} DistortionCoordinates_t;
+
+typedef struct Texture_t
+{
+	void * handle; // void *
+	enum ETextureType eType;
+	enum EColorSpace eColorSpace;
+} Texture_t;
+
+typedef struct TrackedDevicePose_t
+{
+	struct HmdMatrix34_t mDeviceToAbsoluteTracking;
+	struct HmdVector3_t vVelocity;
+	struct HmdVector3_t vAngularVelocity;
+	enum ETrackingResult eTrackingResult;
+	bool bPoseIsValid;
+	bool bDeviceIsConnected;
+} TrackedDevicePose_t;
+
+typedef struct VRTextureBounds_t
+{
+	float uMin;
+	float vMin;
+	float uMax;
+	float vMax;
+} VRTextureBounds_t;
+
+typedef struct VRVulkanTextureData_t
+{
+	uint64_t m_nImage;
+	struct VkDevice_T * m_pDevice; // struct VkDevice_T *
+	struct VkPhysicalDevice_T * m_pPhysicalDevice; // struct VkPhysicalDevice_T *
+	struct VkInstance_T * m_pInstance; // struct VkInstance_T *
+	struct VkQueue_T * m_pQueue; // struct VkQueue_T *
+	uint32_t m_nQueueFamilyIndex;
+	uint32_t m_nWidth;
+	uint32_t m_nHeight;
+	uint32_t m_nFormat;
+	uint32_t m_nSampleCount;
+} VRVulkanTextureData_t;
+
+typedef struct D3D12TextureData_t
+{
+	struct ID3D12Resource * m_pResource; // struct ID3D12Resource *
+	struct ID3D12CommandQueue * m_pCommandQueue; // struct ID3D12CommandQueue *
+	uint32_t m_nNodeMask;
+} D3D12TextureData_t;
+
+typedef struct VREvent_Controller_t
+{
+	uint32_t button;
+} VREvent_Controller_t;
+
+typedef struct VREvent_Mouse_t
+{
+	float x;
+	float y;
+	uint32_t button;
+} VREvent_Mouse_t;
+
+typedef struct VREvent_Scroll_t
+{
+	float xdelta;
+	float ydelta;
+	uint32_t repeatCount;
+} VREvent_Scroll_t;
+
+typedef struct VREvent_TouchPadMove_t
+{
+	bool bFingerDown;
+	float flSecondsFingerDown;
+	float fValueXFirst;
+	float fValueYFirst;
+	float fValueXRaw;
+	float fValueYRaw;
+} VREvent_TouchPadMove_t;
+
+typedef struct VREvent_Notification_t
+{
+	uint64_t ulUserValue;
+	uint32_t notificationId;
+} VREvent_Notification_t;
+
+typedef struct VREvent_Process_t
+{
+	uint32_t pid;
+	uint32_t oldPid;
+	bool bForced;
+} VREvent_Process_t;
+
+typedef struct VREvent_Overlay_t
+{
+	uint64_t overlayHandle;
+} VREvent_Overlay_t;
+
+typedef struct VREvent_Status_t
+{
+	uint32_t statusState;
+} VREvent_Status_t;
+
+typedef struct VREvent_Keyboard_t
+{
+	char * cNewInput[8]; //char[8]
+	uint64_t uUserValue;
+} VREvent_Keyboard_t;
+
+typedef struct VREvent_Ipd_t
+{
+	float ipdMeters;
+} VREvent_Ipd_t;
+
+typedef struct VREvent_Chaperone_t
+{
+	uint64_t m_nPreviousUniverse;
+	uint64_t m_nCurrentUniverse;
+} VREvent_Chaperone_t;
+
+typedef struct VREvent_Reserved_t
+{
+	uint64_t reserved0;
+	uint64_t reserved1;
+} VREvent_Reserved_t;
+
+typedef struct VREvent_PerformanceTest_t
+{
+	uint32_t m_nFidelityLevel;
+} VREvent_PerformanceTest_t;
+
+typedef struct VREvent_SeatedZeroPoseReset_t
+{
+	bool bResetBySystemMenu;
+} VREvent_SeatedZeroPoseReset_t;
+
+typedef struct VREvent_Screenshot_t
+{
+	uint32_t handle;
+	uint32_t type;
+} VREvent_Screenshot_t;
+
+typedef struct VREvent_ScreenshotProgress_t
+{
+	float progress;
+} VREvent_ScreenshotProgress_t;
+
+typedef struct VREvent_ApplicationLaunch_t
+{
+	uint32_t pid;
+	uint32_t unArgsHandle;
+} VREvent_ApplicationLaunch_t;
+
+typedef struct VREvent_EditingCameraSurface_t
+{
+	uint64_t overlayHandle;
+	uint32_t nVisualMode;
+} VREvent_EditingCameraSurface_t;
+
+typedef struct VREvent_MessageOverlay_t
+{
+	uint32_t unVRMessageOverlayResponse;
+} VREvent_MessageOverlay_t;
+
+typedef struct VREvent_Property_t
+{
+	PropertyContainerHandle_t container;
+	enum ETrackedDeviceProperty prop;
+} VREvent_Property_t;
+
+typedef struct HiddenAreaMesh_t
+{
+	struct HmdVector2_t * pVertexData; // const struct vr::HmdVector2_t *
+	uint32_t unTriangleCount;
+} HiddenAreaMesh_t;
+
+typedef struct VRControllerAxis_t
+{
+	float x;
+	float y;
+} VRControllerAxis_t;
+
+typedef struct VRControllerState_t
+{
+	uint32_t unPacketNum;
+	uint64_t ulButtonPressed;
+	uint64_t ulButtonTouched;
+	struct VRControllerAxis_t rAxis[5]; //struct vr::VRControllerAxis_t[5]
+} VRControllerState_t;
+
+typedef struct Compositor_OverlaySettings
+{
+	uint32_t size;
+	bool curved;
+	bool antialias;
+	float scale;
+	float distance;
+	float alpha;
+	float uOffset;
+	float vOffset;
+	float uScale;
+	float vScale;
+	float gridDivs;
+	float gridWidth;
+	float gridScale;
+	struct HmdMatrix44_t transform;
+} Compositor_OverlaySettings;
+
+typedef struct CameraVideoStreamFrameHeader_t
+{
+	enum EVRTrackedCameraFrameType eFrameType;
+	uint32_t nWidth;
+	uint32_t nHeight;
+	uint32_t nBytesPerPixel;
+	uint32_t nFrameSequence;
+	struct TrackedDevicePose_t standingTrackedDevicePose;
+} CameraVideoStreamFrameHeader_t;
+
+typedef struct AppOverrideKeys_t
+{
+	char * pchKey; // const char *
+	char * pchValue; // const char *
+} AppOverrideKeys_t;
+
+typedef struct Compositor_FrameTiming
+{
+	uint32_t m_nSize;
+	uint32_t m_nFrameIndex;
+	uint32_t m_nNumFramePresents;
+	uint32_t m_nNumMisPresented;
+	uint32_t m_nNumDroppedFrames;
+	uint32_t m_nReprojectionFlags;
+	double m_flSystemTimeInSeconds;
+	float m_flPreSubmitGpuMs;
+	float m_flPostSubmitGpuMs;
+	float m_flTotalRenderGpuMs;
+	float m_flCompositorRenderGpuMs;
+	float m_flCompositorRenderCpuMs;
+	float m_flCompositorIdleCpuMs;
+	float m_flClientFrameIntervalMs;
+	float m_flPresentCallCpuMs;
+	float m_flWaitForPresentCpuMs;
+	float m_flSubmitFrameMs;
+	float m_flWaitGetPosesCalledMs;
+	float m_flNewPosesReadyMs;
+	float m_flNewFrameReadyMs;
+	float m_flCompositorUpdateStartMs;
+	float m_flCompositorUpdateEndMs;
+	float m_flCompositorRenderStartMs;
+	TrackedDevicePose_t m_HmdPose;
+} Compositor_FrameTiming;
+
+typedef struct Compositor_CumulativeStats
+{
+	uint32_t m_nPid;
+	uint32_t m_nNumFramePresents;
+	uint32_t m_nNumDroppedFrames;
+	uint32_t m_nNumReprojectedFrames;
+	uint32_t m_nNumFramePresentsOnStartup;
+	uint32_t m_nNumDroppedFramesOnStartup;
+	uint32_t m_nNumReprojectedFramesOnStartup;
+	uint32_t m_nNumLoading;
+	uint32_t m_nNumFramePresentsLoading;
+	uint32_t m_nNumDroppedFramesLoading;
+	uint32_t m_nNumReprojectedFramesLoading;
+	uint32_t m_nNumTimedOut;
+	uint32_t m_nNumFramePresentsTimedOut;
+	uint32_t m_nNumDroppedFramesTimedOut;
+	uint32_t m_nNumReprojectedFramesTimedOut;
+} Compositor_CumulativeStats;
+
+typedef struct VROverlayIntersectionParams_t
+{
+	struct HmdVector3_t vSource;
+	struct HmdVector3_t vDirection;
+	enum ETrackingUniverseOrigin eOrigin;
+} VROverlayIntersectionParams_t;
+
+typedef struct VROverlayIntersectionResults_t
+{
+	struct HmdVector3_t vPoint;
+	struct HmdVector3_t vNormal;
+	struct HmdVector2_t vUVs;
+	float fDistance;
+} VROverlayIntersectionResults_t;
+
+typedef struct IntersectionMaskRectangle_t
+{
+	float m_flTopLeftX;
+	float m_flTopLeftY;
+	float m_flWidth;
+	float m_flHeight;
+} IntersectionMaskRectangle_t;
+
+typedef struct IntersectionMaskCircle_t
+{
+	float m_flCenterX;
+	float m_flCenterY;
+	float m_flRadius;
+} IntersectionMaskCircle_t;
+
+typedef struct RenderModel_ComponentState_t
+{
+	struct HmdMatrix34_t mTrackingToComponentRenderModel;
+	struct HmdMatrix34_t mTrackingToComponentLocal;
+	VRComponentProperties uProperties;
+} RenderModel_ComponentState_t;
+
+typedef struct RenderModel_Vertex_t
+{
+	struct HmdVector3_t vPosition;
+	struct HmdVector3_t vNormal;
+	float rfTextureCoord[2]; //float[2]
+} RenderModel_Vertex_t;
+
+typedef struct RenderModel_TextureMap_t
+{
+	uint16_t unWidth;
+	uint16_t unHeight;
+	uint8_t * rubTextureMapData; // const uint8_t *
+} RenderModel_TextureMap_t;
+
+typedef struct RenderModel_t
+{
+	struct RenderModel_Vertex_t * rVertexData; // const struct vr::RenderModel_Vertex_t *
+	uint32_t unVertexCount;
+	uint16_t * rIndexData; // const uint16_t *
+	uint32_t unTriangleCount;
+	TextureID_t diffuseTextureId;
+} RenderModel_t;
+
+typedef struct RenderModel_ControllerMode_State_t
+{
+	bool bScrollWheelVisible;
+} RenderModel_ControllerMode_State_t;
+
+typedef struct NotificationBitmap_t
+{
+	void * m_pImageData; // void *
+	int32_t m_nWidth;
+	int32_t m_nHeight;
+	int32_t m_nBytesPerPixel;
+} NotificationBitmap_t;
+
+typedef struct COpenVRContext
+{
+	intptr_t m_pVRSystem; // class vr::IVRSystem *
+	intptr_t m_pVRChaperone; // class vr::IVRChaperone *
+	intptr_t m_pVRChaperoneSetup; // class vr::IVRChaperoneSetup *
+	intptr_t m_pVRCompositor; // class vr::IVRCompositor *
+	intptr_t m_pVROverlay; // class vr::IVROverlay *
+	intptr_t m_pVRResources; // class vr::IVRResources *
+	intptr_t m_pVRRenderModels; // class vr::IVRRenderModels *
+	intptr_t m_pVRExtendedDisplay; // class vr::IVRExtendedDisplay *
+	intptr_t m_pVRSettings; // class vr::IVRSettings *
+	intptr_t m_pVRApplications; // class vr::IVRApplications *
+	intptr_t m_pVRTrackedCamera; // class vr::IVRTrackedCamera *
+	intptr_t m_pVRScreenshots; // class vr::IVRScreenshots *
+} COpenVRContext;
+
+
+typedef union
+{
+	VREvent_Reserved_t reserved;
+	VREvent_Controller_t controller;
+	VREvent_Mouse_t mouse;
+	VREvent_Scroll_t scroll;
+	VREvent_Process_t process;
+	VREvent_Notification_t notification;
+	VREvent_Overlay_t overlay;
+	VREvent_Status_t status;
+	VREvent_Keyboard_t keyboard;
+	VREvent_Ipd_t ipd;
+	VREvent_Chaperone_t chaperone;
+	VREvent_PerformanceTest_t performanceTest;
+	VREvent_TouchPadMove_t touchPadMove;
+	VREvent_SeatedZeroPoseReset_t seatedZeroPoseReset;
+} VREvent_Data_t;
+
+/** An event posted by the server to all running applications */
+struct VREvent_t
+{
+	uint32_t eventType; // EVREventType enum
+	TrackedDeviceIndex_t trackedDeviceIndex;
+	float eventAgeSeconds;
+	// event data must be the end of the struct as its size is variable
+	VREvent_Data_t data;
+};
+
+
+typedef union
+{
+	IntersectionMaskRectangle_t m_Rectangle;
+	IntersectionMaskCircle_t m_Circle;
+} VROverlayIntersectionMaskPrimitive_Data_t;
+
+struct VROverlayIntersectionMaskPrimitive_t
+{
+	EVROverlayIntersectionMaskPrimitiveType m_nPrimitiveType;
+	VROverlayIntersectionMaskPrimitive_Data_t m_Primitive;
+};
+
+
+// OpenVR Function Pointer Tables
+
+struct VR_IVRSystem_FnTable
+{
+	void (OPENVR_FNTABLE_CALLTYPE *GetRecommendedRenderTargetSize)(uint32_t * pnWidth, uint32_t * pnHeight);
+	struct HmdMatrix44_t (OPENVR_FNTABLE_CALLTYPE *GetProjectionMatrix)(EVREye eEye, float fNearZ, float fFarZ);
+	void (OPENVR_FNTABLE_CALLTYPE *GetProjectionRaw)(EVREye eEye, float * pfLeft, float * pfRight, float * pfTop, float * pfBottom);
+	bool (OPENVR_FNTABLE_CALLTYPE *ComputeDistortion)(EVREye eEye, float fU, float fV, struct DistortionCoordinates_t * pDistortionCoordinates);
+	struct HmdMatrix34_t (OPENVR_FNTABLE_CALLTYPE *GetEyeToHeadTransform)(EVREye eEye);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetTimeSinceLastVsync)(float * pfSecondsSinceLastVsync, uint64_t * pulFrameCounter);
+	int32_t (OPENVR_FNTABLE_CALLTYPE *GetD3D9AdapterIndex)();
+	void (OPENVR_FNTABLE_CALLTYPE *GetDXGIOutputInfo)(int32_t * pnAdapterIndex);
+	bool (OPENVR_FNTABLE_CALLTYPE *IsDisplayOnDesktop)();
+	bool (OPENVR_FNTABLE_CALLTYPE *SetDisplayVisibility)(bool bIsVisibleOnDesktop);
+	void (OPENVR_FNTABLE_CALLTYPE *GetDeviceToAbsoluteTrackingPose)(ETrackingUniverseOrigin eOrigin, float fPredictedSecondsToPhotonsFromNow, struct TrackedDevicePose_t * pTrackedDevicePoseArray, uint32_t unTrackedDevicePoseArrayCount);
+	void (OPENVR_FNTABLE_CALLTYPE *ResetSeatedZeroPose)();
+	struct HmdMatrix34_t (OPENVR_FNTABLE_CALLTYPE *GetSeatedZeroPoseToStandingAbsoluteTrackingPose)();
+	struct HmdMatrix34_t (OPENVR_FNTABLE_CALLTYPE *GetRawZeroPoseToStandingAbsoluteTrackingPose)();
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetSortedTrackedDeviceIndicesOfClass)(ETrackedDeviceClass eTrackedDeviceClass, TrackedDeviceIndex_t * punTrackedDeviceIndexArray, uint32_t unTrackedDeviceIndexArrayCount, TrackedDeviceIndex_t unRelativeToTrackedDeviceIndex);
+	EDeviceActivityLevel (OPENVR_FNTABLE_CALLTYPE *GetTrackedDeviceActivityLevel)(TrackedDeviceIndex_t unDeviceId);
+	void (OPENVR_FNTABLE_CALLTYPE *ApplyTransform)(struct TrackedDevicePose_t * pOutputPose, struct TrackedDevicePose_t * pTrackedDevicePose, struct HmdMatrix34_t * pTransform);
+	TrackedDeviceIndex_t (OPENVR_FNTABLE_CALLTYPE *GetTrackedDeviceIndexForControllerRole)(ETrackedControllerRole unDeviceType);
+	ETrackedControllerRole (OPENVR_FNTABLE_CALLTYPE *GetControllerRoleForTrackedDeviceIndex)(TrackedDeviceIndex_t unDeviceIndex);
+	ETrackedDeviceClass (OPENVR_FNTABLE_CALLTYPE *GetTrackedDeviceClass)(TrackedDeviceIndex_t unDeviceIndex);
+	bool (OPENVR_FNTABLE_CALLTYPE *IsTrackedDeviceConnected)(TrackedDeviceIndex_t unDeviceIndex);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetBoolTrackedDeviceProperty)(TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError * pError);
+	float (OPENVR_FNTABLE_CALLTYPE *GetFloatTrackedDeviceProperty)(TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError * pError);
+	int32_t (OPENVR_FNTABLE_CALLTYPE *GetInt32TrackedDeviceProperty)(TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError * pError);
+	uint64_t (OPENVR_FNTABLE_CALLTYPE *GetUint64TrackedDeviceProperty)(TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError * pError);
+	struct HmdMatrix34_t (OPENVR_FNTABLE_CALLTYPE *GetMatrix34TrackedDeviceProperty)(TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, ETrackedPropertyError * pError);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetStringTrackedDeviceProperty)(TrackedDeviceIndex_t unDeviceIndex, ETrackedDeviceProperty prop, char * pchValue, uint32_t unBufferSize, ETrackedPropertyError * pError);
+	char * (OPENVR_FNTABLE_CALLTYPE *GetPropErrorNameFromEnum)(ETrackedPropertyError error);
+	bool (OPENVR_FNTABLE_CALLTYPE *PollNextEvent)(struct VREvent_t * pEvent, uint32_t uncbVREvent);
+	bool (OPENVR_FNTABLE_CALLTYPE *PollNextEventWithPose)(ETrackingUniverseOrigin eOrigin, struct VREvent_t * pEvent, uint32_t uncbVREvent, TrackedDevicePose_t * pTrackedDevicePose);
+	char * (OPENVR_FNTABLE_CALLTYPE *GetEventTypeNameFromEnum)(EVREventType eType);
+	struct HiddenAreaMesh_t (OPENVR_FNTABLE_CALLTYPE *GetHiddenAreaMesh)(EVREye eEye, EHiddenAreaMeshType type);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetControllerState)(TrackedDeviceIndex_t unControllerDeviceIndex, VRControllerState_t * pControllerState, uint32_t unControllerStateSize);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetControllerStateWithPose)(ETrackingUniverseOrigin eOrigin, TrackedDeviceIndex_t unControllerDeviceIndex, VRControllerState_t * pControllerState, uint32_t unControllerStateSize, struct TrackedDevicePose_t * pTrackedDevicePose);
+	void (OPENVR_FNTABLE_CALLTYPE *TriggerHapticPulse)(TrackedDeviceIndex_t unControllerDeviceIndex, uint32_t unAxisId, unsigned short usDurationMicroSec);
+	char * (OPENVR_FNTABLE_CALLTYPE *GetButtonIdNameFromEnum)(EVRButtonId eButtonId);
+	char * (OPENVR_FNTABLE_CALLTYPE *GetControllerAxisTypeNameFromEnum)(EVRControllerAxisType eAxisType);
+	bool (OPENVR_FNTABLE_CALLTYPE *CaptureInputFocus)();
+	void (OPENVR_FNTABLE_CALLTYPE *ReleaseInputFocus)();
+	bool (OPENVR_FNTABLE_CALLTYPE *IsInputFocusCapturedByAnotherProcess)();
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *DriverDebugRequest)(TrackedDeviceIndex_t unDeviceIndex, char * pchRequest, char * pchResponseBuffer, uint32_t unResponseBufferSize);
+	EVRFirmwareError (OPENVR_FNTABLE_CALLTYPE *PerformFirmwareUpdate)(TrackedDeviceIndex_t unDeviceIndex);
+	void (OPENVR_FNTABLE_CALLTYPE *AcknowledgeQuit_Exiting)();
+	void (OPENVR_FNTABLE_CALLTYPE *AcknowledgeQuit_UserPrompt)();
+};
+
+struct VR_IVRExtendedDisplay_FnTable
+{
+	void (OPENVR_FNTABLE_CALLTYPE *GetWindowBounds)(int32_t * pnX, int32_t * pnY, uint32_t * pnWidth, uint32_t * pnHeight);
+	void (OPENVR_FNTABLE_CALLTYPE *GetEyeOutputViewport)(EVREye eEye, uint32_t * pnX, uint32_t * pnY, uint32_t * pnWidth, uint32_t * pnHeight);
+	void (OPENVR_FNTABLE_CALLTYPE *GetDXGIOutputInfo)(int32_t * pnAdapterIndex, int32_t * pnAdapterOutputIndex);
+};
+
+struct VR_IVRTrackedCamera_FnTable
+{
+	char * (OPENVR_FNTABLE_CALLTYPE *GetCameraErrorNameFromEnum)(EVRTrackedCameraError eCameraError);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *HasCamera)(TrackedDeviceIndex_t nDeviceIndex, bool * pHasCamera);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *GetCameraFrameSize)(TrackedDeviceIndex_t nDeviceIndex, EVRTrackedCameraFrameType eFrameType, uint32_t * pnWidth, uint32_t * pnHeight, uint32_t * pnFrameBufferSize);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *GetCameraIntrinsics)(TrackedDeviceIndex_t nDeviceIndex, EVRTrackedCameraFrameType eFrameType, HmdVector2_t * pFocalLength, HmdVector2_t * pCenter);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *GetCameraProjection)(TrackedDeviceIndex_t nDeviceIndex, EVRTrackedCameraFrameType eFrameType, float flZNear, float flZFar, HmdMatrix44_t * pProjection);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *AcquireVideoStreamingService)(TrackedDeviceIndex_t nDeviceIndex, TrackedCameraHandle_t * pHandle);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *ReleaseVideoStreamingService)(TrackedCameraHandle_t hTrackedCamera);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *GetVideoStreamFrameBuffer)(TrackedCameraHandle_t hTrackedCamera, EVRTrackedCameraFrameType eFrameType, void * pFrameBuffer, uint32_t nFrameBufferSize, CameraVideoStreamFrameHeader_t * pFrameHeader, uint32_t nFrameHeaderSize);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *GetVideoStreamTextureSize)(TrackedDeviceIndex_t nDeviceIndex, EVRTrackedCameraFrameType eFrameType, VRTextureBounds_t * pTextureBounds, uint32_t * pnWidth, uint32_t * pnHeight);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *GetVideoStreamTextureD3D11)(TrackedCameraHandle_t hTrackedCamera, EVRTrackedCameraFrameType eFrameType, void * pD3D11DeviceOrResource, void ** ppD3D11ShaderResourceView, CameraVideoStreamFrameHeader_t * pFrameHeader, uint32_t nFrameHeaderSize);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *GetVideoStreamTextureGL)(TrackedCameraHandle_t hTrackedCamera, EVRTrackedCameraFrameType eFrameType, glUInt_t * pglTextureId, CameraVideoStreamFrameHeader_t * pFrameHeader, uint32_t nFrameHeaderSize);
+	EVRTrackedCameraError (OPENVR_FNTABLE_CALLTYPE *ReleaseVideoStreamTextureGL)(TrackedCameraHandle_t hTrackedCamera, glUInt_t glTextureId);
+};
+
+struct VR_IVRApplications_FnTable
+{
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *AddApplicationManifest)(char * pchApplicationManifestFullPath, bool bTemporary);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *RemoveApplicationManifest)(char * pchApplicationManifestFullPath);
+	bool (OPENVR_FNTABLE_CALLTYPE *IsApplicationInstalled)(char * pchAppKey);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetApplicationCount)();
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *GetApplicationKeyByIndex)(uint32_t unApplicationIndex, char * pchAppKeyBuffer, uint32_t unAppKeyBufferLen);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *GetApplicationKeyByProcessId)(uint32_t unProcessId, char * pchAppKeyBuffer, uint32_t unAppKeyBufferLen);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *LaunchApplication)(char * pchAppKey);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *LaunchTemplateApplication)(char * pchTemplateAppKey, char * pchNewAppKey, struct AppOverrideKeys_t * pKeys, uint32_t unKeys);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *LaunchApplicationFromMimeType)(char * pchMimeType, char * pchArgs);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *LaunchDashboardOverlay)(char * pchAppKey);
+	bool (OPENVR_FNTABLE_CALLTYPE *CancelApplicationLaunch)(char * pchAppKey);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *IdentifyApplication)(uint32_t unProcessId, char * pchAppKey);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetApplicationProcessId)(char * pchAppKey);
+	char * (OPENVR_FNTABLE_CALLTYPE *GetApplicationsErrorNameFromEnum)(EVRApplicationError error);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetApplicationPropertyString)(char * pchAppKey, EVRApplicationProperty eProperty, char * pchPropertyValueBuffer, uint32_t unPropertyValueBufferLen, EVRApplicationError * peError);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetApplicationPropertyBool)(char * pchAppKey, EVRApplicationProperty eProperty, EVRApplicationError * peError);
+	uint64_t (OPENVR_FNTABLE_CALLTYPE *GetApplicationPropertyUint64)(char * pchAppKey, EVRApplicationProperty eProperty, EVRApplicationError * peError);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *SetApplicationAutoLaunch)(char * pchAppKey, bool bAutoLaunch);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetApplicationAutoLaunch)(char * pchAppKey);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *SetDefaultApplicationForMimeType)(char * pchAppKey, char * pchMimeType);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetDefaultApplicationForMimeType)(char * pchMimeType, char * pchAppKeyBuffer, uint32_t unAppKeyBufferLen);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetApplicationSupportedMimeTypes)(char * pchAppKey, char * pchMimeTypesBuffer, uint32_t unMimeTypesBuffer);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetApplicationsThatSupportMimeType)(char * pchMimeType, char * pchAppKeysThatSupportBuffer, uint32_t unAppKeysThatSupportBuffer);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetApplicationLaunchArguments)(uint32_t unHandle, char * pchArgs, uint32_t unArgs);
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *GetStartingApplication)(char * pchAppKeyBuffer, uint32_t unAppKeyBufferLen);
+	EVRApplicationTransitionState (OPENVR_FNTABLE_CALLTYPE *GetTransitionState)();
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *PerformApplicationPrelaunchCheck)(char * pchAppKey);
+	char * (OPENVR_FNTABLE_CALLTYPE *GetApplicationsTransitionStateNameFromEnum)(EVRApplicationTransitionState state);
+	bool (OPENVR_FNTABLE_CALLTYPE *IsQuitUserPromptRequested)();
+	EVRApplicationError (OPENVR_FNTABLE_CALLTYPE *LaunchInternalProcess)(char * pchBinaryPath, char * pchArguments, char * pchWorkingDirectory);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetCurrentSceneProcessId)();
+};
+
+struct VR_IVRChaperone_FnTable
+{
+	ChaperoneCalibrationState (OPENVR_FNTABLE_CALLTYPE *GetCalibrationState)();
+	bool (OPENVR_FNTABLE_CALLTYPE *GetPlayAreaSize)(float * pSizeX, float * pSizeZ);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetPlayAreaRect)(struct HmdQuad_t * rect);
+	void (OPENVR_FNTABLE_CALLTYPE *ReloadInfo)();
+	void (OPENVR_FNTABLE_CALLTYPE *SetSceneColor)(struct HmdColor_t color);
+	void (OPENVR_FNTABLE_CALLTYPE *GetBoundsColor)(struct HmdColor_t * pOutputColorArray, int nNumOutputColors, float flCollisionBoundsFadeDistance, struct HmdColor_t * pOutputCameraColor);
+	bool (OPENVR_FNTABLE_CALLTYPE *AreBoundsVisible)();
+	void (OPENVR_FNTABLE_CALLTYPE *ForceBoundsVisible)(bool bForce);
+};
+
+struct VR_IVRChaperoneSetup_FnTable
+{
+	bool (OPENVR_FNTABLE_CALLTYPE *CommitWorkingCopy)(EChaperoneConfigFile configFile);
+	void (OPENVR_FNTABLE_CALLTYPE *RevertWorkingCopy)();
+	bool (OPENVR_FNTABLE_CALLTYPE *GetWorkingPlayAreaSize)(float * pSizeX, float * pSizeZ);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetWorkingPlayAreaRect)(struct HmdQuad_t * rect);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetWorkingCollisionBoundsInfo)(struct HmdQuad_t * pQuadsBuffer, uint32_t * punQuadsCount);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetLiveCollisionBoundsInfo)(struct HmdQuad_t * pQuadsBuffer, uint32_t * punQuadsCount);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetWorkingSeatedZeroPoseToRawTrackingPose)(struct HmdMatrix34_t * pmatSeatedZeroPoseToRawTrackingPose);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetWorkingStandingZeroPoseToRawTrackingPose)(struct HmdMatrix34_t * pmatStandingZeroPoseToRawTrackingPose);
+	void (OPENVR_FNTABLE_CALLTYPE *SetWorkingPlayAreaSize)(float sizeX, float sizeZ);
+	void (OPENVR_FNTABLE_CALLTYPE *SetWorkingCollisionBoundsInfo)(struct HmdQuad_t * pQuadsBuffer, uint32_t unQuadsCount);
+	void (OPENVR_FNTABLE_CALLTYPE *SetWorkingSeatedZeroPoseToRawTrackingPose)(struct HmdMatrix34_t * pMatSeatedZeroPoseToRawTrackingPose);
+	void (OPENVR_FNTABLE_CALLTYPE *SetWorkingStandingZeroPoseToRawTrackingPose)(struct HmdMatrix34_t * pMatStandingZeroPoseToRawTrackingPose);
+	void (OPENVR_FNTABLE_CALLTYPE *ReloadFromDisk)(EChaperoneConfigFile configFile);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetLiveSeatedZeroPoseToRawTrackingPose)(struct HmdMatrix34_t * pmatSeatedZeroPoseToRawTrackingPose);
+	void (OPENVR_FNTABLE_CALLTYPE *SetWorkingCollisionBoundsTagsInfo)(uint8_t * pTagsBuffer, uint32_t unTagCount);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetLiveCollisionBoundsTagsInfo)(uint8_t * pTagsBuffer, uint32_t * punTagCount);
+	bool (OPENVR_FNTABLE_CALLTYPE *SetWorkingPhysicalBoundsInfo)(struct HmdQuad_t * pQuadsBuffer, uint32_t unQuadsCount);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetLivePhysicalBoundsInfo)(struct HmdQuad_t * pQuadsBuffer, uint32_t * punQuadsCount);
+	bool (OPENVR_FNTABLE_CALLTYPE *ExportLiveToBuffer)(char * pBuffer, uint32_t * pnBufferLength);
+	bool (OPENVR_FNTABLE_CALLTYPE *ImportFromBufferToWorking)(char * pBuffer, uint32_t nImportFlags);
+};
+
+struct VR_IVRCompositor_FnTable
+{
+	void (OPENVR_FNTABLE_CALLTYPE *SetTrackingSpace)(ETrackingUniverseOrigin eOrigin);
+	ETrackingUniverseOrigin (OPENVR_FNTABLE_CALLTYPE *GetTrackingSpace)();
+	EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *WaitGetPoses)(struct TrackedDevicePose_t * pRenderPoseArray, uint32_t unRenderPoseArrayCount, struct TrackedDevicePose_t * pGamePoseArray, uint32_t unGamePoseArrayCount);
+	EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *GetLastPoses)(struct TrackedDevicePose_t * pRenderPoseArray, uint32_t unRenderPoseArrayCount, struct TrackedDevicePose_t * pGamePoseArray, uint32_t unGamePoseArrayCount);
+	EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *GetLastPoseForTrackedDeviceIndex)(TrackedDeviceIndex_t unDeviceIndex, struct TrackedDevicePose_t * pOutputPose, struct TrackedDevicePose_t * pOutputGamePose);
+	EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *Submit)(EVREye eEye, struct Texture_t * pTexture, struct VRTextureBounds_t * pBounds, EVRSubmitFlags nSubmitFlags);
+	void (OPENVR_FNTABLE_CALLTYPE *ClearLastSubmittedFrame)();
+	void (OPENVR_FNTABLE_CALLTYPE *PostPresentHandoff)();
+	bool (OPENVR_FNTABLE_CALLTYPE *GetFrameTiming)(struct Compositor_FrameTiming * pTiming, uint32_t unFramesAgo);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetFrameTimings)(struct Compositor_FrameTiming * pTiming, uint32_t nFrames);
+	float (OPENVR_FNTABLE_CALLTYPE *GetFrameTimeRemaining)();
+	void (OPENVR_FNTABLE_CALLTYPE *GetCumulativeStats)(struct Compositor_CumulativeStats * pStats, uint32_t nStatsSizeInBytes);
+	void (OPENVR_FNTABLE_CALLTYPE *FadeToColor)(float fSeconds, float fRed, float fGreen, float fBlue, float fAlpha, bool bBackground);
+	struct HmdColor_t (OPENVR_FNTABLE_CALLTYPE *GetCurrentFadeColor)(bool bBackground);
+	void (OPENVR_FNTABLE_CALLTYPE *FadeGrid)(float fSeconds, bool bFadeIn);
+	float (OPENVR_FNTABLE_CALLTYPE *GetCurrentGridAlpha)();
+	EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *SetSkyboxOverride)(struct Texture_t * pTextures, uint32_t unTextureCount);
+	void (OPENVR_FNTABLE_CALLTYPE *ClearSkyboxOverride)();
+	void (OPENVR_FNTABLE_CALLTYPE *CompositorBringToFront)();
+	void (OPENVR_FNTABLE_CALLTYPE *CompositorGoToBack)();
+	void (OPENVR_FNTABLE_CALLTYPE *CompositorQuit)();
+	bool (OPENVR_FNTABLE_CALLTYPE *IsFullscreen)();
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetCurrentSceneFocusProcess)();
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetLastFrameRenderer)();
+	bool (OPENVR_FNTABLE_CALLTYPE *CanRenderScene)();
+	void (OPENVR_FNTABLE_CALLTYPE *ShowMirrorWindow)();
+	void (OPENVR_FNTABLE_CALLTYPE *HideMirrorWindow)();
+	bool (OPENVR_FNTABLE_CALLTYPE *IsMirrorWindowVisible)();
+	void (OPENVR_FNTABLE_CALLTYPE *CompositorDumpImages)();
+	bool (OPENVR_FNTABLE_CALLTYPE *ShouldAppRenderWithLowResources)();
+	void (OPENVR_FNTABLE_CALLTYPE *ForceInterleavedReprojectionOn)(bool bOverride);
+	void (OPENVR_FNTABLE_CALLTYPE *ForceReconnectProcess)();
+	void (OPENVR_FNTABLE_CALLTYPE *SuspendRendering)(bool bSuspend);
+	EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *GetMirrorTextureD3D11)(EVREye eEye, void * pD3D11DeviceOrResource, void ** ppD3D11ShaderResourceView);
+	void (OPENVR_FNTABLE_CALLTYPE *ReleaseMirrorTextureD3D11)(void * pD3D11ShaderResourceView);
+	EVRCompositorError (OPENVR_FNTABLE_CALLTYPE *GetMirrorTextureGL)(EVREye eEye, glUInt_t * pglTextureId, glSharedTextureHandle_t * pglSharedTextureHandle);
+	bool (OPENVR_FNTABLE_CALLTYPE *ReleaseSharedGLTexture)(glUInt_t glTextureId, glSharedTextureHandle_t glSharedTextureHandle);
+	void (OPENVR_FNTABLE_CALLTYPE *LockGLSharedTextureForAccess)(glSharedTextureHandle_t glSharedTextureHandle);
+	void (OPENVR_FNTABLE_CALLTYPE *UnlockGLSharedTextureForAccess)(glSharedTextureHandle_t glSharedTextureHandle);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetVulkanInstanceExtensionsRequired)(char * pchValue, uint32_t unBufferSize);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetVulkanDeviceExtensionsRequired)(struct VkPhysicalDevice_T * pPhysicalDevice, char * pchValue, uint32_t unBufferSize);
+};
+
+struct VR_IVROverlay_FnTable
+{
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *FindOverlay)(char * pchOverlayKey, VROverlayHandle_t * pOverlayHandle);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *CreateOverlay)(char * pchOverlayKey, char * pchOverlayFriendlyName, VROverlayHandle_t * pOverlayHandle);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *DestroyOverlay)(VROverlayHandle_t ulOverlayHandle);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetHighQualityOverlay)(VROverlayHandle_t ulOverlayHandle);
+	VROverlayHandle_t (OPENVR_FNTABLE_CALLTYPE *GetHighQualityOverlay)();
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetOverlayKey)(VROverlayHandle_t ulOverlayHandle, char * pchValue, uint32_t unBufferSize, EVROverlayError * pError);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetOverlayName)(VROverlayHandle_t ulOverlayHandle, char * pchValue, uint32_t unBufferSize, EVROverlayError * pError);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayImageData)(VROverlayHandle_t ulOverlayHandle, void * pvBuffer, uint32_t unBufferSize, uint32_t * punWidth, uint32_t * punHeight);
+	char * (OPENVR_FNTABLE_CALLTYPE *GetOverlayErrorNameFromEnum)(EVROverlayError error);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayRenderingPid)(VROverlayHandle_t ulOverlayHandle, uint32_t unPID);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetOverlayRenderingPid)(VROverlayHandle_t ulOverlayHandle);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayFlag)(VROverlayHandle_t ulOverlayHandle, VROverlayFlags eOverlayFlag, bool bEnabled);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayFlag)(VROverlayHandle_t ulOverlayHandle, VROverlayFlags eOverlayFlag, bool * pbEnabled);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayColor)(VROverlayHandle_t ulOverlayHandle, float fRed, float fGreen, float fBlue);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayColor)(VROverlayHandle_t ulOverlayHandle, float * pfRed, float * pfGreen, float * pfBlue);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayAlpha)(VROverlayHandle_t ulOverlayHandle, float fAlpha);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayAlpha)(VROverlayHandle_t ulOverlayHandle, float * pfAlpha);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTexelAspect)(VROverlayHandle_t ulOverlayHandle, float fTexelAspect);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTexelAspect)(VROverlayHandle_t ulOverlayHandle, float * pfTexelAspect);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlaySortOrder)(VROverlayHandle_t ulOverlayHandle, uint32_t unSortOrder);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlaySortOrder)(VROverlayHandle_t ulOverlayHandle, uint32_t * punSortOrder);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayWidthInMeters)(VROverlayHandle_t ulOverlayHandle, float fWidthInMeters);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayWidthInMeters)(VROverlayHandle_t ulOverlayHandle, float * pfWidthInMeters);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayAutoCurveDistanceRangeInMeters)(VROverlayHandle_t ulOverlayHandle, float fMinDistanceInMeters, float fMaxDistanceInMeters);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayAutoCurveDistanceRangeInMeters)(VROverlayHandle_t ulOverlayHandle, float * pfMinDistanceInMeters, float * pfMaxDistanceInMeters);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTextureColorSpace)(VROverlayHandle_t ulOverlayHandle, EColorSpace eTextureColorSpace);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTextureColorSpace)(VROverlayHandle_t ulOverlayHandle, EColorSpace * peTextureColorSpace);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTextureBounds)(VROverlayHandle_t ulOverlayHandle, struct VRTextureBounds_t * pOverlayTextureBounds);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTextureBounds)(VROverlayHandle_t ulOverlayHandle, struct VRTextureBounds_t * pOverlayTextureBounds);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTransformType)(VROverlayHandle_t ulOverlayHandle, VROverlayTransformType * peTransformType);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTransformAbsolute)(VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin eTrackingOrigin, struct HmdMatrix34_t * pmatTrackingOriginToOverlayTransform);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTransformAbsolute)(VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin * peTrackingOrigin, struct HmdMatrix34_t * pmatTrackingOriginToOverlayTransform);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTransformTrackedDeviceRelative)(VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t unTrackedDevice, struct HmdMatrix34_t * pmatTrackedDeviceToOverlayTransform);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTransformTrackedDeviceRelative)(VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t * punTrackedDevice, struct HmdMatrix34_t * pmatTrackedDeviceToOverlayTransform);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTransformTrackedDeviceComponent)(VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t unDeviceIndex, char * pchComponentName);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTransformTrackedDeviceComponent)(VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t * punDeviceIndex, char * pchComponentName, uint32_t unComponentNameSize);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *ShowOverlay)(VROverlayHandle_t ulOverlayHandle);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *HideOverlay)(VROverlayHandle_t ulOverlayHandle);
+	bool (OPENVR_FNTABLE_CALLTYPE *IsOverlayVisible)(VROverlayHandle_t ulOverlayHandle);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetTransformForOverlayCoordinates)(VROverlayHandle_t ulOverlayHandle, ETrackingUniverseOrigin eTrackingOrigin, struct HmdVector2_t coordinatesInOverlay, struct HmdMatrix34_t * pmatTransform);
+	bool (OPENVR_FNTABLE_CALLTYPE *PollNextOverlayEvent)(VROverlayHandle_t ulOverlayHandle, struct VREvent_t * pEvent, uint32_t uncbVREvent);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayInputMethod)(VROverlayHandle_t ulOverlayHandle, VROverlayInputMethod * peInputMethod);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayInputMethod)(VROverlayHandle_t ulOverlayHandle, VROverlayInputMethod eInputMethod);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayMouseScale)(VROverlayHandle_t ulOverlayHandle, struct HmdVector2_t * pvecMouseScale);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayMouseScale)(VROverlayHandle_t ulOverlayHandle, struct HmdVector2_t * pvecMouseScale);
+	bool (OPENVR_FNTABLE_CALLTYPE *ComputeOverlayIntersection)(VROverlayHandle_t ulOverlayHandle, struct VROverlayIntersectionParams_t * pParams, struct VROverlayIntersectionResults_t * pResults);
+	bool (OPENVR_FNTABLE_CALLTYPE *HandleControllerOverlayInteractionAsMouse)(VROverlayHandle_t ulOverlayHandle, TrackedDeviceIndex_t unControllerDeviceIndex);
+	bool (OPENVR_FNTABLE_CALLTYPE *IsHoverTargetOverlay)(VROverlayHandle_t ulOverlayHandle);
+	VROverlayHandle_t (OPENVR_FNTABLE_CALLTYPE *GetGamepadFocusOverlay)();
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetGamepadFocusOverlay)(VROverlayHandle_t ulNewFocusOverlay);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayNeighbor)(EOverlayDirection eDirection, VROverlayHandle_t ulFrom, VROverlayHandle_t ulTo);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *MoveGamepadFocusToNeighbor)(EOverlayDirection eDirection, VROverlayHandle_t ulFrom);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayTexture)(VROverlayHandle_t ulOverlayHandle, struct Texture_t * pTexture);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *ClearOverlayTexture)(VROverlayHandle_t ulOverlayHandle);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayRaw)(VROverlayHandle_t ulOverlayHandle, void * pvBuffer, uint32_t unWidth, uint32_t unHeight, uint32_t unDepth);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayFromFile)(VROverlayHandle_t ulOverlayHandle, char * pchFilePath);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTexture)(VROverlayHandle_t ulOverlayHandle, void ** pNativeTextureHandle, void * pNativeTextureRef, uint32_t * pWidth, uint32_t * pHeight, uint32_t * pNativeFormat, ETextureType * pAPIType, EColorSpace * pColorSpace, struct VRTextureBounds_t * pTextureBounds);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *ReleaseNativeOverlayHandle)(VROverlayHandle_t ulOverlayHandle, void * pNativeTextureHandle);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayTextureSize)(VROverlayHandle_t ulOverlayHandle, uint32_t * pWidth, uint32_t * pHeight);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *CreateDashboardOverlay)(char * pchOverlayKey, char * pchOverlayFriendlyName, VROverlayHandle_t * pMainHandle, VROverlayHandle_t * pThumbnailHandle);
+	bool (OPENVR_FNTABLE_CALLTYPE *IsDashboardVisible)();
+	bool (OPENVR_FNTABLE_CALLTYPE *IsActiveDashboardOverlay)(VROverlayHandle_t ulOverlayHandle);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetDashboardOverlaySceneProcess)(VROverlayHandle_t ulOverlayHandle, uint32_t unProcessId);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetDashboardOverlaySceneProcess)(VROverlayHandle_t ulOverlayHandle, uint32_t * punProcessId);
+	void (OPENVR_FNTABLE_CALLTYPE *ShowDashboard)(char * pchOverlayToShow);
+	TrackedDeviceIndex_t (OPENVR_FNTABLE_CALLTYPE *GetPrimaryDashboardDevice)();
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *ShowKeyboard)(EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, char * pchDescription, uint32_t unCharMax, char * pchExistingText, bool bUseMinimalMode, uint64_t uUserValue);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *ShowKeyboardForOverlay)(VROverlayHandle_t ulOverlayHandle, EGamepadTextInputMode eInputMode, EGamepadTextInputLineMode eLineInputMode, char * pchDescription, uint32_t unCharMax, char * pchExistingText, bool bUseMinimalMode, uint64_t uUserValue);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetKeyboardText)(char * pchText, uint32_t cchText);
+	void (OPENVR_FNTABLE_CALLTYPE *HideKeyboard)();
+	void (OPENVR_FNTABLE_CALLTYPE *SetKeyboardTransformAbsolute)(ETrackingUniverseOrigin eTrackingOrigin, struct HmdMatrix34_t * pmatTrackingOriginToKeyboardTransform);
+	void (OPENVR_FNTABLE_CALLTYPE *SetKeyboardPositionForOverlay)(VROverlayHandle_t ulOverlayHandle, struct HmdRect2_t avoidRect);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *SetOverlayIntersectionMask)(VROverlayHandle_t ulOverlayHandle, struct VROverlayIntersectionMaskPrimitive_t * pMaskPrimitives, uint32_t unNumMaskPrimitives, uint32_t unPrimitiveSize);
+	EVROverlayError (OPENVR_FNTABLE_CALLTYPE *GetOverlayFlags)(VROverlayHandle_t ulOverlayHandle, uint32_t * pFlags);
+	VRMessageOverlayResponse (OPENVR_FNTABLE_CALLTYPE *ShowMessageOverlay)(char * pchText, char * pchCaption, char * pchButton0Text, char * pchButton1Text, char * pchButton2Text, char * pchButton3Text);
+};
+
+struct VR_IVRRenderModels_FnTable
+{
+	EVRRenderModelError (OPENVR_FNTABLE_CALLTYPE *LoadRenderModel_Async)(char * pchRenderModelName, struct RenderModel_t ** ppRenderModel);
+	void (OPENVR_FNTABLE_CALLTYPE *FreeRenderModel)(struct RenderModel_t * pRenderModel);
+	EVRRenderModelError (OPENVR_FNTABLE_CALLTYPE *LoadTexture_Async)(TextureID_t textureId, struct RenderModel_TextureMap_t ** ppTexture);
+	void (OPENVR_FNTABLE_CALLTYPE *FreeTexture)(struct RenderModel_TextureMap_t * pTexture);
+	EVRRenderModelError (OPENVR_FNTABLE_CALLTYPE *LoadTextureD3D11_Async)(TextureID_t textureId, void * pD3D11Device, void ** ppD3D11Texture2D);
+	EVRRenderModelError (OPENVR_FNTABLE_CALLTYPE *LoadIntoTextureD3D11_Async)(TextureID_t textureId, void * pDstTexture);
+	void (OPENVR_FNTABLE_CALLTYPE *FreeTextureD3D11)(void * pD3D11Texture2D);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetRenderModelName)(uint32_t unRenderModelIndex, char * pchRenderModelName, uint32_t unRenderModelNameLen);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetRenderModelCount)();
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetComponentCount)(char * pchRenderModelName);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetComponentName)(char * pchRenderModelName, uint32_t unComponentIndex, char * pchComponentName, uint32_t unComponentNameLen);
+	uint64_t (OPENVR_FNTABLE_CALLTYPE *GetComponentButtonMask)(char * pchRenderModelName, char * pchComponentName);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetComponentRenderModelName)(char * pchRenderModelName, char * pchComponentName, char * pchComponentRenderModelName, uint32_t unComponentRenderModelNameLen);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetComponentState)(char * pchRenderModelName, char * pchComponentName, VRControllerState_t * pControllerState, struct RenderModel_ControllerMode_State_t * pState, struct RenderModel_ComponentState_t * pComponentState);
+	bool (OPENVR_FNTABLE_CALLTYPE *RenderModelHasComponent)(char * pchRenderModelName, char * pchComponentName);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetRenderModelThumbnailURL)(char * pchRenderModelName, char * pchThumbnailURL, uint32_t unThumbnailURLLen, EVRRenderModelError * peError);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetRenderModelOriginalPath)(char * pchRenderModelName, char * pchOriginalPath, uint32_t unOriginalPathLen, EVRRenderModelError * peError);
+	char * (OPENVR_FNTABLE_CALLTYPE *GetRenderModelErrorNameFromEnum)(EVRRenderModelError error);
+};
+
+struct VR_IVRNotifications_FnTable
+{
+	EVRNotificationError (OPENVR_FNTABLE_CALLTYPE *CreateNotification)(VROverlayHandle_t ulOverlayHandle, uint64_t ulUserValue, EVRNotificationType type, char * pchText, EVRNotificationStyle style, struct NotificationBitmap_t * pImage, VRNotificationId * pNotificationId);
+	EVRNotificationError (OPENVR_FNTABLE_CALLTYPE *RemoveNotification)(VRNotificationId notificationId);
+};
+
+struct VR_IVRSettings_FnTable
+{
+	char * (OPENVR_FNTABLE_CALLTYPE *GetSettingsErrorNameFromEnum)(EVRSettingsError eError);
+	bool (OPENVR_FNTABLE_CALLTYPE *Sync)(bool bForce, EVRSettingsError * peError);
+	void (OPENVR_FNTABLE_CALLTYPE *SetBool)(char * pchSection, char * pchSettingsKey, bool bValue, EVRSettingsError * peError);
+	void (OPENVR_FNTABLE_CALLTYPE *SetInt32)(char * pchSection, char * pchSettingsKey, int32_t nValue, EVRSettingsError * peError);
+	void (OPENVR_FNTABLE_CALLTYPE *SetFloat)(char * pchSection, char * pchSettingsKey, float flValue, EVRSettingsError * peError);
+	void (OPENVR_FNTABLE_CALLTYPE *SetString)(char * pchSection, char * pchSettingsKey, char * pchValue, EVRSettingsError * peError);
+	bool (OPENVR_FNTABLE_CALLTYPE *GetBool)(char * pchSection, char * pchSettingsKey, EVRSettingsError * peError);
+	int32_t (OPENVR_FNTABLE_CALLTYPE *GetInt32)(char * pchSection, char * pchSettingsKey, EVRSettingsError * peError);
+	float (OPENVR_FNTABLE_CALLTYPE *GetFloat)(char * pchSection, char * pchSettingsKey, EVRSettingsError * peError);
+	void (OPENVR_FNTABLE_CALLTYPE *GetString)(char * pchSection, char * pchSettingsKey, char * pchValue, uint32_t unValueLen, EVRSettingsError * peError);
+	void (OPENVR_FNTABLE_CALLTYPE *RemoveSection)(char * pchSection, EVRSettingsError * peError);
+	void (OPENVR_FNTABLE_CALLTYPE *RemoveKeyInSection)(char * pchSection, char * pchSettingsKey, EVRSettingsError * peError);
+};
+
+struct VR_IVRScreenshots_FnTable
+{
+	EVRScreenshotError (OPENVR_FNTABLE_CALLTYPE *RequestScreenshot)(ScreenshotHandle_t * pOutScreenshotHandle, EVRScreenshotType type, char * pchPreviewFilename, char * pchVRFilename);
+	EVRScreenshotError (OPENVR_FNTABLE_CALLTYPE *HookScreenshot)(EVRScreenshotType * pSupportedTypes, int numTypes);
+	EVRScreenshotType (OPENVR_FNTABLE_CALLTYPE *GetScreenshotPropertyType)(ScreenshotHandle_t screenshotHandle, EVRScreenshotError * pError);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetScreenshotPropertyFilename)(ScreenshotHandle_t screenshotHandle, EVRScreenshotPropertyFilenames filenameType, char * pchFilename, uint32_t cchFilename, EVRScreenshotError * pError);
+	EVRScreenshotError (OPENVR_FNTABLE_CALLTYPE *UpdateScreenshotProgress)(ScreenshotHandle_t screenshotHandle, float flProgress);
+	EVRScreenshotError (OPENVR_FNTABLE_CALLTYPE *TakeStereoScreenshot)(ScreenshotHandle_t * pOutScreenshotHandle, char * pchPreviewFilename, char * pchVRFilename);
+	EVRScreenshotError (OPENVR_FNTABLE_CALLTYPE *SubmitScreenshot)(ScreenshotHandle_t screenshotHandle, EVRScreenshotType type, char * pchSourcePreviewFilename, char * pchSourceVRFilename);
+};
+
+struct VR_IVRResources_FnTable
+{
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *LoadSharedResource)(char * pchResourceName, char * pchBuffer, uint32_t unBufferLen);
+	uint32_t (OPENVR_FNTABLE_CALLTYPE *GetResourceFullPath)(char * pchResourceName, char * pchResourceTypeDirectory, char * pchPathBuffer, uint32_t unBufferLen);
+};
+
+
+#if 0
+// Global entry points
+S_API intptr_t VR_InitInternal( EVRInitError *peError, EVRApplicationType eType );
+S_API void VR_ShutdownInternal();
+S_API bool VR_IsHmdPresent();
+S_API intptr_t VR_GetGenericInterface( const char *pchInterfaceVersion, EVRInitError *peError );
+S_API bool VR_IsRuntimeInstalled();
+S_API const char * VR_GetVRInitErrorAsSymbol( EVRInitError error );
+S_API const char * VR_GetVRInitErrorAsEnglishDescription( EVRInitError error );
+#endif
+
+#endif // __OPENVR_API_FLAT_H__
+
+
diff --git a/third_party/openvr/src/headers/openvr_driver.h b/third_party/openvr/src/headers/openvr_driver.h
new file mode 100644
index 0000000..455f8e8e0
--- /dev/null
+++ b/third_party/openvr/src/headers/openvr_driver.h
@@ -0,0 +1,2541 @@
+#pragma once
+
+// openvr_driver.h
+//========= Copyright Valve Corporation ============//
+// Dynamically generated file. Do not modify this file directly.
+
+#ifndef _OPENVR_DRIVER_API
+#define _OPENVR_DRIVER_API
+
+#include <stdint.h>
+
+
+
+// vrtypes.h
+#ifndef _INCLUDE_VRTYPES_H
+#define _INCLUDE_VRTYPES_H
+
+// Forward declarations to avoid requiring vulkan.h
+struct VkDevice_T;
+struct VkPhysicalDevice_T;
+struct VkInstance_T;
+struct VkQueue_T;
+
+// Forward declarations to avoid requiring d3d12.h
+struct ID3D12Resource;
+struct ID3D12CommandQueue;
+
+namespace vr
+{
+
+#if defined(__linux__) || defined(__APPLE__) 
+	// The 32-bit version of gcc has the alignment requirement for uint64 and double set to
+	// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned.
+	// The 64-bit version of gcc has the alignment requirement for these types set to
+	// 8 meaning that unless we use #pragma pack(4) our structures will get bigger.
+	// The 64-bit structure packing has to match the 32-bit structure packing for each platform.
+	#pragma pack( push, 4 )
+#else
+	#pragma pack( push, 8 )
+#endif
+
+typedef void* glSharedTextureHandle_t;
+typedef int32_t glInt_t;
+typedef uint32_t glUInt_t;
+
+// right-handed system
+// +y is up
+// +x is to the right
+// -z is going away from you
+// Distance unit is  meters
+struct HmdMatrix34_t
+{
+	float m[3][4];
+};
+
+struct HmdMatrix44_t
+{
+	float m[4][4];
+};
+
+struct HmdVector3_t
+{
+	float v[3];
+};
+
+struct HmdVector4_t
+{
+	float v[4];
+};
+
+struct HmdVector3d_t
+{
+	double v[3];
+};
+
+struct HmdVector2_t
+{
+	float v[2];
+};
+
+struct HmdQuaternion_t
+{
+	double w, x, y, z;
+};
+
+struct HmdColor_t
+{
+	float r, g, b, a;
+};
+
+struct HmdQuad_t
+{
+	HmdVector3_t vCorners[ 4 ];
+};
+
+struct HmdRect2_t
+{
+	HmdVector2_t vTopLeft;
+	HmdVector2_t vBottomRight;
+};
+
+/** Used to return the post-distortion UVs for each color channel. 
+* UVs range from 0 to 1 with 0,0 in the upper left corner of the 
+* source render target. The 0,0 to 1,1 range covers a single eye. */
+struct DistortionCoordinates_t
+{
+	float rfRed[2];
+	float rfGreen[2];
+	float rfBlue[2];
+};
+
+enum EVREye
+{
+	Eye_Left = 0,
+	Eye_Right = 1
+};
+
+enum ETextureType
+{
+	TextureType_DirectX = 0, // Handle is an ID3D11Texture
+	TextureType_OpenGL = 1,  // Handle is an OpenGL texture name or an OpenGL render buffer name, depending on submit flags
+	TextureType_Vulkan = 2, // Handle is a pointer to a VRVulkanTextureData_t structure
+	TextureType_IOSurface = 3, // Handle is a macOS cross-process-sharable IOSurface
+	TextureType_DirectX12 = 4, // Handle is a pointer to a D3D12TextureData_t structure
+};
+
+enum EColorSpace
+{
+	ColorSpace_Auto = 0,	// Assumes 'gamma' for 8-bit per component formats, otherwise 'linear'.  This mirrors the DXGI formats which have _SRGB variants.
+	ColorSpace_Gamma = 1,	// Texture data can be displayed directly on the display without any conversion (a.k.a. display native format).
+	ColorSpace_Linear = 2,	// Same as gamma but has been converted to a linear representation using DXGI's sRGB conversion algorithm.
+};
+
+struct Texture_t
+{
+	void* handle; // See ETextureType definition above
+	ETextureType eType;
+	EColorSpace eColorSpace;
+};
+
+// Handle to a shared texture (HANDLE on Windows obtained using OpenSharedResource).
+typedef uint64_t SharedTextureHandle_t;
+#define INVALID_SHARED_TEXTURE_HANDLE	((vr::SharedTextureHandle_t)0)
+
+enum ETrackingResult
+{
+	TrackingResult_Uninitialized			= 1,
+
+	TrackingResult_Calibrating_InProgress	= 100,
+	TrackingResult_Calibrating_OutOfRange	= 101,
+
+	TrackingResult_Running_OK				= 200,
+	TrackingResult_Running_OutOfRange		= 201,
+};
+
+static const uint32_t k_unMaxDriverDebugResponseSize = 32768;
+
+/** Used to pass device IDs to API calls */
+typedef uint32_t TrackedDeviceIndex_t;
+static const uint32_t k_unTrackedDeviceIndex_Hmd = 0;
+static const uint32_t k_unMaxTrackedDeviceCount = 16;
+static const uint32_t k_unTrackedDeviceIndexOther = 0xFFFFFFFE;
+static const uint32_t k_unTrackedDeviceIndexInvalid = 0xFFFFFFFF;
+
+/** Describes what kind of object is being tracked at a given ID */
+enum ETrackedDeviceClass
+{
+	TrackedDeviceClass_Invalid = 0,				// the ID was not valid.
+	TrackedDeviceClass_HMD = 1,					// Head-Mounted Displays
+	TrackedDeviceClass_Controller = 2,			// Tracked controllers
+	TrackedDeviceClass_GenericTracker = 3,		// Generic trackers, similar to controllers
+	TrackedDeviceClass_TrackingReference = 4,	// Camera and base stations that serve as tracking reference points
+};
+
+
+/** Describes what specific role associated with a tracked device */
+enum ETrackedControllerRole
+{
+	TrackedControllerRole_Invalid = 0,					// Invalid value for controller type
+	TrackedControllerRole_LeftHand = 1,					// Tracked device associated with the left hand
+	TrackedControllerRole_RightHand = 2,				// Tracked device associated with the right hand
+};
+
+
+/** describes a single pose for a tracked object */
+struct TrackedDevicePose_t
+{
+	HmdMatrix34_t mDeviceToAbsoluteTracking;
+	HmdVector3_t vVelocity;				// velocity in tracker space in m/s
+	HmdVector3_t vAngularVelocity;		// angular velocity in radians/s (?)
+	ETrackingResult eTrackingResult;
+	bool bPoseIsValid;
+
+	// This indicates that there is a device connected for this spot in the pose array.
+	// It could go from true to false if the user unplugs the device.
+	bool bDeviceIsConnected;
+};
+
+/** Identifies which style of tracking origin the application wants to use
+* for the poses it is requesting */
+enum ETrackingUniverseOrigin
+{
+	TrackingUniverseSeated = 0,		// Poses are provided relative to the seated zero pose
+	TrackingUniverseStanding = 1,	// Poses are provided relative to the safe bounds configured by the user
+	TrackingUniverseRawAndUncalibrated = 2,	// Poses are provided in the coordinate system defined by the driver.  It has Y up and is unified for devices of the same driver. You usually don't want this one.
+};
+
+// Refers to a single container of properties
+typedef uint64_t PropertyContainerHandle_t;
+typedef uint32_t PropertyTypeTag_t;
+
+static const PropertyContainerHandle_t k_ulInvalidPropertyContainer = 0;
+static const PropertyTypeTag_t k_unInvalidPropertyTag = 0;
+
+// Use these tags to set/get common types as struct properties
+static const PropertyTypeTag_t k_unFloatPropertyTag = 1;
+static const PropertyTypeTag_t k_unInt32PropertyTag = 2;
+static const PropertyTypeTag_t k_unUint64PropertyTag = 3;
+static const PropertyTypeTag_t k_unBoolPropertyTag = 4;
+static const PropertyTypeTag_t k_unStringPropertyTag = 5;
+
+static const PropertyTypeTag_t k_unHmdMatrix34PropertyTag = 20;
+static const PropertyTypeTag_t k_unHmdMatrix44PropertyTag = 21;
+static const PropertyTypeTag_t k_unHmdVector3PropertyTag = 22;
+static const PropertyTypeTag_t k_unHmdVector4PropertyTag = 23;
+
+static const PropertyTypeTag_t k_unHiddenAreaPropertyTag = 30;
+
+static const PropertyTypeTag_t k_unOpenVRInternalReserved_Start = 1000;
+static const PropertyTypeTag_t k_unOpenVRInternalReserved_End = 10000;
+
+
+/** Each entry in this enum represents a property that can be retrieved about a
+* tracked device. Many fields are only valid for one ETrackedDeviceClass. */
+enum ETrackedDeviceProperty
+{
+	Prop_Invalid								= 0,
+
+	// general properties that apply to all device classes
+	Prop_TrackingSystemName_String				= 1000,
+	Prop_ModelNumber_String						= 1001,
+	Prop_SerialNumber_String					= 1002,
+	Prop_RenderModelName_String					= 1003,
+	Prop_WillDriftInYaw_Bool					= 1004,
+	Prop_ManufacturerName_String				= 1005,
+	Prop_TrackingFirmwareVersion_String			= 1006,
+	Prop_HardwareRevision_String				= 1007,
+	Prop_AllWirelessDongleDescriptions_String	= 1008,
+	Prop_ConnectedWirelessDongle_String			= 1009,
+	Prop_DeviceIsWireless_Bool					= 1010,
+	Prop_DeviceIsCharging_Bool					= 1011,
+	Prop_DeviceBatteryPercentage_Float			= 1012, // 0 is empty, 1 is full
+	Prop_StatusDisplayTransform_Matrix34		= 1013,
+	Prop_Firmware_UpdateAvailable_Bool			= 1014,
+	Prop_Firmware_ManualUpdate_Bool				= 1015,
+	Prop_Firmware_ManualUpdateURL_String		= 1016,
+	Prop_HardwareRevision_Uint64				= 1017,
+	Prop_FirmwareVersion_Uint64					= 1018,
+	Prop_FPGAVersion_Uint64						= 1019,
+	Prop_VRCVersion_Uint64						= 1020,
+	Prop_RadioVersion_Uint64					= 1021,
+	Prop_DongleVersion_Uint64					= 1022,
+	Prop_BlockServerShutdown_Bool				= 1023,
+	Prop_CanUnifyCoordinateSystemWithHmd_Bool	= 1024,
+	Prop_ContainsProximitySensor_Bool			= 1025,
+	Prop_DeviceProvidesBatteryStatus_Bool		= 1026,
+	Prop_DeviceCanPowerOff_Bool					= 1027,
+	Prop_Firmware_ProgrammingTarget_String		= 1028,
+	Prop_DeviceClass_Int32						= 1029,
+	Prop_HasCamera_Bool							= 1030,
+	Prop_DriverVersion_String                   = 1031,
+	Prop_Firmware_ForceUpdateRequired_Bool      = 1032,
+	Prop_ViveSystemButtonFixRequired_Bool		= 1033,
+	Prop_ParentDriver_Uint64					= 1034,
+
+
+	// Properties that are unique to TrackedDeviceClass_HMD
+	Prop_ReportsTimeSinceVSync_Bool				= 2000,
+	Prop_SecondsFromVsyncToPhotons_Float		= 2001,
+	Prop_DisplayFrequency_Float					= 2002,
+	Prop_UserIpdMeters_Float					= 2003,
+	Prop_CurrentUniverseId_Uint64				= 2004, 
+	Prop_PreviousUniverseId_Uint64				= 2005, 
+	Prop_DisplayFirmwareVersion_Uint64			= 2006,
+	Prop_IsOnDesktop_Bool						= 2007,
+	Prop_DisplayMCType_Int32					= 2008,
+	Prop_DisplayMCOffset_Float					= 2009,
+	Prop_DisplayMCScale_Float					= 2010,
+	Prop_EdidVendorID_Int32						= 2011,
+	Prop_DisplayMCImageLeft_String              = 2012,
+	Prop_DisplayMCImageRight_String             = 2013,
+	Prop_DisplayGCBlackClamp_Float				= 2014,
+	Prop_EdidProductID_Int32					= 2015,
+	Prop_CameraToHeadTransform_Matrix34			= 2016,
+	Prop_DisplayGCType_Int32					= 2017,
+	Prop_DisplayGCOffset_Float					= 2018,
+	Prop_DisplayGCScale_Float					= 2019,
+	Prop_DisplayGCPrescale_Float				= 2020,
+	Prop_DisplayGCImage_String					= 2021,
+	Prop_LensCenterLeftU_Float					= 2022,
+	Prop_LensCenterLeftV_Float					= 2023,
+	Prop_LensCenterRightU_Float					= 2024,
+	Prop_LensCenterRightV_Float					= 2025,
+	Prop_UserHeadToEyeDepthMeters_Float			= 2026,
+	Prop_CameraFirmwareVersion_Uint64			= 2027,
+	Prop_CameraFirmwareDescription_String		= 2028,
+	Prop_DisplayFPGAVersion_Uint64				= 2029,
+	Prop_DisplayBootloaderVersion_Uint64		= 2030,
+	Prop_DisplayHardwareVersion_Uint64			= 2031,
+	Prop_AudioFirmwareVersion_Uint64			= 2032,
+	Prop_CameraCompatibilityMode_Int32			= 2033,
+	Prop_ScreenshotHorizontalFieldOfViewDegrees_Float = 2034,
+	Prop_ScreenshotVerticalFieldOfViewDegrees_Float = 2035,
+	Prop_DisplaySuppressed_Bool					= 2036,
+	Prop_DisplayAllowNightMode_Bool				= 2037,
+	Prop_DisplayMCImageWidth_Int32				= 2038,
+	Prop_DisplayMCImageHeight_Int32				= 2039,
+	Prop_DisplayMCImageNumChannels_Int32		= 2040,
+	Prop_DisplayMCImageData_Binary				= 2041,
+	Prop_UsesDriverDirectMode_Bool				= 2042,
+
+	// Properties that are unique to TrackedDeviceClass_Controller
+	Prop_AttachedDeviceId_String				= 3000,
+	Prop_SupportedButtons_Uint64				= 3001,
+	Prop_Axis0Type_Int32						= 3002, // Return value is of type EVRControllerAxisType
+	Prop_Axis1Type_Int32						= 3003, // Return value is of type EVRControllerAxisType
+	Prop_Axis2Type_Int32						= 3004, // Return value is of type EVRControllerAxisType
+	Prop_Axis3Type_Int32						= 3005, // Return value is of type EVRControllerAxisType
+	Prop_Axis4Type_Int32						= 3006, // Return value is of type EVRControllerAxisType
+	Prop_ControllerRoleHint_Int32				= 3007, // Return value is of type ETrackedControllerRole
+
+	// Properties that are unique to TrackedDeviceClass_TrackingReference
+	Prop_FieldOfViewLeftDegrees_Float			= 4000,
+	Prop_FieldOfViewRightDegrees_Float			= 4001,
+	Prop_FieldOfViewTopDegrees_Float			= 4002,
+	Prop_FieldOfViewBottomDegrees_Float			= 4003,
+	Prop_TrackingRangeMinimumMeters_Float		= 4004,
+	Prop_TrackingRangeMaximumMeters_Float		= 4005,
+	Prop_ModeLabel_String						= 4006,
+
+	// Properties that are used for user interface like icons names
+	Prop_IconPathName_String						= 5000, // usually a directory named "icons"
+	Prop_NamedIconPathDeviceOff_String				= 5001, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceSearching_String		= 5002, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceSearchingAlert_String	= 5003, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceReady_String			= 5004, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceReadyAlert_String		= 5005, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceNotReady_String			= 5006, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceStandby_String			= 5007, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+	Prop_NamedIconPathDeviceAlertLow_String			= 5008, // PNG for static icon, or GIF for animation, 50x32 for headsets and 32x32 for others
+
+	// Properties that are used by helpers, but are opaque to applications
+	Prop_DisplayHiddenArea_Binary_Start				= 5100,
+	Prop_DisplayHiddenArea_Binary_End				= 5150,
+
+	// Properties that are unique to drivers
+	Prop_UserConfigPath_String					= 6000,
+	Prop_InstallPath_String						= 6001,
+
+	// Vendors are free to expose private debug data in this reserved region
+	Prop_VendorSpecific_Reserved_Start			= 10000,
+	Prop_VendorSpecific_Reserved_End			= 10999,
+};
+
+/** No string property will ever be longer than this length */
+static const uint32_t k_unMaxPropertyStringSize = 32 * 1024;
+
+/** Used to return errors that occur when reading properties. */
+enum ETrackedPropertyError
+{
+	TrackedProp_Success						= 0,
+	TrackedProp_WrongDataType				= 1,
+	TrackedProp_WrongDeviceClass			= 2,
+	TrackedProp_BufferTooSmall				= 3,
+	TrackedProp_UnknownProperty				= 4, // Driver has not set the property (and may not ever).
+	TrackedProp_InvalidDevice				= 5,
+	TrackedProp_CouldNotContactServer		= 6,
+	TrackedProp_ValueNotProvidedByDevice	= 7,
+	TrackedProp_StringExceedsMaximumLength	= 8,
+	TrackedProp_NotYetAvailable				= 9, // The property value isn't known yet, but is expected soon. Call again later.
+	TrackedProp_PermissionDenied			= 10,
+	TrackedProp_InvalidOperation			= 11,
+};
+
+/** Allows the application to control what part of the provided texture will be used in the
+* frame buffer. */
+struct VRTextureBounds_t
+{
+	float uMin, vMin;
+	float uMax, vMax;
+};
+
+
+/** Allows the application to control how scene textures are used by the compositor when calling Submit. */
+enum EVRSubmitFlags
+{
+	// Simple render path. App submits rendered left and right eye images with no lens distortion correction applied.
+	Submit_Default = 0x00,
+
+	// App submits final left and right eye images with lens distortion already applied (lens distortion makes the images appear
+	// barrel distorted with chromatic aberration correction applied). The app would have used the data returned by
+	// vr::IVRSystem::ComputeDistortion() to apply the correct distortion to the rendered images before calling Submit().
+	Submit_LensDistortionAlreadyApplied = 0x01,
+
+	// If the texture pointer passed in is actually a renderbuffer (e.g. for MSAA in OpenGL) then set this flag.
+	Submit_GlRenderBuffer = 0x02,
+
+	// Do not use
+	Submit_Reserved = 0x04,
+};
+
+/** Data required for passing Vulkan textures to IVRCompositor::Submit.
+* Be sure to call OpenVR_Shutdown before destroying these resources. */
+struct VRVulkanTextureData_t
+{
+	uint64_t m_nImage; // VkImage
+	VkDevice_T *m_pDevice;
+	VkPhysicalDevice_T *m_pPhysicalDevice;
+	VkInstance_T *m_pInstance;
+	VkQueue_T *m_pQueue;
+	uint32_t m_nQueueFamilyIndex;
+	uint32_t m_nWidth, m_nHeight, m_nFormat, m_nSampleCount;
+};
+
+/** Data required for passing D3D12 textures to IVRCompositor::Submit.
+* Be sure to call OpenVR_Shutdown before destroying these resources. */
+struct D3D12TextureData_t
+{
+	ID3D12Resource *m_pResource;
+	ID3D12CommandQueue *m_pCommandQueue;
+	uint32_t m_nNodeMask;
+};
+
+/** Status of the overall system or tracked objects */
+enum EVRState
+{
+	VRState_Undefined = -1,
+	VRState_Off = 0,
+	VRState_Searching = 1,
+	VRState_Searching_Alert = 2,
+	VRState_Ready = 3,
+	VRState_Ready_Alert = 4,
+	VRState_NotReady = 5,
+	VRState_Standby = 6,
+	VRState_Ready_Alert_Low = 7,
+};
+
+/** The types of events that could be posted (and what the parameters mean for each event type) */
+enum EVREventType
+{
+	VREvent_None = 0,
+
+	VREvent_TrackedDeviceActivated		= 100,
+	VREvent_TrackedDeviceDeactivated	= 101,
+	VREvent_TrackedDeviceUpdated		= 102,
+	VREvent_TrackedDeviceUserInteractionStarted	= 103,
+	VREvent_TrackedDeviceUserInteractionEnded	= 104,
+	VREvent_IpdChanged					= 105,
+	VREvent_EnterStandbyMode			= 106,
+	VREvent_LeaveStandbyMode			= 107,
+	VREvent_TrackedDeviceRoleChanged	= 108,
+	VREvent_WatchdogWakeUpRequested		= 109,
+	VREvent_LensDistortionChanged		= 110,
+	VREvent_PropertyChanged				= 111,
+
+	VREvent_ButtonPress					= 200, // data is controller
+	VREvent_ButtonUnpress				= 201, // data is controller
+	VREvent_ButtonTouch					= 202, // data is controller
+	VREvent_ButtonUntouch				= 203, // data is controller
+
+	VREvent_MouseMove					= 300, // data is mouse
+	VREvent_MouseButtonDown				= 301, // data is mouse
+	VREvent_MouseButtonUp				= 302, // data is mouse
+	VREvent_FocusEnter					= 303, // data is overlay
+	VREvent_FocusLeave					= 304, // data is overlay
+	VREvent_Scroll						= 305, // data is mouse
+	VREvent_TouchPadMove				= 306, // data is mouse
+	VREvent_OverlayFocusChanged			= 307, // data is overlay, global event
+
+	VREvent_InputFocusCaptured			= 400, // data is process DEPRECATED
+	VREvent_InputFocusReleased			= 401, // data is process DEPRECATED
+	VREvent_SceneFocusLost				= 402, // data is process
+	VREvent_SceneFocusGained			= 403, // data is process
+	VREvent_SceneApplicationChanged		= 404, // data is process - The App actually drawing the scene changed (usually to or from the compositor)
+	VREvent_SceneFocusChanged			= 405, // data is process - New app got access to draw the scene
+	VREvent_InputFocusChanged			= 406, // data is process
+	VREvent_SceneApplicationSecondaryRenderingStarted = 407, // data is process
+
+	VREvent_HideRenderModels			= 410, // Sent to the scene application to request hiding render models temporarily
+	VREvent_ShowRenderModels			= 411, // Sent to the scene application to request restoring render model visibility
+
+	VREvent_OverlayShown				= 500,
+	VREvent_OverlayHidden				= 501,
+	VREvent_DashboardActivated			= 502,
+	VREvent_DashboardDeactivated		= 503,
+	VREvent_DashboardThumbSelected		= 504, // Sent to the overlay manager - data is overlay
+	VREvent_DashboardRequested			= 505, // Sent to the overlay manager - data is overlay
+	VREvent_ResetDashboard				= 506, // Send to the overlay manager
+	VREvent_RenderToast					= 507, // Send to the dashboard to render a toast - data is the notification ID
+	VREvent_ImageLoaded					= 508, // Sent to overlays when a SetOverlayRaw or SetOverlayFromFile call finishes loading
+	VREvent_ShowKeyboard				= 509, // Sent to keyboard renderer in the dashboard to invoke it
+	VREvent_HideKeyboard				= 510, // Sent to keyboard renderer in the dashboard to hide it
+	VREvent_OverlayGamepadFocusGained	= 511, // Sent to an overlay when IVROverlay::SetFocusOverlay is called on it
+	VREvent_OverlayGamepadFocusLost		= 512, // Send to an overlay when it previously had focus and IVROverlay::SetFocusOverlay is called on something else
+	VREvent_OverlaySharedTextureChanged = 513,
+	VREvent_DashboardGuideButtonDown	= 514,
+	VREvent_DashboardGuideButtonUp		= 515,
+	VREvent_ScreenshotTriggered			= 516, // Screenshot button combo was pressed, Dashboard should request a screenshot
+	VREvent_ImageFailed					= 517, // Sent to overlays when a SetOverlayRaw or SetOverlayfromFail fails to load
+	VREvent_DashboardOverlayCreated		= 518,
+
+	// Screenshot API
+	VREvent_RequestScreenshot				= 520, // Sent by vrclient application to compositor to take a screenshot
+	VREvent_ScreenshotTaken					= 521, // Sent by compositor to the application that the screenshot has been taken
+	VREvent_ScreenshotFailed				= 522, // Sent by compositor to the application that the screenshot failed to be taken
+	VREvent_SubmitScreenshotToDashboard		= 523, // Sent by compositor to the dashboard that a completed screenshot was submitted
+	VREvent_ScreenshotProgressToDashboard	= 524, // Sent by compositor to the dashboard that a completed screenshot was submitted
+
+	VREvent_PrimaryDashboardDeviceChanged	= 525,
+
+	VREvent_Notification_Shown				= 600,
+	VREvent_Notification_Hidden				= 601,
+	VREvent_Notification_BeginInteraction	= 602,
+	VREvent_Notification_Destroyed			= 603,
+
+	VREvent_Quit							= 700, // data is process
+	VREvent_ProcessQuit						= 701, // data is process
+	VREvent_QuitAborted_UserPrompt			= 702, // data is process
+	VREvent_QuitAcknowledged				= 703, // data is process
+	VREvent_DriverRequestedQuit				= 704, // The driver has requested that SteamVR shut down
+
+	VREvent_ChaperoneDataHasChanged			= 800,
+	VREvent_ChaperoneUniverseHasChanged		= 801,
+	VREvent_ChaperoneTempDataHasChanged		= 802,
+	VREvent_ChaperoneSettingsHaveChanged	= 803,
+	VREvent_SeatedZeroPoseReset				= 804,
+
+	VREvent_AudioSettingsHaveChanged		= 820,
+
+	VREvent_BackgroundSettingHasChanged		= 850,
+	VREvent_CameraSettingsHaveChanged		= 851,
+	VREvent_ReprojectionSettingHasChanged	= 852,
+	VREvent_ModelSkinSettingsHaveChanged	= 853,
+	VREvent_EnvironmentSettingsHaveChanged	= 854,
+	VREvent_PowerSettingsHaveChanged		= 855,
+
+	VREvent_StatusUpdate					= 900,
+
+	VREvent_MCImageUpdated					= 1000,
+
+	VREvent_FirmwareUpdateStarted			= 1100,
+	VREvent_FirmwareUpdateFinished			= 1101,
+
+	VREvent_KeyboardClosed					= 1200,
+	VREvent_KeyboardCharInput				= 1201,
+	VREvent_KeyboardDone					= 1202, // Sent when DONE button clicked on keyboard
+
+	VREvent_ApplicationTransitionStarted		= 1300,
+	VREvent_ApplicationTransitionAborted		= 1301,
+	VREvent_ApplicationTransitionNewAppStarted	= 1302,
+	VREvent_ApplicationListUpdated				= 1303,
+	VREvent_ApplicationMimeTypeLoad				= 1304,
+	VREvent_ApplicationTransitionNewAppLaunchComplete = 1305,
+
+	VREvent_Compositor_MirrorWindowShown		= 1400,
+	VREvent_Compositor_MirrorWindowHidden		= 1401,
+	VREvent_Compositor_ChaperoneBoundsShown		= 1410,
+	VREvent_Compositor_ChaperoneBoundsHidden	= 1411,
+
+	VREvent_TrackedCamera_StartVideoStream  = 1500,
+	VREvent_TrackedCamera_StopVideoStream   = 1501,
+	VREvent_TrackedCamera_PauseVideoStream  = 1502,
+	VREvent_TrackedCamera_ResumeVideoStream = 1503,
+	VREvent_TrackedCamera_EditingSurface    = 1550,
+
+	VREvent_PerformanceTest_EnableCapture	= 1600,
+	VREvent_PerformanceTest_DisableCapture	= 1601,
+	VREvent_PerformanceTest_FidelityLevel	= 1602,
+
+	VREvent_MessageOverlay_Closed			= 1650,
+	
+	// Vendors are free to expose private events in this reserved region
+	VREvent_VendorSpecific_Reserved_Start	= 10000,
+	VREvent_VendorSpecific_Reserved_End		= 19999,
+};
+
+
+/** Level of Hmd activity */
+enum EDeviceActivityLevel
+{
+	k_EDeviceActivityLevel_Unknown = -1,
+	k_EDeviceActivityLevel_Idle = 0,
+	k_EDeviceActivityLevel_UserInteraction = 1,
+	k_EDeviceActivityLevel_UserInteraction_Timeout = 2,
+	k_EDeviceActivityLevel_Standby = 3,
+};
+
+
+/** VR controller button and axis IDs */
+enum EVRButtonId
+{
+	k_EButton_System			= 0,
+	k_EButton_ApplicationMenu	= 1,
+	k_EButton_Grip				= 2,
+	k_EButton_DPad_Left			= 3,
+	k_EButton_DPad_Up			= 4,
+	k_EButton_DPad_Right		= 5,
+	k_EButton_DPad_Down			= 6,
+	k_EButton_A					= 7,
+	
+	k_EButton_ProximitySensor   = 31,
+
+	k_EButton_Axis0				= 32,
+	k_EButton_Axis1				= 33,
+	k_EButton_Axis2				= 34,
+	k_EButton_Axis3				= 35,
+	k_EButton_Axis4				= 36,
+
+	// aliases for well known controllers
+	k_EButton_SteamVR_Touchpad	= k_EButton_Axis0,
+	k_EButton_SteamVR_Trigger	= k_EButton_Axis1,
+
+	k_EButton_Dashboard_Back	= k_EButton_Grip,
+
+	k_EButton_Max				= 64
+};
+
+inline uint64_t ButtonMaskFromId( EVRButtonId id ) { return 1ull << id; }
+
+/** used for controller button events */
+struct VREvent_Controller_t
+{
+	uint32_t button; // EVRButtonId enum
+};
+
+
+/** used for simulated mouse events in overlay space */
+enum EVRMouseButton
+{
+	VRMouseButton_Left					= 0x0001,
+	VRMouseButton_Right					= 0x0002,
+	VRMouseButton_Middle				= 0x0004,
+};
+
+
+/** used for simulated mouse events in overlay space */
+struct VREvent_Mouse_t
+{
+	float x, y; // co-ords are in GL space, bottom left of the texture is 0,0
+	uint32_t button; // EVRMouseButton enum
+};
+
+/** used for simulated mouse wheel scroll in overlay space */
+struct VREvent_Scroll_t
+{
+	float xdelta, ydelta; // movement in fraction of the pad traversed since last delta, 1.0 for a full swipe
+	uint32_t repeatCount;
+};
+
+/** when in mouse input mode you can receive data from the touchpad, these events are only sent if the users finger
+   is on the touchpad (or just released from it) 
+**/
+struct VREvent_TouchPadMove_t
+{
+	// true if the users finger is detected on the touch pad
+	bool bFingerDown;
+
+	// How long the finger has been down in seconds
+	float flSecondsFingerDown;
+
+	// These values indicate the starting finger position (so you can do some basic swipe stuff)
+	float fValueXFirst;
+	float fValueYFirst;
+
+	// This is the raw sampled coordinate without deadzoning
+	float fValueXRaw;
+	float fValueYRaw;
+};
+
+/** notification related events. Details will still change at this point */
+struct VREvent_Notification_t
+{
+	uint64_t ulUserValue;
+	uint32_t notificationId;
+};
+
+/** Used for events about processes */
+struct VREvent_Process_t
+{
+	uint32_t pid;
+	uint32_t oldPid;
+	bool bForced;
+};
+
+
+/** Used for a few events about overlays */
+struct VREvent_Overlay_t
+{
+	uint64_t overlayHandle;
+};
+
+
+/** Used for a few events about overlays */
+struct VREvent_Status_t
+{
+	uint32_t statusState; // EVRState enum
+};
+
+/** Used for keyboard events **/
+struct VREvent_Keyboard_t
+{
+	char cNewInput[8];	// Up to 11 bytes of new input
+	uint64_t uUserValue;	// Possible flags about the new input
+};
+
+struct VREvent_Ipd_t
+{
+	float ipdMeters;
+};
+
+struct VREvent_Chaperone_t
+{
+	uint64_t m_nPreviousUniverse;
+	uint64_t m_nCurrentUniverse;
+};
+
+/** Not actually used for any events */
+struct VREvent_Reserved_t
+{
+	uint64_t reserved0;
+	uint64_t reserved1;
+};
+
+struct VREvent_PerformanceTest_t
+{
+	uint32_t m_nFidelityLevel;
+};
+
+struct VREvent_SeatedZeroPoseReset_t
+{
+	bool bResetBySystemMenu;
+};
+
+struct VREvent_Screenshot_t
+{
+	uint32_t handle;
+	uint32_t type;
+};
+
+struct VREvent_ScreenshotProgress_t
+{
+	float progress;
+};
+
+struct VREvent_ApplicationLaunch_t
+{
+	uint32_t pid;
+	uint32_t unArgsHandle;
+};
+
+struct VREvent_EditingCameraSurface_t
+{
+	uint64_t overlayHandle;
+	uint32_t nVisualMode;
+};
+
+struct VREvent_MessageOverlay_t
+{
+	uint32_t unVRMessageOverlayResponse; // vr::VRMessageOverlayResponse enum
+};
+
+struct VREvent_Property_t
+{
+	PropertyContainerHandle_t container;
+	ETrackedDeviceProperty prop;
+};
+
+/** NOTE!!! If you change this you MUST manually update openvr_interop.cs.py */
+typedef union
+{
+	VREvent_Reserved_t reserved;
+	VREvent_Controller_t controller;
+	VREvent_Mouse_t mouse;
+	VREvent_Scroll_t scroll;
+	VREvent_Process_t process;
+	VREvent_Notification_t notification;
+	VREvent_Overlay_t overlay;
+	VREvent_Status_t status;
+	VREvent_Keyboard_t keyboard;
+	VREvent_Ipd_t ipd;
+	VREvent_Chaperone_t chaperone;
+	VREvent_PerformanceTest_t performanceTest;
+	VREvent_TouchPadMove_t touchPadMove;
+	VREvent_SeatedZeroPoseReset_t seatedZeroPoseReset;
+	VREvent_Screenshot_t screenshot;
+	VREvent_ScreenshotProgress_t screenshotProgress;
+	VREvent_ApplicationLaunch_t applicationLaunch;
+	VREvent_EditingCameraSurface_t cameraSurface;
+	VREvent_MessageOverlay_t messageOverlay;
+	VREvent_Property_t property;
+} VREvent_Data_t;
+
+/** An event posted by the server to all running applications */
+struct VREvent_t
+{
+	uint32_t eventType; // EVREventType enum
+	TrackedDeviceIndex_t trackedDeviceIndex;
+	float eventAgeSeconds;
+	// event data must be the end of the struct as its size is variable
+	VREvent_Data_t data;
+};
+
+
+/** The mesh to draw into the stencil (or depth) buffer to perform 
+* early stencil (or depth) kills of pixels that will never appear on the HMD.
+* This mesh draws on all the pixels that will be hidden after distortion. 
+*
+* If the HMD does not provide a visible area mesh pVertexData will be
+* NULL and unTriangleCount will be 0. */
+struct HiddenAreaMesh_t
+{
+	const HmdVector2_t *pVertexData;
+	uint32_t unTriangleCount;
+};
+
+
+enum EHiddenAreaMeshType
+{
+	k_eHiddenAreaMesh_Standard = 0,
+	k_eHiddenAreaMesh_Inverse = 1,
+	k_eHiddenAreaMesh_LineLoop = 2,
+
+	k_eHiddenAreaMesh_Max = 3,
+};
+
+
+/** Identifies what kind of axis is on the controller at index n. Read this type 
+* with pVRSystem->Get( nControllerDeviceIndex, Prop_Axis0Type_Int32 + n );
+*/
+enum EVRControllerAxisType
+{
+	k_eControllerAxis_None = 0,
+	k_eControllerAxis_TrackPad = 1,
+	k_eControllerAxis_Joystick = 2,
+	k_eControllerAxis_Trigger = 3, // Analog trigger data is in the X axis
+};
+
+
+/** contains information about one axis on the controller */
+struct VRControllerAxis_t
+{
+	float x; // Ranges from -1.0 to 1.0 for joysticks and track pads. Ranges from 0.0 to 1.0 for triggers were 0 is fully released.
+	float y; // Ranges from -1.0 to 1.0 for joysticks and track pads. Is always 0.0 for triggers.
+};
+
+
+/** the number of axes in the controller state */
+static const uint32_t k_unControllerStateAxisCount = 5;
+
+
+/** Holds all the state of a controller at one moment in time. */
+struct VRControllerState001_t
+{
+	// If packet num matches that on your prior call, then the controller state hasn't been changed since 
+	// your last call and there is no need to process it
+	uint32_t unPacketNum;
+
+	// bit flags for each of the buttons. Use ButtonMaskFromId to turn an ID into a mask
+	uint64_t ulButtonPressed;
+	uint64_t ulButtonTouched;
+
+	// Axis data for the controller's analog inputs
+	VRControllerAxis_t rAxis[ k_unControllerStateAxisCount ];
+};
+
+
+typedef VRControllerState001_t VRControllerState_t;
+
+
+/** determines how to provide output to the application of various event processing functions. */
+enum EVRControllerEventOutputType
+{
+	ControllerEventOutput_OSEvents = 0,
+	ControllerEventOutput_VREvents = 1,
+};
+
+
+
+/** Collision Bounds Style */
+enum ECollisionBoundsStyle
+{
+	COLLISION_BOUNDS_STYLE_BEGINNER = 0,
+	COLLISION_BOUNDS_STYLE_INTERMEDIATE,
+	COLLISION_BOUNDS_STYLE_SQUARES,
+	COLLISION_BOUNDS_STYLE_ADVANCED,
+	COLLISION_BOUNDS_STYLE_NONE,
+
+	COLLISION_BOUNDS_STYLE_COUNT
+};
+
+/** Allows the application to customize how the overlay appears in the compositor */
+struct Compositor_OverlaySettings
+{
+	uint32_t size; // sizeof(Compositor_OverlaySettings)
+	bool curved, antialias;
+	float scale, distance, alpha;
+	float uOffset, vOffset, uScale, vScale;
+	float gridDivs, gridWidth, gridScale;
+	HmdMatrix44_t transform;
+};
+
+/** used to refer to a single VR overlay */
+typedef uint64_t VROverlayHandle_t;
+
+static const VROverlayHandle_t k_ulOverlayHandleInvalid = 0;
+
+/** Errors that can occur around VR overlays */
+enum EVROverlayError
+{
+	VROverlayError_None						= 0,
+
+	VROverlayError_UnknownOverlay			= 10,
+	VROverlayError_InvalidHandle			= 11,
+	VROverlayError_PermissionDenied			= 12,
+	VROverlayError_OverlayLimitExceeded		= 13, // No more overlays could be created because the maximum number already exist
+	VROverlayError_WrongVisibilityType		= 14,
+	VROverlayError_KeyTooLong				= 15,
+	VROverlayError_NameTooLong				= 16,
+	VROverlayError_KeyInUse					= 17,
+	VROverlayError_WrongTransformType		= 18,
+	VROverlayError_InvalidTrackedDevice		= 19,
+	VROverlayError_InvalidParameter			= 20,
+	VROverlayError_ThumbnailCantBeDestroyed	= 21,
+	VROverlayError_ArrayTooSmall			= 22,
+	VROverlayError_RequestFailed			= 23,
+	VROverlayError_InvalidTexture			= 24,
+	VROverlayError_UnableToLoadFile			= 25,
+	VROverlayError_KeyboardAlreadyInUse		= 26,
+	VROverlayError_NoNeighbor				= 27,
+	VROverlayError_TooManyMaskPrimitives	= 29,
+	VROverlayError_BadMaskPrimitive			= 30,
+};
+
+/** enum values to pass in to VR_Init to identify whether the application will 
+* draw a 3D scene. */
+enum EVRApplicationType
+{
+	VRApplication_Other = 0,		// Some other kind of application that isn't covered by the other entries 
+	VRApplication_Scene	= 1,		// Application will submit 3D frames 
+	VRApplication_Overlay = 2,		// Application only interacts with overlays
+	VRApplication_Background = 3,	// Application should not start SteamVR if it's not already running, and should not
+									// keep it running if everything else quits.
+	VRApplication_Utility = 4,		// Init should not try to load any drivers. The application needs access to utility
+									// interfaces (like IVRSettings and IVRApplications) but not hardware.
+	VRApplication_VRMonitor = 5,	// Reserved for vrmonitor
+	VRApplication_SteamWatchdog = 6,// Reserved for Steam
+
+	VRApplication_Max
+};
+
+
+/** error codes for firmware */
+enum EVRFirmwareError
+{
+	VRFirmwareError_None = 0,
+	VRFirmwareError_Success = 1,
+	VRFirmwareError_Fail = 2,
+};
+
+
+/** error codes for notifications */
+enum EVRNotificationError
+{
+	VRNotificationError_OK = 0,
+	VRNotificationError_InvalidNotificationId = 100,
+	VRNotificationError_NotificationQueueFull = 101,
+	VRNotificationError_InvalidOverlayHandle = 102,
+	VRNotificationError_SystemWithUserValueAlreadyExists = 103,
+};
+
+
+/** error codes returned by Vr_Init */
+
+// Please add adequate error description to https://developer.valvesoftware.com/w/index.php?title=Category:SteamVRHelp
+enum EVRInitError
+{
+	VRInitError_None	= 0,
+	VRInitError_Unknown = 1,
+
+	VRInitError_Init_InstallationNotFound		= 100,
+	VRInitError_Init_InstallationCorrupt		= 101,
+	VRInitError_Init_VRClientDLLNotFound		= 102,
+	VRInitError_Init_FileNotFound				= 103,
+	VRInitError_Init_FactoryNotFound			= 104,
+	VRInitError_Init_InterfaceNotFound			= 105,
+	VRInitError_Init_InvalidInterface			= 106,
+	VRInitError_Init_UserConfigDirectoryInvalid = 107,
+	VRInitError_Init_HmdNotFound				= 108,
+	VRInitError_Init_NotInitialized				= 109,
+	VRInitError_Init_PathRegistryNotFound		= 110,
+	VRInitError_Init_NoConfigPath				= 111,
+	VRInitError_Init_NoLogPath					= 112,
+	VRInitError_Init_PathRegistryNotWritable	= 113,
+	VRInitError_Init_AppInfoInitFailed			= 114,
+	VRInitError_Init_Retry						= 115, // Used internally to cause retries to vrserver
+	VRInitError_Init_InitCanceledByUser			= 116, // The calling application should silently exit. The user canceled app startup
+	VRInitError_Init_AnotherAppLaunching		= 117, 
+	VRInitError_Init_SettingsInitFailed			= 118, 
+	VRInitError_Init_ShuttingDown				= 119,
+	VRInitError_Init_TooManyObjects				= 120,
+	VRInitError_Init_NoServerForBackgroundApp	= 121,
+	VRInitError_Init_NotSupportedWithCompositor	= 122,
+	VRInitError_Init_NotAvailableToUtilityApps	= 123,
+	VRInitError_Init_Internal				 	= 124,
+	VRInitError_Init_HmdDriverIdIsNone		 	= 125,
+	VRInitError_Init_HmdNotFoundPresenceFailed 	= 126,
+	VRInitError_Init_VRMonitorNotFound			= 127,
+	VRInitError_Init_VRMonitorStartupFailed		= 128,
+	VRInitError_Init_LowPowerWatchdogNotSupported = 129, 
+	VRInitError_Init_InvalidApplicationType		= 130,
+	VRInitError_Init_NotAvailableToWatchdogApps = 131,
+	VRInitError_Init_WatchdogDisabledInSettings = 132,
+	VRInitError_Init_VRDashboardNotFound		= 133,
+	VRInitError_Init_VRDashboardStartupFailed	= 134,
+
+	VRInitError_Driver_Failed				= 200,
+	VRInitError_Driver_Unknown				= 201,
+	VRInitError_Driver_HmdUnknown			= 202,
+	VRInitError_Driver_NotLoaded			= 203,
+	VRInitError_Driver_RuntimeOutOfDate		= 204,
+	VRInitError_Driver_HmdInUse				= 205,
+	VRInitError_Driver_NotCalibrated		= 206,
+	VRInitError_Driver_CalibrationInvalid	= 207,
+	VRInitError_Driver_HmdDisplayNotFound	= 208,
+	VRInitError_Driver_TrackedDeviceInterfaceUnknown = 209,
+	// VRInitError_Driver_HmdDisplayNotFoundAfterFix	 = 210, // not needed: here for historic reasons
+	VRInitError_Driver_HmdDriverIdOutOfBounds = 211,
+	VRInitError_Driver_HmdDisplayMirrored  = 212,
+
+	VRInitError_IPC_ServerInitFailed		= 300,
+	VRInitError_IPC_ConnectFailed			= 301,
+	VRInitError_IPC_SharedStateInitFailed	= 302,
+	VRInitError_IPC_CompositorInitFailed	= 303,
+	VRInitError_IPC_MutexInitFailed			= 304,
+	VRInitError_IPC_Failed					= 305,
+	VRInitError_IPC_CompositorConnectFailed	= 306,
+	VRInitError_IPC_CompositorInvalidConnectResponse = 307,
+	VRInitError_IPC_ConnectFailedAfterMultipleAttempts = 308,
+
+	VRInitError_Compositor_Failed					= 400,
+	VRInitError_Compositor_D3D11HardwareRequired	= 401,
+	VRInitError_Compositor_FirmwareRequiresUpdate	= 402,
+	VRInitError_Compositor_OverlayInitFailed		= 403,
+	VRInitError_Compositor_ScreenshotsInitFailed	= 404,
+
+	VRInitError_VendorSpecific_UnableToConnectToOculusRuntime = 1000,
+
+	VRInitError_VendorSpecific_HmdFound_CantOpenDevice 				= 1101,
+	VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart	= 1102,
+	VRInitError_VendorSpecific_HmdFound_NoStoredConfig 				= 1103,
+	VRInitError_VendorSpecific_HmdFound_ConfigTooBig 				= 1104,
+	VRInitError_VendorSpecific_HmdFound_ConfigTooSmall 				= 1105,
+	VRInitError_VendorSpecific_HmdFound_UnableToInitZLib 			= 1106,
+	VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion 	= 1107,
+	VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart	= 1108,
+	VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart	= 1109,
+	VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext		= 1110,
+	VRInitError_VendorSpecific_HmdFound_UserDataAddressRange		= 1111,
+	VRInitError_VendorSpecific_HmdFound_UserDataError				= 1112,
+	VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck		= 1113,
+
+	VRInitError_Steam_SteamInstallationNotFound = 2000,
+};
+
+enum EVRScreenshotType
+{
+	VRScreenshotType_None = 0,
+	VRScreenshotType_Mono = 1, // left eye only
+	VRScreenshotType_Stereo = 2,
+	VRScreenshotType_Cubemap = 3,
+	VRScreenshotType_MonoPanorama = 4,
+	VRScreenshotType_StereoPanorama = 5
+};
+
+enum EVRScreenshotPropertyFilenames
+{
+	VRScreenshotPropertyFilenames_Preview = 0,
+	VRScreenshotPropertyFilenames_VR = 1,
+};
+
+enum EVRTrackedCameraError
+{
+	VRTrackedCameraError_None                       = 0,
+	VRTrackedCameraError_OperationFailed            = 100,
+	VRTrackedCameraError_InvalidHandle              = 101,	
+	VRTrackedCameraError_InvalidFrameHeaderVersion  = 102,
+	VRTrackedCameraError_OutOfHandles               = 103,
+	VRTrackedCameraError_IPCFailure                 = 104,
+	VRTrackedCameraError_NotSupportedForThisDevice  = 105,
+	VRTrackedCameraError_SharedMemoryFailure        = 106,
+	VRTrackedCameraError_FrameBufferingFailure      = 107,
+	VRTrackedCameraError_StreamSetupFailure         = 108,
+	VRTrackedCameraError_InvalidGLTextureId         = 109,
+	VRTrackedCameraError_InvalidSharedTextureHandle = 110,
+	VRTrackedCameraError_FailedToGetGLTextureId     = 111,
+	VRTrackedCameraError_SharedTextureFailure       = 112,
+	VRTrackedCameraError_NoFrameAvailable           = 113,
+	VRTrackedCameraError_InvalidArgument            = 114,
+	VRTrackedCameraError_InvalidFrameBufferSize     = 115,
+};
+
+enum EVRTrackedCameraFrameType
+{
+	VRTrackedCameraFrameType_Distorted = 0,			// This is the camera video frame size in pixels, still distorted.
+	VRTrackedCameraFrameType_Undistorted,			// In pixels, an undistorted inscribed rectangle region without invalid regions. This size is subject to changes shortly.
+	VRTrackedCameraFrameType_MaximumUndistorted,	// In pixels, maximum undistorted with invalid regions. Non zero alpha component identifies valid regions.
+	MAX_CAMERA_FRAME_TYPES
+};
+
+typedef uint64_t TrackedCameraHandle_t;
+#define INVALID_TRACKED_CAMERA_HANDLE	((vr::TrackedCameraHandle_t)0)
+
+struct CameraVideoStreamFrameHeader_t
+{
+	EVRTrackedCameraFrameType eFrameType;
+
+	uint32_t nWidth;
+	uint32_t nHeight;
+	uint32_t nBytesPerPixel;
+
+	uint32_t nFrameSequence;
+
+	TrackedDevicePose_t standingTrackedDevicePose;
+};
+
+// Screenshot types
+typedef uint32_t ScreenshotHandle_t;
+
+static const uint32_t k_unScreenshotHandleInvalid = 0;
+
+#pragma pack( pop )
+
+// figure out how to import from the VR API dll
+#if defined(_WIN32)
+
+#ifdef VR_API_EXPORT
+#define VR_INTERFACE extern "C" __declspec( dllexport )
+#else
+#define VR_INTERFACE extern "C" __declspec( dllimport )
+#endif
+
+#elif defined(__GNUC__) || defined(COMPILER_GCC) || defined(__APPLE__)
+
+#ifdef VR_API_EXPORT
+#define VR_INTERFACE extern "C" __attribute__((visibility("default")))
+#else
+#define VR_INTERFACE extern "C" 
+#endif
+
+#else
+#error "Unsupported Platform."
+#endif
+
+
+#if defined( _WIN32 )
+#define VR_CALLTYPE __cdecl
+#else
+#define VR_CALLTYPE 
+#endif
+
+} // namespace vr
+
+#endif // _INCLUDE_VRTYPES_H
+
+
+// vrannotation.h
+#ifdef API_GEN
+# define VR_CLANG_ATTR(ATTR) __attribute__((annotate( ATTR )))
+#else
+# define VR_CLANG_ATTR(ATTR)
+#endif
+
+#define VR_METHOD_DESC(DESC) VR_CLANG_ATTR( "desc:" #DESC ";" )
+#define VR_IGNOREATTR() VR_CLANG_ATTR( "ignore" )
+#define VR_OUT_STRUCT() VR_CLANG_ATTR( "out_struct: ;" )
+#define VR_OUT_STRING() VR_CLANG_ATTR( "out_string: ;" )
+#define VR_OUT_ARRAY_CALL(COUNTER,FUNCTION,PARAMS) VR_CLANG_ATTR( "out_array_call:" #COUNTER "," #FUNCTION "," #PARAMS ";" )
+#define VR_OUT_ARRAY_COUNT(COUNTER) VR_CLANG_ATTR( "out_array_count:" #COUNTER ";" )
+#define VR_ARRAY_COUNT(COUNTER) VR_CLANG_ATTR( "array_count:" #COUNTER ";" )
+#define VR_ARRAY_COUNT_D(COUNTER, DESC) VR_CLANG_ATTR( "array_count:" #COUNTER ";desc:" #DESC )
+#define VR_BUFFER_COUNT(COUNTER) VR_CLANG_ATTR( "buffer_count:" #COUNTER ";" )
+#define VR_OUT_BUFFER_COUNT(COUNTER) VR_CLANG_ATTR( "out_buffer_count:" #COUNTER ";" )
+#define VR_OUT_STRING_COUNT(COUNTER) VR_CLANG_ATTR( "out_string_count:" #COUNTER ";" )
+
+// vrtrackedcameratypes.h
+#ifndef _VRTRACKEDCAMERATYPES_H
+#define _VRTRACKEDCAMERATYPES_H 
+
+namespace vr
+{
+
+#if defined(__linux__) || defined(__APPLE__) 
+	// The 32-bit version of gcc has the alignment requirement for uint64 and double set to
+	// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned.
+	// The 64-bit version of gcc has the alignment requirement for these types set to
+	// 8 meaning that unless we use #pragma pack(4) our structures will get bigger.
+	// The 64-bit structure packing has to match the 32-bit structure packing for each platform.
+	#pragma pack( push, 4 )
+#else
+	#pragma pack( push, 8 )
+#endif
+
+enum ECameraVideoStreamFormat
+{
+	CVS_FORMAT_UNKNOWN = 0,
+	CVS_FORMAT_RAW10 = 1,		// 10 bits per pixel
+	CVS_FORMAT_NV12 = 2,		// 12 bits per pixel
+	CVS_FORMAT_RGB24 = 3,		// 24 bits per pixel
+	CVS_MAX_FORMATS
+};
+
+enum ECameraCompatibilityMode
+{
+	CAMERA_COMPAT_MODE_BULK_DEFAULT = 0,
+	CAMERA_COMPAT_MODE_BULK_64K_DMA,
+	CAMERA_COMPAT_MODE_BULK_16K_DMA,
+	CAMERA_COMPAT_MODE_BULK_8K_DMA,
+	CAMERA_COMPAT_MODE_ISO_52FPS,
+	CAMERA_COMPAT_MODE_ISO_50FPS,
+	CAMERA_COMPAT_MODE_ISO_48FPS,
+	CAMERA_COMPAT_MODE_ISO_46FPS,
+	CAMERA_COMPAT_MODE_ISO_44FPS,
+	CAMERA_COMPAT_MODE_ISO_42FPS,
+	CAMERA_COMPAT_MODE_ISO_40FPS,
+	CAMERA_COMPAT_MODE_ISO_35FPS,
+	CAMERA_COMPAT_MODE_ISO_30FPS,
+	MAX_CAMERA_COMPAT_MODES
+};
+
+#ifdef _MSC_VER
+#define VR_CAMERA_DECL_ALIGN( x ) __declspec( align( x ) )
+#else
+#define VR_CAMERA_DECL_ALIGN( x ) //
+#endif
+
+#define MAX_CAMERA_FRAME_SHARED_HANDLES	4
+
+VR_CAMERA_DECL_ALIGN( 8 ) struct CameraVideoStreamFrame_t
+{
+	ECameraVideoStreamFormat m_nStreamFormat;
+
+	uint32_t m_nWidth;
+	uint32_t m_nHeight;
+
+	uint32_t m_nImageDataSize;						// Based on stream format, width, height
+
+	uint32_t m_nFrameSequence;						// Starts from 0 when stream starts.
+
+	uint32_t m_nBufferIndex;						// Identifies which buffer the image data is hosted
+	uint32_t m_nBufferCount;						// Total number of configured buffers
+
+	uint32_t m_nExposureTime;
+
+	uint32_t m_nISPFrameTimeStamp;					// Driver provided time stamp per driver centric time base
+	uint32_t m_nISPReferenceTimeStamp;
+	uint32_t m_nSyncCounter;
+
+	uint32_t m_nCamSyncEvents;
+	uint32_t m_nISPSyncEvents;
+
+	double m_flReferenceCamSyncTime;
+
+	double m_flFrameElapsedTime;					// Starts from 0 when stream starts. In seconds.
+	double m_flFrameDeliveryRate;
+
+	double m_flFrameCaptureTime_DriverAbsolute;		// In USB time, via AuxEvent
+	double m_flFrameCaptureTime_ServerRelative;		// In System time within the server
+	uint64_t m_nFrameCaptureTicks_ServerAbsolute;	// In system ticks within the server
+	double m_flFrameCaptureTime_ClientRelative;		// At the client, relative to when the frame was exposed/captured.
+
+	double m_flSyncMarkerError;
+
+	TrackedDevicePose_t m_StandingTrackedDevicePose;	// Supplied by HMD layer when used as a tracked camera
+
+	uint64_t m_pImageData;
+};
+
+#pragma pack( pop )
+
+}
+
+#endif // _VRTRACKEDCAMERATYPES_H
+// ivrsettings.h
+namespace vr
+{
+	enum EVRSettingsError
+	{
+		VRSettingsError_None = 0,
+		VRSettingsError_IPCFailed = 1,
+		VRSettingsError_WriteFailed = 2,
+		VRSettingsError_ReadFailed = 3,
+		VRSettingsError_JsonParseFailed = 4,
+		VRSettingsError_UnsetSettingHasNoDefault = 5, // This will be returned if the setting does not appear in the appropriate default file and has not been set
+	};
+
+	// The maximum length of a settings key
+	static const uint32_t k_unMaxSettingsKeyLength = 128;
+
+	class IVRSettings
+	{
+	public:
+		virtual const char *GetSettingsErrorNameFromEnum( EVRSettingsError eError ) = 0;
+
+		// Returns true if file sync occurred (force or settings dirty)
+		virtual bool Sync( bool bForce = false, EVRSettingsError *peError = nullptr ) = 0;
+
+		virtual void SetBool( const char *pchSection, const char *pchSettingsKey, bool bValue, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void SetInt32( const char *pchSection, const char *pchSettingsKey, int32_t nValue, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void SetFloat( const char *pchSection, const char *pchSettingsKey, float flValue, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void SetString( const char *pchSection, const char *pchSettingsKey, const char *pchValue, EVRSettingsError *peError = nullptr ) = 0;
+
+		// Users of the system need to provide a proper default in default.vrsettings in the resources/settings/ directory
+		// of either the runtime or the driver_xxx directory. Otherwise the default will be false, 0, 0.0 or ""
+		virtual bool GetBool( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0;
+		virtual int32_t GetInt32( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0;
+		virtual float GetFloat( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void GetString( const char *pchSection, const char *pchSettingsKey, VR_OUT_STRING() char *pchValue, uint32_t unValueLen, EVRSettingsError *peError = nullptr ) = 0;
+
+		virtual void RemoveSection( const char *pchSection, EVRSettingsError *peError = nullptr ) = 0;
+		virtual void RemoveKeyInSection( const char *pchSection, const char *pchSettingsKey, EVRSettingsError *peError = nullptr ) = 0;
+	};
+
+	//-----------------------------------------------------------------------------
+	static const char * const IVRSettings_Version = "IVRSettings_002";
+
+	//-----------------------------------------------------------------------------
+	// steamvr keys
+	static const char * const k_pch_SteamVR_Section = "steamvr";
+	static const char * const k_pch_SteamVR_RequireHmd_String = "requireHmd";
+	static const char * const k_pch_SteamVR_ForcedDriverKey_String = "forcedDriver";
+	static const char * const k_pch_SteamVR_ForcedHmdKey_String = "forcedHmd";
+	static const char * const k_pch_SteamVR_DisplayDebug_Bool = "displayDebug";
+	static const char * const k_pch_SteamVR_DebugProcessPipe_String = "debugProcessPipe";
+	static const char * const k_pch_SteamVR_EnableDistortion_Bool = "enableDistortion";
+	static const char * const k_pch_SteamVR_DisplayDebugX_Int32 = "displayDebugX";
+	static const char * const k_pch_SteamVR_DisplayDebugY_Int32 = "displayDebugY";
+	static const char * const k_pch_SteamVR_SendSystemButtonToAllApps_Bool= "sendSystemButtonToAllApps";
+	static const char * const k_pch_SteamVR_LogLevel_Int32 = "loglevel";
+	static const char * const k_pch_SteamVR_IPD_Float = "ipd";
+	static const char * const k_pch_SteamVR_Background_String = "background";
+	static const char * const k_pch_SteamVR_BackgroundUseDomeProjection_Bool = "backgroundUseDomeProjection";
+	static const char * const k_pch_SteamVR_BackgroundCameraHeight_Float = "backgroundCameraHeight";
+	static const char * const k_pch_SteamVR_BackgroundDomeRadius_Float = "backgroundDomeRadius";
+	static const char * const k_pch_SteamVR_GridColor_String = "gridColor";
+	static const char * const k_pch_SteamVR_PlayAreaColor_String = "playAreaColor";
+	static const char * const k_pch_SteamVR_ShowStage_Bool = "showStage";
+	static const char * const k_pch_SteamVR_ActivateMultipleDrivers_Bool = "activateMultipleDrivers";
+	static const char * const k_pch_SteamVR_DirectMode_Bool = "directMode";
+	static const char * const k_pch_SteamVR_DirectModeEdidVid_Int32 = "directModeEdidVid";
+	static const char * const k_pch_SteamVR_DirectModeEdidPid_Int32 = "directModeEdidPid";
+	static const char * const k_pch_SteamVR_UsingSpeakers_Bool = "usingSpeakers";
+	static const char * const k_pch_SteamVR_SpeakersForwardYawOffsetDegrees_Float = "speakersForwardYawOffsetDegrees";
+	static const char * const k_pch_SteamVR_BaseStationPowerManagement_Bool = "basestationPowerManagement";
+	static const char * const k_pch_SteamVR_NeverKillProcesses_Bool = "neverKillProcesses";
+	static const char * const k_pch_SteamVR_RenderTargetMultiplier_Float = "renderTargetMultiplier";
+	static const char * const k_pch_SteamVR_AllowAsyncReprojection_Bool = "allowAsyncReprojection";
+	static const char * const k_pch_SteamVR_AllowReprojection_Bool = "allowInterleavedReprojection";
+	static const char * const k_pch_SteamVR_ForceReprojection_Bool = "forceReprojection";
+	static const char * const k_pch_SteamVR_ForceFadeOnBadTracking_Bool = "forceFadeOnBadTracking";
+	static const char * const k_pch_SteamVR_DefaultMirrorView_Int32 = "defaultMirrorView";
+	static const char * const k_pch_SteamVR_ShowMirrorView_Bool = "showMirrorView";
+	static const char * const k_pch_SteamVR_MirrorViewGeometry_String = "mirrorViewGeometry";
+	static const char * const k_pch_SteamVR_StartMonitorFromAppLaunch = "startMonitorFromAppLaunch";
+	static const char * const k_pch_SteamVR_StartCompositorFromAppLaunch_Bool = "startCompositorFromAppLaunch";
+	static const char * const k_pch_SteamVR_StartDashboardFromAppLaunch_Bool = "startDashboardFromAppLaunch";
+	static const char * const k_pch_SteamVR_StartOverlayAppsFromDashboard_Bool = "startOverlayAppsFromDashboard";
+	static const char * const k_pch_SteamVR_EnableHomeApp = "enableHomeApp";
+	static const char * const k_pch_SteamVR_SetInitialDefaultHomeApp = "setInitialDefaultHomeApp";
+	static const char * const k_pch_SteamVR_CycleBackgroundImageTimeSec_Int32 = "CycleBackgroundImageTimeSec";
+	static const char * const k_pch_SteamVR_RetailDemo_Bool = "retailDemo";
+	static const char * const k_pch_SteamVR_IpdOffset_Float = "ipdOffset";
+
+	//-----------------------------------------------------------------------------
+	// lighthouse keys
+	static const char * const k_pch_Lighthouse_Section = "driver_lighthouse";
+	static const char * const k_pch_Lighthouse_DisableIMU_Bool = "disableimu";
+	static const char * const k_pch_Lighthouse_UseDisambiguation_String = "usedisambiguation";
+	static const char * const k_pch_Lighthouse_DisambiguationDebug_Int32 = "disambiguationdebug";
+	static const char * const k_pch_Lighthouse_PrimaryBasestation_Int32 = "primarybasestation";
+	static const char * const k_pch_Lighthouse_DBHistory_Bool = "dbhistory";
+
+	//-----------------------------------------------------------------------------
+	// null keys
+	static const char * const k_pch_Null_Section = "driver_null";
+	static const char * const k_pch_Null_SerialNumber_String = "serialNumber";
+	static const char * const k_pch_Null_ModelNumber_String = "modelNumber";
+	static const char * const k_pch_Null_WindowX_Int32 = "windowX";
+	static const char * const k_pch_Null_WindowY_Int32 = "windowY";
+	static const char * const k_pch_Null_WindowWidth_Int32 = "windowWidth";
+	static const char * const k_pch_Null_WindowHeight_Int32 = "windowHeight";
+	static const char * const k_pch_Null_RenderWidth_Int32 = "renderWidth";
+	static const char * const k_pch_Null_RenderHeight_Int32 = "renderHeight";
+	static const char * const k_pch_Null_SecondsFromVsyncToPhotons_Float = "secondsFromVsyncToPhotons";
+	static const char * const k_pch_Null_DisplayFrequency_Float = "displayFrequency";
+
+	//-----------------------------------------------------------------------------
+	// user interface keys
+	static const char * const k_pch_UserInterface_Section = "userinterface";
+	static const char * const k_pch_UserInterface_StatusAlwaysOnTop_Bool = "StatusAlwaysOnTop";
+	static const char * const k_pch_UserInterface_MinimizeToTray_Bool = "MinimizeToTray";
+	static const char * const k_pch_UserInterface_Screenshots_Bool = "screenshots";
+	static const char * const k_pch_UserInterface_ScreenshotType_Int = "screenshotType";
+
+	//-----------------------------------------------------------------------------
+	// notification keys
+	static const char * const k_pch_Notifications_Section = "notifications";
+	static const char * const k_pch_Notifications_DoNotDisturb_Bool = "DoNotDisturb";
+
+	//-----------------------------------------------------------------------------
+	// keyboard keys
+	static const char * const k_pch_Keyboard_Section = "keyboard";
+	static const char * const k_pch_Keyboard_TutorialCompletions = "TutorialCompletions";
+	static const char * const k_pch_Keyboard_ScaleX = "ScaleX";
+	static const char * const k_pch_Keyboard_ScaleY = "ScaleY";
+	static const char * const k_pch_Keyboard_OffsetLeftX = "OffsetLeftX";
+	static const char * const k_pch_Keyboard_OffsetRightX = "OffsetRightX";
+	static const char * const k_pch_Keyboard_OffsetY = "OffsetY";
+	static const char * const k_pch_Keyboard_Smoothing = "Smoothing";
+
+	//-----------------------------------------------------------------------------
+	// perf keys
+	static const char * const k_pch_Perf_Section = "perfcheck";
+	static const char * const k_pch_Perf_HeuristicActive_Bool = "heuristicActive";
+	static const char * const k_pch_Perf_NotifyInHMD_Bool = "warnInHMD";
+	static const char * const k_pch_Perf_NotifyOnlyOnce_Bool = "warnOnlyOnce";
+	static const char * const k_pch_Perf_AllowTimingStore_Bool = "allowTimingStore";
+	static const char * const k_pch_Perf_SaveTimingsOnExit_Bool = "saveTimingsOnExit";
+	static const char * const k_pch_Perf_TestData_Float = "perfTestData";
+
+	//-----------------------------------------------------------------------------
+	// collision bounds keys
+	static const char * const k_pch_CollisionBounds_Section = "collisionBounds";
+	static const char * const k_pch_CollisionBounds_Style_Int32 = "CollisionBoundsStyle";
+	static const char * const k_pch_CollisionBounds_GroundPerimeterOn_Bool = "CollisionBoundsGroundPerimeterOn";
+	static const char * const k_pch_CollisionBounds_CenterMarkerOn_Bool = "CollisionBoundsCenterMarkerOn";
+	static const char * const k_pch_CollisionBounds_PlaySpaceOn_Bool = "CollisionBoundsPlaySpaceOn";
+	static const char * const k_pch_CollisionBounds_FadeDistance_Float = "CollisionBoundsFadeDistance";
+	static const char * const k_pch_CollisionBounds_ColorGammaR_Int32 = "CollisionBoundsColorGammaR";
+	static const char * const k_pch_CollisionBounds_ColorGammaG_Int32 = "CollisionBoundsColorGammaG";
+	static const char * const k_pch_CollisionBounds_ColorGammaB_Int32 = "CollisionBoundsColorGammaB";
+	static const char * const k_pch_CollisionBounds_ColorGammaA_Int32 = "CollisionBoundsColorGammaA";
+
+	//-----------------------------------------------------------------------------
+	// camera keys
+	static const char * const k_pch_Camera_Section = "camera";
+	static const char * const k_pch_Camera_EnableCamera_Bool = "enableCamera";
+	static const char * const k_pch_Camera_EnableCameraInDashboard_Bool = "enableCameraInDashboard";
+	static const char * const k_pch_Camera_EnableCameraForCollisionBounds_Bool = "enableCameraForCollisionBounds";
+	static const char * const k_pch_Camera_EnableCameraForRoomView_Bool = "enableCameraForRoomView";
+	static const char * const k_pch_Camera_BoundsColorGammaR_Int32 = "cameraBoundsColorGammaR";
+	static const char * const k_pch_Camera_BoundsColorGammaG_Int32 = "cameraBoundsColorGammaG";
+	static const char * const k_pch_Camera_BoundsColorGammaB_Int32 = "cameraBoundsColorGammaB";
+	static const char * const k_pch_Camera_BoundsColorGammaA_Int32 = "cameraBoundsColorGammaA";
+	static const char * const k_pch_Camera_BoundsStrength_Int32 = "cameraBoundsStrength";
+
+	//-----------------------------------------------------------------------------
+	// audio keys
+	static const char * const k_pch_audio_Section = "audio";
+	static const char * const k_pch_audio_OnPlaybackDevice_String = "onPlaybackDevice";
+	static const char * const k_pch_audio_OnRecordDevice_String = "onRecordDevice";
+	static const char * const k_pch_audio_OnPlaybackMirrorDevice_String = "onPlaybackMirrorDevice";
+	static const char * const k_pch_audio_OffPlaybackDevice_String = "offPlaybackDevice";
+	static const char * const k_pch_audio_OffRecordDevice_String = "offRecordDevice";
+	static const char * const k_pch_audio_VIVEHDMIGain = "viveHDMIGain";
+
+	//-----------------------------------------------------------------------------
+	// power management keys
+	static const char * const k_pch_Power_Section = "power";
+	static const char * const k_pch_Power_PowerOffOnExit_Bool = "powerOffOnExit";
+	static const char * const k_pch_Power_TurnOffScreensTimeout_Float = "turnOffScreensTimeout";
+	static const char * const k_pch_Power_TurnOffControllersTimeout_Float = "turnOffControllersTimeout";
+	static const char * const k_pch_Power_ReturnToWatchdogTimeout_Float = "returnToWatchdogTimeout";
+	static const char * const k_pch_Power_AutoLaunchSteamVROnButtonPress = "autoLaunchSteamVROnButtonPress";
+
+	//-----------------------------------------------------------------------------
+	// dashboard keys
+	static const char * const k_pch_Dashboard_Section = "dashboard";
+	static const char * const k_pch_Dashboard_EnableDashboard_Bool = "enableDashboard";
+	static const char * const k_pch_Dashboard_ArcadeMode_Bool = "arcadeMode";
+
+	//-----------------------------------------------------------------------------
+	// model skin keys
+	static const char * const k_pch_modelskin_Section = "modelskins";
+
+	//-----------------------------------------------------------------------------
+	// driver keys - These could be checked in any driver_<name> section
+	static const char * const k_pch_Driver_Enable_Bool = "enable";
+
+} // namespace vr
+
+// iservertrackeddevicedriver.h
+namespace vr
+{
+
+
+struct DriverPoseQuaternion_t
+{
+	double w, x, y, z;
+};
+
+struct DriverPose_t
+{
+	/* Time offset of this pose, in seconds from the actual time of the pose,
+	 * relative to the time of the PoseUpdated() call made by the driver.
+	 */
+	double poseTimeOffset;
+
+	/* Generally, the pose maintained by a driver
+	 * is in an inertial coordinate system different
+	 * from the world system of x+ right, y+ up, z+ back.
+	 * Also, the driver is not usually tracking the "head" position,
+	 * but instead an internal IMU or another reference point in the HMD.
+	 * The following two transforms transform positions and orientations
+	 * to app world space from driver world space,
+	 * and to HMD head space from driver local body space. 
+	 *
+	 * We maintain the driver pose state in its internal coordinate system,
+	 * so we can do the pose prediction math without having to
+	 * use angular acceleration.  A driver's angular acceleration is generally not measured,
+	 * and is instead calculated from successive samples of angular velocity.
+	 * This leads to a noisy angular acceleration values, which are also
+	 * lagged due to the filtering required to reduce noise to an acceptable level.
+	 */
+	vr::HmdQuaternion_t qWorldFromDriverRotation;
+	double vecWorldFromDriverTranslation[ 3 ];
+
+	vr::HmdQuaternion_t qDriverFromHeadRotation;
+	double vecDriverFromHeadTranslation[ 3 ];
+
+	/* State of driver pose, in meters and radians. */
+	/* Position of the driver tracking reference in driver world space
+	* +[0] (x) is right
+	* +[1] (y) is up
+	* -[2] (z) is forward
+	*/
+	double vecPosition[ 3 ];
+
+	/* Velocity of the pose in meters/second */
+	double vecVelocity[ 3 ];
+
+	/* Acceleration of the pose in meters/second */
+	double vecAcceleration[ 3 ];
+
+	/* Orientation of the tracker, represented as a quaternion */
+	vr::HmdQuaternion_t qRotation;
+
+	/* Angular velocity of the pose in axis-angle 
+	* representation. The direction is the angle of
+	* rotation and the magnitude is the angle around
+	* that axis in radians/second. */
+	double vecAngularVelocity[ 3 ];
+
+	/* Angular acceleration of the pose in axis-angle 
+	* representation. The direction is the angle of
+	* rotation and the magnitude is the angle around
+	* that axis in radians/second^2. */
+	double vecAngularAcceleration[ 3 ];
+
+	ETrackingResult result;
+
+	bool poseIsValid;
+	bool willDriftInYaw;
+	bool shouldApplyHeadModel;
+	bool deviceIsConnected;
+};
+
+
+// ----------------------------------------------------------------------------------------------
+// Purpose: Represents a single tracked device in a driver
+// ----------------------------------------------------------------------------------------------
+class ITrackedDeviceServerDriver
+{
+public:
+
+	// ------------------------------------
+	// Management Methods
+	// ------------------------------------
+	/** This is called before an HMD is returned to the application. It will always be
+	* called before any display or tracking methods. Memory and processor use by the
+	* ITrackedDeviceServerDriver object should be kept to a minimum until it is activated.
+	* The pose listener is guaranteed to be valid until Deactivate is called, but
+	* should not be used after that point. */
+	virtual EVRInitError Activate( uint32_t unObjectId ) = 0;
+
+	/** This is called when The VR system is switching from this Hmd being the active display
+	* to another Hmd being the active display. The driver should clean whatever memory
+	* and thread use it can when it is deactivated */
+	virtual void Deactivate() = 0;
+
+	/** Handles a request from the system to put this device into standby mode. What that means is defined per-device. */
+	virtual void EnterStandby() = 0;
+
+	/** Requests a component interface of the driver for device-specific functionality. The driver should return NULL
+	* if the requested interface or version is not supported. */
+	virtual void *GetComponent( const char *pchComponentNameAndVersion ) = 0;
+
+	/** A VR Client has made this debug request of the driver. The set of valid requests is entirely
+	* up to the driver and the client to figure out, as is the format of the response. Responses that
+	* exceed the length of the supplied buffer should be truncated and null terminated */
+	virtual void DebugRequest( const char *pchRequest, char *pchResponseBuffer, uint32_t unResponseBufferSize ) = 0;
+
+	// ------------------------------------
+	// Tracking Methods
+	// ------------------------------------
+	virtual DriverPose_t GetPose() = 0;
+};
+
+
+
+static const char *ITrackedDeviceServerDriver_Version = "ITrackedDeviceServerDriver_005";
+
+}
+// ivrdisplaycomponent.h
+namespace vr
+{
+
+
+	// ----------------------------------------------------------------------------------------------
+	// Purpose: The display component on a single tracked device
+	// ----------------------------------------------------------------------------------------------
+	class IVRDisplayComponent
+	{
+	public:
+
+		// ------------------------------------
+		// Display Methods
+		// ------------------------------------
+
+		/** Size and position that the window needs to be on the VR display. */
+		virtual void GetWindowBounds( int32_t *pnX, int32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0;
+
+		/** Returns true if the display is extending the desktop. */
+		virtual bool IsDisplayOnDesktop( ) = 0;
+
+		/** Returns true if the display is real and not a fictional display. */
+		virtual bool IsDisplayRealDisplay( ) = 0;
+
+		/** Suggested size for the intermediate render target that the distortion pulls from. */
+		virtual void GetRecommendedRenderTargetSize( uint32_t *pnWidth, uint32_t *pnHeight ) = 0;
+
+		/** Gets the viewport in the frame buffer to draw the output of the distortion into */
+		virtual void GetEyeOutputViewport( EVREye eEye, uint32_t *pnX, uint32_t *pnY, uint32_t *pnWidth, uint32_t *pnHeight ) = 0;
+
+		/** The components necessary to build your own projection matrix in case your
+		* application is doing something fancy like infinite Z */
+		virtual void GetProjectionRaw( EVREye eEye, float *pfLeft, float *pfRight, float *pfTop, float *pfBottom ) = 0;
+
+		/** Returns the result of the distortion function for the specified eye and input UVs. UVs go from 0,0 in
+		* the upper left of that eye's viewport and 1,1 in the lower right of that eye's viewport. */
+		virtual DistortionCoordinates_t ComputeDistortion( EVREye eEye, float fU, float fV ) = 0;
+
+	};
+
+	static const char *IVRDisplayComponent_Version = "IVRDisplayComponent_002";
+
+}
+
+// ivrdriverdirectmodecomponent.h
+namespace vr
+{
+
+
+	// ----------------------------------------------------------------------------------------------
+	// Purpose: This component is used for drivers that implement direct mode entirely on their own
+	//			without allowing the VR Compositor to own the window/device. Chances are you don't
+	//			need to implement this component in your driver.
+	// ----------------------------------------------------------------------------------------------
+	class IVRDriverDirectModeComponent
+	{
+	public:
+
+		// -----------------------------------
+		// Direct mode methods
+		// -----------------------------------
+
+		/** Specific to Oculus compositor support, textures supplied must be created using this method. */
+		virtual void CreateSwapTextureSet( uint32_t unPid, uint32_t unFormat, uint32_t unWidth, uint32_t unHeight, vr::SharedTextureHandle_t( *pSharedTextureHandles )[ 3 ] ) {}
+
+		/** Used to textures created using CreateSwapTextureSet.  Only one of the set's handles needs to be used to destroy the entire set. */
+		virtual void DestroySwapTextureSet( vr::SharedTextureHandle_t sharedTextureHandle ) {}
+
+		/** Used to purge all texture sets for a given process. */
+		virtual void DestroyAllSwapTextureSets( uint32_t unPid ) {}
+
+		/** After Present returns, calls this to get the next index to use for rendering. */
+		virtual void GetNextSwapTextureSetIndex( vr::SharedTextureHandle_t sharedTextureHandles[ 2 ], uint32_t( *pIndices )[ 2 ] ) {}
+
+		/** Call once per layer to draw for this frame.  One shared texture handle per eye.  Textures must be created
+		* using CreateSwapTextureSet and should be alternated per frame.  Call Present once all layers have been submitted. */
+		virtual void SubmitLayer( vr::SharedTextureHandle_t sharedTextureHandles[ 2 ], const vr::VRTextureBounds_t( &bounds )[ 2 ], const vr::HmdMatrix34_t *pPose ) {}
+
+		/** Submits queued layers for display. */
+		virtual void Present( vr::SharedTextureHandle_t syncTexture ) {}
+
+	};
+
+	static const char *IVRDriverDirectModeComponent_Version = "IVRDriverDirectModeComponent_002";
+
+}
+
+// ivrcontrollercomponent.h
+namespace vr
+{
+
+
+	// ----------------------------------------------------------------------------------------------
+	// Purpose: Controller access on a single tracked device.
+	// ----------------------------------------------------------------------------------------------
+	class IVRControllerComponent
+	{
+	public:
+
+		// ------------------------------------
+		// Controller Methods
+		// ------------------------------------
+
+		/** Gets the current state of a controller. */
+		virtual VRControllerState_t GetControllerState( ) = 0;
+
+		/** Returns a uint64 property. If the property is not available this function will return 0. */
+		virtual bool TriggerHapticPulse( uint32_t unAxisId, uint16_t usPulseDurationMicroseconds ) = 0;
+
+	};
+
+
+
+	static const char *IVRControllerComponent_Version = "IVRControllerComponent_001";
+
+}
+// ivrcameracomponent.h
+namespace vr
+{
+	//-----------------------------------------------------------------------------
+	//-----------------------------------------------------------------------------
+	class ICameraVideoSinkCallback
+	{
+	public:
+		virtual void OnCameraVideoSinkCallback() = 0;
+	};
+
+	// ----------------------------------------------------------------------------------------------
+	// Purpose: The camera on a single tracked device
+	// ----------------------------------------------------------------------------------------------
+	class IVRCameraComponent
+	{
+	public:
+		// ------------------------------------
+		// Camera Methods
+		// ------------------------------------
+		virtual bool GetCameraFrameDimensions( vr::ECameraVideoStreamFormat nVideoStreamFormat, uint32_t *pWidth, uint32_t *pHeight ) = 0;
+		virtual bool GetCameraFrameBufferingRequirements( int *pDefaultFrameQueueSize, uint32_t *pFrameBufferDataSize ) = 0;
+		virtual bool SetCameraFrameBuffering( int nFrameBufferCount, void **ppFrameBuffers, uint32_t nFrameBufferDataSize ) = 0;
+		virtual bool SetCameraVideoStreamFormat( vr::ECameraVideoStreamFormat nVideoStreamFormat ) = 0;
+		virtual vr::ECameraVideoStreamFormat GetCameraVideoStreamFormat() = 0;
+		virtual bool StartVideoStream() = 0;
+		virtual void StopVideoStream() = 0;
+		virtual bool IsVideoStreamActive( bool *pbPaused, float *pflElapsedTime ) = 0;
+		virtual const vr::CameraVideoStreamFrame_t *GetVideoStreamFrame() = 0;
+		virtual void ReleaseVideoStreamFrame( const vr::CameraVideoStreamFrame_t *pFrameImage ) = 0;
+		virtual bool SetAutoExposure( bool bEnable ) = 0;
+		virtual bool PauseVideoStream() = 0;
+		virtual bool ResumeVideoStream() = 0;
+		virtual bool GetCameraDistortion( float flInputU, float flInputV, float *pflOutputU, float *pflOutputV ) = 0;
+		virtual bool GetCameraProjection( vr::EVRTrackedCameraFrameType eFrameType, float flZNear, float flZFar, vr::HmdMatrix44_t *pProjection ) = 0;
+		virtual bool SetFrameRate( int nISPFrameRate, int nSensorFrameRate ) = 0;
+		virtual bool SetCameraVideoSinkCallback( vr::ICameraVideoSinkCallback *pCameraVideoSinkCallback ) = 0;
+		virtual bool GetCameraCompatibilityMode( vr::ECameraCompatibilityMode *pCameraCompatibilityMode ) = 0;
+		virtual bool SetCameraCompatibilityMode( vr::ECameraCompatibilityMode nCameraCompatibilityMode ) = 0;
+		virtual bool GetCameraFrameBounds( vr::EVRTrackedCameraFrameType eFrameType, uint32_t *pLeft, uint32_t *pTop, uint32_t *pWidth, uint32_t *pHeight ) = 0;
+		virtual bool GetCameraIntrinsics( vr::EVRTrackedCameraFrameType eFrameType, HmdVector2_t *pFocalLength, HmdVector2_t *pCenter ) = 0;
+	};
+
+	static const char *IVRCameraComponent_Version = "IVRCameraComponent_002";
+}
+// itrackeddevicedriverprovider.h
+namespace vr
+{
+
+class ITrackedDeviceServerDriver;
+struct TrackedDeviceDriverInfo_t;
+struct DriverPose_t;
+typedef PropertyContainerHandle_t DriverHandle_t;
+
+/** This interface is provided by vrserver to allow the driver to notify 
+* the system when something changes about a device. These changes must
+* not change the serial number or class of the device because those values
+* are permanently associated with the device's index. */
+class IVRDriverContext
+{
+public:
+	/** Returns the requested interface. If the interface was not available it will return NULL and fill
+	* out the error. */
+	virtual void *GetGenericInterface( const char *pchInterfaceVersion, EVRInitError *peError = nullptr ) = 0;
+
+	/** Returns the property container handle for this driver */
+	virtual DriverHandle_t GetDriverHandle() = 0;
+};
+
+
+/** This interface must be implemented in each driver. It will be loaded in vrserver.exe */
+class IServerTrackedDeviceProvider
+{
+public:
+	/** initializes the driver. This will be called before any other methods are called.
+	* If Init returns anything other than VRInitError_None the driver DLL will be unloaded.
+	*
+	* pDriverHost will never be NULL, and will always be a pointer to a IServerDriverHost interface
+	*
+	* pchUserDriverConfigDir - The absolute path of the directory where the driver should store user
+	*	config files.
+	* pchDriverInstallDir - The absolute path of the root directory for the driver.
+	*/
+	virtual EVRInitError Init( IVRDriverContext *pDriverContext ) = 0;
+
+	/** cleans up the driver right before it is unloaded */
+	virtual void Cleanup() = 0;
+
+	/** Returns the version of the ITrackedDeviceServerDriver interface used by this driver */
+	virtual const char * const *GetInterfaceVersions() = 0;
+
+	/** Allows the driver do to some work in the main loop of the server. */
+	virtual void RunFrame() = 0;
+
+
+	// ------------  Power State Functions ----------------------- //
+
+	/** Returns true if the driver wants to block Standby mode. */
+	virtual bool ShouldBlockStandbyMode() = 0;
+
+	/** Called when the system is entering Standby mode. The driver should switch itself into whatever sort of low-power
+	* state it has. */
+	virtual void EnterStandby() = 0;
+
+	/** Called when the system is leaving Standby mode. The driver should switch itself back to
+	full operation. */
+	virtual void LeaveStandby() = 0;
+
+};
+
+
+static const char *IServerTrackedDeviceProvider_Version = "IServerTrackedDeviceProvider_004";
+
+
+
+
+/** This interface must be implemented in each driver. It will be loaded in vrclient.dll */
+class IVRWatchdogProvider
+{
+public:
+	/** initializes the driver in watchdog mode. */
+	virtual EVRInitError Init( IVRDriverContext *pDriverContext ) = 0;
+
+	/** cleans up the driver right before it is unloaded */
+	virtual void Cleanup() = 0;
+};
+
+static const char *IVRWatchdogProvider_Version = "IVRWatchdogProvider_001";
+
+}
+// ivrproperties.h
+#include <string>
+
+namespace vr
+{
+
+	enum EPropertyWriteType
+	{
+		PropertyWrite_Set = 0,
+		PropertyWrite_Erase = 1,
+		PropertyWrite_SetError = 2
+	};
+
+	struct PropertyWrite_t
+	{
+		ETrackedDeviceProperty prop;
+		EPropertyWriteType writeType;
+		ETrackedPropertyError eSetError;
+		void *pvBuffer;
+		uint32_t unBufferSize;
+		PropertyTypeTag_t unTag;
+		ETrackedPropertyError eError;
+	};
+
+	struct PropertyRead_t
+	{
+		ETrackedDeviceProperty prop;
+		void *pvBuffer;
+		uint32_t unBufferSize;
+		PropertyTypeTag_t unTag;
+		uint32_t unRequiredBufferSize;
+		ETrackedPropertyError eError;
+	};
+
+
+class IVRProperties
+{
+public:
+
+	/** Reads a set of properties atomically. See the PropertyReadBatch_t struct for more information. */
+	virtual ETrackedPropertyError ReadPropertyBatch( PropertyContainerHandle_t ulContainerHandle, PropertyRead_t *pBatch, uint32_t unBatchEntryCount ) = 0;
+
+	/** Writes a set of properties atomically. See the PropertyWriteBatch_t struct for more information. */
+	virtual ETrackedPropertyError WritePropertyBatch( PropertyContainerHandle_t ulContainerHandle, PropertyWrite_t *pBatch, uint32_t unBatchEntryCount ) = 0;
+
+	/** returns a string that corresponds with the specified property error. The string will be the name
+	* of the error enum value for all valid error codes */
+	virtual const char *GetPropErrorNameFromEnum( ETrackedPropertyError error ) = 0;
+
+	/** Returns a container handle given a tracked device index */
+	virtual PropertyContainerHandle_t TrackedDeviceToPropertyContainer( TrackedDeviceIndex_t nDevice ) = 0;
+
+};
+
+static const char * const IVRProperties_Version = "IVRProperties_001";
+
+class CVRPropertyHelpers
+{
+public:
+	CVRPropertyHelpers( IVRProperties * pProperties ) : m_pProperties( pProperties ) {}
+
+	/** Returns a scaler property. If the device index is not valid or the property value type does not match,
+	* this function will return false. */
+	bool GetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L );
+	float GetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L );
+	int32_t GetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L );
+	uint64_t GetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError = 0L );
+
+	/** Returns a single typed property. If the device index is not valid or the property is not a string type this function will
+	* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing
+	* null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */
+	uint32_t GetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() void *pvBuffer, uint32_t unBufferSize, PropertyTypeTag_t *punTag, ETrackedPropertyError *pError = 0L );
+
+
+	/** Returns a string property. If the device index is not valid or the property is not a string type this function will
+	* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing
+	* null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */
+	uint32_t GetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError = 0L );
+
+	/** Returns a string property as a std::string. If the device index is not valid or the property is not a string type this function will
+	* return an empty string. */
+	std::string GetStringProperty( vr::PropertyContainerHandle_t ulContainer, vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *peError = nullptr );
+
+	/** Sets a scaler property. The new value will be returned on any subsequent call to get this property in any process. */
+	ETrackedPropertyError SetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, bool bNewValue );
+	ETrackedPropertyError SetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, float fNewValue );
+	ETrackedPropertyError SetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, int32_t nNewValue );
+	ETrackedPropertyError SetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, uint64_t ulNewValue );
+
+	/** Sets a string property. The new value will be returned on any subsequent call to get this property in any process. */
+	ETrackedPropertyError SetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, const char *pchNewValue );
+
+	/** Sets a single typed property. The new value will be returned on any subsequent call to get this property in any process. */
+	ETrackedPropertyError SetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, void *pvNewValue, uint32_t unNewValueSize, PropertyTypeTag_t unTag );
+
+	/** Sets the error return value for a property. This value will be returned on all subsequent requests to get the property */
+	ETrackedPropertyError SetPropertyError( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError eError );
+
+	/** Clears any value or error set for the property. */
+	ETrackedPropertyError EraseProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop );
+
+	/* Turns a device index into a property container handle. */
+	PropertyContainerHandle_t TrackedDeviceToPropertyContainer( TrackedDeviceIndex_t nDevice ) { return m_pProperties->TrackedDeviceToPropertyContainer( nDevice );  }
+
+private:
+	template<typename T>
+	T GetPropertyHelper( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError, T bDefault, PropertyTypeTag_t unTypeTag );
+
+	IVRProperties *m_pProperties;
+};
+
+
+inline uint32_t CVRPropertyHelpers::GetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() void *pvBuffer, uint32_t unBufferSize, PropertyTypeTag_t *punTag, ETrackedPropertyError *pError )
+{
+	PropertyRead_t batch;
+	batch.prop = prop;
+	batch.pvBuffer = pvBuffer;
+	batch.unBufferSize = unBufferSize;
+
+	m_pProperties->ReadPropertyBatch( ulContainerHandle, &batch, 1 );
+
+	if ( pError )
+	{
+		*pError = batch.eError;
+	}
+
+	if ( punTag )
+	{
+		*punTag = batch.unTag;
+	}
+
+	return batch.unRequiredBufferSize;
+}
+
+
+/** Sets a single typed property. The new value will be returned on any subsequent call to get this property in any process. */
+inline ETrackedPropertyError CVRPropertyHelpers::SetProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, void *pvNewValue, uint32_t unNewValueSize, PropertyTypeTag_t unTag )
+{
+	PropertyWrite_t batch;
+	batch.writeType = PropertyWrite_Set;
+	batch.prop = prop;
+	batch.pvBuffer = pvNewValue;
+	batch.unBufferSize = unNewValueSize;
+	batch.unTag = unTag;
+
+	m_pProperties->WritePropertyBatch( ulContainerHandle, &batch, 1 );
+
+	return batch.eError;
+}
+
+
+/** Returns a string property. If the device index is not valid or the property is not a string type this function will
+* return 0. Otherwise it returns the length of the number of bytes necessary to hold this string including the trailing
+* null. Strings will always fit in buffers of k_unMaxPropertyStringSize characters. */
+inline uint32_t CVRPropertyHelpers::GetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, VR_OUT_STRING() char *pchValue, uint32_t unBufferSize, ETrackedPropertyError *pError )
+{
+	PropertyTypeTag_t unTag;
+	ETrackedPropertyError error;
+	uint32_t unRequiredSize = GetProperty( ulContainerHandle, prop, pchValue, unBufferSize, &unTag, &error );
+	if ( unTag != k_unStringPropertyTag && error == TrackedProp_Success )
+	{
+		error = TrackedProp_WrongDataType;
+	}
+
+	if ( pError )
+	{
+		*pError = error;
+	}
+
+	if ( error != TrackedProp_Success )
+	{
+		if ( pchValue && unBufferSize )
+		{
+			*pchValue = '\0';
+		}
+	}
+
+	return unRequiredSize;
+}
+
+
+/** Returns a string property as a std::string. If the device index is not valid or the property is not a string type this function will
+* return an empty string. */
+inline std::string CVRPropertyHelpers::GetStringProperty( vr::PropertyContainerHandle_t ulContainer, vr::ETrackedDeviceProperty prop, vr::ETrackedPropertyError *peError )
+{
+	char buf[1024];
+	vr::ETrackedPropertyError err;
+	uint32_t unRequiredBufferLen = GetStringProperty( ulContainer, prop, buf, sizeof(buf), &err );
+
+	std::string sResult;
+
+	if ( err == TrackedProp_Success )
+	{
+		sResult = buf;
+	}
+	else if ( err == TrackedProp_BufferTooSmall )
+	{
+		char *pchBuffer = new char[unRequiredBufferLen];
+		unRequiredBufferLen = GetStringProperty( ulContainer, prop, pchBuffer, unRequiredBufferLen, &err );
+		sResult = pchBuffer;
+		delete[] pchBuffer;
+	}
+
+	if ( peError )
+	{
+		*peError = err;
+	}
+
+	return sResult;
+}
+
+
+/** Sets a string property. The new value will be returned on any subsequent call to get this property in any process. */
+inline ETrackedPropertyError CVRPropertyHelpers::SetStringProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, const char *pchNewValue )
+{
+	if ( !pchNewValue )
+		return TrackedProp_InvalidOperation;
+
+	// this is strlen without the dependency on string.h
+	const char *pchCurr = pchNewValue;
+	while ( *pchCurr )
+	{
+		pchCurr++;
+	}
+
+	return SetProperty( ulContainerHandle, prop, (void *)pchNewValue, (uint32_t)(pchCurr - pchNewValue) + 1, k_unStringPropertyTag );
+}
+
+
+template<typename T>
+inline T CVRPropertyHelpers::GetPropertyHelper( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError, T bDefault, PropertyTypeTag_t unTypeTag )
+{
+	T bValue;
+	ETrackedPropertyError eError;
+	PropertyTypeTag_t unReadTag;
+	GetProperty( ulContainerHandle, prop, &bValue, sizeof( bValue ), &unReadTag, &eError );
+	if ( unReadTag != unTypeTag && eError == TrackedProp_Success )
+	{
+		eError = TrackedProp_WrongDataType;
+	};
+
+	if ( pError )
+		*pError = eError;
+	if ( eError != TrackedProp_Success )
+	{
+		return bDefault;
+	}
+	else
+	{
+		return bValue;
+	}
+}
+
+
+inline bool CVRPropertyHelpers::GetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError )
+{
+	return GetPropertyHelper<bool>( ulContainerHandle, prop, pError, false, k_unBoolPropertyTag );
+}
+
+
+inline float CVRPropertyHelpers::GetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError )
+{
+	return GetPropertyHelper<float>( ulContainerHandle, prop, pError, 0.f, k_unFloatPropertyTag );
+}
+
+inline int32_t CVRPropertyHelpers::GetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError )
+{
+	return GetPropertyHelper<int32_t>( ulContainerHandle, prop, pError, 0, k_unInt32PropertyTag );
+}
+
+inline uint64_t CVRPropertyHelpers::GetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError *pError )
+{
+	return GetPropertyHelper<uint64_t>( ulContainerHandle, prop, pError, 0, k_unUint64PropertyTag );
+}
+
+inline ETrackedPropertyError CVRPropertyHelpers::SetBoolProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, bool bNewValue )
+{
+	return SetProperty( ulContainerHandle, prop, &bNewValue, sizeof( bNewValue ), k_unBoolPropertyTag );
+}
+
+inline ETrackedPropertyError CVRPropertyHelpers::SetFloatProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, float fNewValue )
+{
+	return SetProperty( ulContainerHandle, prop, &fNewValue, sizeof( fNewValue ), k_unFloatPropertyTag );
+}
+
+inline ETrackedPropertyError CVRPropertyHelpers::SetInt32Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, int32_t nNewValue )
+{
+	return SetProperty( ulContainerHandle, prop, &nNewValue, sizeof( nNewValue ), k_unInt32PropertyTag );
+}
+
+inline ETrackedPropertyError CVRPropertyHelpers::SetUint64Property( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, uint64_t ulNewValue )
+{
+	return SetProperty( ulContainerHandle, prop, &ulNewValue, sizeof( ulNewValue ), k_unUint64PropertyTag );
+}
+
+/** Sets the error return value for a property. This value will be returned on all subsequent requests to get the property */
+inline ETrackedPropertyError CVRPropertyHelpers::SetPropertyError( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop, ETrackedPropertyError eError )
+{
+	PropertyWrite_t batch;
+	batch.writeType = PropertyWrite_SetError;
+	batch.prop = prop;
+	batch.eSetError = eError;
+
+	m_pProperties->WritePropertyBatch( ulContainerHandle, &batch, 1 );
+
+	return batch.eError;
+}
+
+/** Clears any value or error set for the property. */
+inline ETrackedPropertyError CVRPropertyHelpers::EraseProperty( PropertyContainerHandle_t ulContainerHandle, ETrackedDeviceProperty prop )
+{
+	PropertyWrite_t batch;
+	batch.writeType = PropertyWrite_Erase;
+	batch.prop = prop;
+
+	m_pProperties->WritePropertyBatch( ulContainerHandle, &batch, 1 );
+
+	return batch.eError;
+
+}
+
+}
+
+
+// ivrdriverlog.h
+namespace vr
+{
+
+class IVRDriverLog
+{
+public:
+	/** Writes a log message to the log file prefixed with the driver name */
+	virtual void Log( const char *pchLogMessage ) = 0;
+};
+
+
+static const char *IVRDriverLog_Version = "IVRDriverLog_001";
+
+}
+// ivrserverdriverhost.h
+namespace vr
+{
+
+class ITrackedDeviceServerDriver;
+struct TrackedDeviceDriverInfo_t;
+struct DriverPose_t;
+
+/** This interface is provided by vrserver to allow the driver to notify 
+* the system when something changes about a device. These changes must
+* not change the serial number or class of the device because those values
+* are permanently associated with the device's index. */
+class IVRServerDriverHost
+{
+public:
+	/** Notifies the server that a tracked device has been added. If this function returns true
+	* the server will call Activate on the device. If it returns false some kind of error
+	* has occurred and the device will not be activated. */
+	virtual bool TrackedDeviceAdded( const char *pchDeviceSerialNumber, ETrackedDeviceClass eDeviceClass, ITrackedDeviceServerDriver *pDriver ) = 0;
+
+	/** Notifies the server that a tracked device's pose has been updated */
+	virtual void TrackedDevicePoseUpdated( uint32_t unWhichDevice, const DriverPose_t & newPose, uint32_t unPoseStructSize ) = 0;
+
+	/** Notifies the server that vsync has occurred on the the display attached to the device. This is
+	* only permitted on devices of the HMD class. */
+	virtual void VsyncEvent( double vsyncTimeOffsetSeconds ) = 0;
+
+	/** notifies the server that the button was pressed */
+	virtual void TrackedDeviceButtonPressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0;
+
+	/** notifies the server that the button was unpressed */
+	virtual void TrackedDeviceButtonUnpressed( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0;
+
+	/** notifies the server that the button was pressed */
+	virtual void TrackedDeviceButtonTouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0;
+
+	/** notifies the server that the button was unpressed */
+	virtual void TrackedDeviceButtonUntouched( uint32_t unWhichDevice, EVRButtonId eButtonId, double eventTimeOffset ) = 0;
+
+	/** notifies the server than a controller axis changed */
+	virtual void TrackedDeviceAxisUpdated( uint32_t unWhichDevice, uint32_t unWhichAxis, const VRControllerAxis_t & axisState ) = 0;
+
+	/** Notifies the server that the proximity sensor on the specified device  */
+	virtual void ProximitySensorState( uint32_t unWhichDevice, bool bProximitySensorTriggered ) = 0;
+
+	/** Sends a vendor specific event (VREvent_VendorSpecific_Reserved_Start..VREvent_VendorSpecific_Reserved_End */
+	virtual void VendorSpecificEvent( uint32_t unWhichDevice, vr::EVREventType eventType, const VREvent_Data_t & eventData, double eventTimeOffset ) = 0;
+
+	/** Returns true if SteamVR is exiting */
+	virtual bool IsExiting() = 0;
+
+	/** Returns true and fills the event with the next event on the queue if there is one. If there are no events
+	* this method returns false. uncbVREvent should be the size in bytes of the VREvent_t struct */
+	virtual bool PollNextEvent( VREvent_t *pEvent, uint32_t uncbVREvent ) = 0;
+};
+
+static const char *IVRServerDriverHost_Version = "IVRServerDriverHost_004";
+
+}
+// ivrhiddenarea.h
+namespace vr
+{
+
+class CVRHiddenAreaHelpers
+{
+public:
+	CVRHiddenAreaHelpers( IVRProperties *pProperties ) : m_pProperties( pProperties ) {}
+
+	/** Stores a hidden area mesh in a property */
+	ETrackedPropertyError SetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount );
+
+	/** retrieves a hidden area mesh from a property. Returns the vert count read out of the property.  */
+	uint32_t GetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount, ETrackedPropertyError *peError );
+
+private:
+	ETrackedDeviceProperty GetPropertyEnum( EVREye eEye, EHiddenAreaMeshType type )
+	{
+		return (ETrackedDeviceProperty)(Prop_DisplayHiddenArea_Binary_Start + ((int)type * 2) + (int)eEye);
+	}
+
+	IVRProperties *m_pProperties;
+};
+
+
+inline ETrackedPropertyError CVRHiddenAreaHelpers::SetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount )
+{
+	ETrackedDeviceProperty prop = GetPropertyEnum( eEye, type );
+	CVRPropertyHelpers propHelpers( m_pProperties );
+	return propHelpers.SetProperty( propHelpers.TrackedDeviceToPropertyContainer( k_unTrackedDeviceIndex_Hmd ), prop, pVerts, sizeof( HmdVector2_t ) * unVertCount, k_unHiddenAreaPropertyTag );
+}
+
+
+inline uint32_t CVRHiddenAreaHelpers::GetHiddenArea( EVREye eEye, EHiddenAreaMeshType type, HmdVector2_t *pVerts, uint32_t unVertCount, ETrackedPropertyError *peError )
+{
+	ETrackedDeviceProperty prop = GetPropertyEnum( eEye, type );
+	CVRPropertyHelpers propHelpers( m_pProperties );
+	ETrackedPropertyError propError;
+	PropertyTypeTag_t unTag;
+	uint32_t unBytesNeeded = propHelpers.GetProperty( propHelpers.TrackedDeviceToPropertyContainer( k_unTrackedDeviceIndex_Hmd ), prop, pVerts, sizeof( HmdVector2_t )*unVertCount, &unTag, &propError );
+	if ( propError == TrackedProp_Success && unTag != k_unHiddenAreaPropertyTag )
+	{
+		propError = TrackedProp_WrongDataType;
+		unBytesNeeded = 0;
+	}
+
+	if ( peError )
+	{
+		*peError = propError;
+	}
+
+	return unBytesNeeded / sizeof( HmdVector2_t );
+}
+
+}
+// ivrwatchdoghost.h
+namespace vr
+{
+
+/** This interface is provided by vrclient to allow the driver to make everything wake up */
+class IVRWatchdogHost
+{
+public:
+	/** Client drivers in watchdog mode should call this when they have received a signal from hardware that should
+	* cause SteamVR to start */
+	virtual void WatchdogWakeUp() = 0;
+};
+
+static const char *IVRWatchdogHost_Version = "IVRWatchdogHost_001";
+
+};
+
+
+
+
+
+
+
+namespace vr
+{
+	static const char * const k_InterfaceVersions[] =
+	{
+		IVRSettings_Version,
+		ITrackedDeviceServerDriver_Version,
+		IVRDisplayComponent_Version,
+		IVRDriverDirectModeComponent_Version,
+		IVRControllerComponent_Version,
+		IVRCameraComponent_Version,
+		IServerTrackedDeviceProvider_Version,
+		IVRWatchdogProvider_Version,
+		nullptr
+	};
+
+	inline IVRDriverContext *&VRDriverContext()
+	{
+		static IVRDriverContext *pHost;
+		return pHost;
+	}
+
+	class COpenVRDriverContext
+	{
+	public:
+		COpenVRDriverContext() : m_propertyHelpers(nullptr), m_hiddenAreaHelpers(nullptr) { Clear(); }
+		void Clear();
+
+		EVRInitError InitServer();
+		EVRInitError InitWatchdog();
+
+		IVRSettings *VRSettings()
+		{
+			if ( m_pVRSettings == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRSettings = (IVRSettings *)VRDriverContext()->GetGenericInterface( IVRSettings_Version, &eError );
+			}
+			return m_pVRSettings;
+		}
+
+		IVRProperties *VRPropertiesRaw()
+		{
+			if ( m_pVRProperties == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRProperties = (IVRProperties *)VRDriverContext()->GetGenericInterface( IVRProperties_Version, &eError );
+				m_propertyHelpers = CVRPropertyHelpers( m_pVRProperties );
+				m_hiddenAreaHelpers = CVRHiddenAreaHelpers( m_pVRProperties );
+			}
+			return m_pVRProperties;
+		}
+
+		CVRPropertyHelpers *VRProperties()
+		{
+			VRPropertiesRaw();
+			return &m_propertyHelpers;
+		}
+
+		CVRHiddenAreaHelpers *VRHiddenArea()
+		{
+			VRPropertiesRaw();
+			return &m_hiddenAreaHelpers;
+		}
+
+		IVRServerDriverHost *VRServerDriverHost()
+		{
+			if ( m_pVRServerDriverHost == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRServerDriverHost = (IVRServerDriverHost *)VRDriverContext()->GetGenericInterface( IVRServerDriverHost_Version, &eError );
+			}
+			return m_pVRServerDriverHost;
+		}
+
+		IVRWatchdogHost *VRWatchdogHost()
+		{
+			if ( m_pVRWatchdogHost == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRWatchdogHost = (IVRWatchdogHost *)VRDriverContext()->GetGenericInterface( IVRWatchdogHost_Version, &eError );
+			}
+			return m_pVRWatchdogHost;
+		}
+
+		IVRDriverLog *VRDriverLog()
+		{
+			if ( m_pVRDriverLog == nullptr )
+			{
+				EVRInitError eError;
+				m_pVRDriverLog = (IVRDriverLog *)VRDriverContext()->GetGenericInterface( IVRDriverLog_Version, &eError );
+			}
+			return m_pVRDriverLog;
+		}
+
+		DriverHandle_t VR_CALLTYPE VRDriverHandle()
+		{
+			return VRDriverContext()->GetDriverHandle();
+		}
+
+	private:
+		IVRSettings			*m_pVRSettings;
+		IVRProperties		*m_pVRProperties;
+		CVRPropertyHelpers	m_propertyHelpers;
+		CVRHiddenAreaHelpers	m_hiddenAreaHelpers;
+		IVRServerDriverHost	*m_pVRServerDriverHost;
+		IVRWatchdogHost		*m_pVRWatchdogHost;
+		IVRDriverLog		*m_pVRDriverLog;
+	};
+
+	inline COpenVRDriverContext &OpenVRInternal_ModuleServerDriverContext()
+	{
+		static void *ctx[sizeof( COpenVRDriverContext ) / sizeof( void * )];
+		return *(COpenVRDriverContext *)ctx; // bypass zero-init constructor
+	}
+
+	inline IVRSettings *VR_CALLTYPE VRSettings() { return OpenVRInternal_ModuleServerDriverContext().VRSettings(); }
+	inline IVRProperties *VR_CALLTYPE VRPropertiesRaw() { return OpenVRInternal_ModuleServerDriverContext().VRPropertiesRaw(); }
+	inline CVRPropertyHelpers *VR_CALLTYPE VRProperties() { return OpenVRInternal_ModuleServerDriverContext().VRProperties(); }
+	inline CVRHiddenAreaHelpers *VR_CALLTYPE VRHiddenArea() { return OpenVRInternal_ModuleServerDriverContext().VRHiddenArea(); }
+	inline IVRDriverLog *VR_CALLTYPE VRDriverLog() { return OpenVRInternal_ModuleServerDriverContext().VRDriverLog(); }
+	inline IVRServerDriverHost *VR_CALLTYPE VRServerDriverHost() { return OpenVRInternal_ModuleServerDriverContext().VRServerDriverHost(); }
+	inline IVRWatchdogHost *VR_CALLTYPE VRWatchdogHost() { return OpenVRInternal_ModuleServerDriverContext().VRWatchdogHost(); }
+	inline DriverHandle_t VR_CALLTYPE VRDriverHandle() { return OpenVRInternal_ModuleServerDriverContext().VRDriverHandle(); }
+	inline void COpenVRDriverContext::Clear()
+	{
+		m_pVRSettings = nullptr;
+		m_pVRProperties = nullptr;
+		m_pVRServerDriverHost = nullptr;
+		m_pVRDriverLog = nullptr;
+		m_pVRWatchdogHost = nullptr;
+	}
+
+	inline EVRInitError COpenVRDriverContext::InitServer()
+	{
+		Clear();
+		if ( !VRServerDriverHost()
+			|| !VRSettings()
+			|| !VRProperties()
+			|| !VRDriverLog() )
+			return VRInitError_Init_InterfaceNotFound;
+		return VRInitError_None;
+	}
+
+	inline EVRInitError COpenVRDriverContext::InitWatchdog()
+	{
+		Clear();
+		if ( !VRWatchdogHost()
+			|| !VRSettings()
+			|| !VRDriverLog() )
+			return VRInitError_Init_InterfaceNotFound;
+		return VRInitError_None;
+	}
+
+	inline EVRInitError InitServerDriverContext( IVRDriverContext *pContext )
+	{
+		VRDriverContext() = pContext;
+		return OpenVRInternal_ModuleServerDriverContext().InitServer();
+	}
+
+	inline EVRInitError InitWatchdogDriverContext( IVRDriverContext *pContext )
+	{
+		VRDriverContext() = pContext;
+		return OpenVRInternal_ModuleServerDriverContext().InitWatchdog();
+	}
+
+	inline void CleanupDriverContext()
+	{
+		VRDriverContext() = nullptr;
+		OpenVRInternal_ModuleServerDriverContext().Clear();
+	}
+
+	#define VR_INIT_SERVER_DRIVER_CONTEXT( pContext ) \
+			{ \
+			vr::EVRInitError eError = vr::InitServerDriverContext( pContext ); \
+			if( eError != vr::VRInitError_None ) \
+				return eError; \
+			}
+
+	#define VR_CLEANUP_SERVER_DRIVER_CONTEXT() \
+		vr::CleanupDriverContext();
+
+	#define VR_INIT_WATCHDOG_DRIVER_CONTEXT( pContext ) \
+			{ \
+			vr::EVRInitError eError = vr::InitWatchdogDriverContext( pContext ); \
+			if( eError != vr::VRInitError_None ) \
+				return eError; \
+			}
+
+	#define VR_CLEANUP_WATCHDOG_DRIVER_CONTEXT() \
+		vr::CleanupDriverContext();
+}
+// End
+
+#endif // _OPENVR_DRIVER_API
+
+
diff --git a/third_party/openvr/src/src/CMakeLists.txt b/third_party/openvr/src/src/CMakeLists.txt
new file mode 100644
index 0000000..5ad5cfa0
--- /dev/null
+++ b/third_party/openvr/src/src/CMakeLists.txt
@@ -0,0 +1,74 @@
+# Project name.
+project(openvr_api)
+
+set( LIBNAME "openvr_api" )
+
+# Set some properies for specific files.
+if(APPLE)
+  set(CMAKE_MACOSX_RPATH 0)
+  if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
+    set_source_files_properties(vrcommon/pathtools_public.cpp vrcommon/vrpathregistry_public.cpp PROPERTIES COMPILE_FLAGS "-x objective-c++")
+  endif()
+  if(BUILD_SHARED)
+    find_library(FOUNDATION_FRAMEWORK Foundation)
+    mark_as_advanced(FOUNDATION_FRAMEWORK)
+    set(EXTRA_LIBS ${EXTRA_LIBS} ${FOUNDATION_FRAMEWORK})
+  endif(BUILD_SHARED)
+elseif(WIN32)
+  if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    add_definitions( -DWIN64 )
+    set( LIBNAME "openvr_api64" )
+  endif()
+endif()
+
+# Add include folders.
+include_directories(${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/headers ${CMAKE_SOURCE_DIR}/src/vrcommon)
+
+if(USE_CUSTOM_LIBCXX)
+	link_directories(
+		${LIBCXX_LIB_DIR}
+	)
+endif()
+
+# Set the source group and files.
+set(CORE_FILES
+	openvr_api_public.cpp
+	jsoncpp.cpp
+)
+set(VRCOMMON_FILES
+	vrcommon/dirtools_public.cpp
+	vrcommon/envvartools_public.cpp
+	vrcommon/pathtools_public.cpp
+	vrcommon/sharedlibtools_public.cpp
+	vrcommon/hmderrors_public.cpp
+	vrcommon/vrpathregistry_public.cpp
+	vrcommon/strtools_public.cpp
+)
+
+set(SOURCE_FILES
+	${CORE_FILES}
+	${VRCOMMON_FILES}
+)
+
+source_group("Src" FILES
+	${CORE_FILES}
+)
+
+source_group("VRCommon" FILES
+	${VRCOMMON_FILES}
+)
+
+# Build the library.
+if(BUILD_SHARED)
+	add_library(${LIBNAME} SHARED ${SOURCE_FILES})
+else()
+	add_library(${LIBNAME} STATIC ${SOURCE_FILES})
+endif()
+
+if(USE_CUSTOM_LIBCXX)
+	set(EXTRA_LIBS ${EXTRA_LIBS} c++ c++abi)
+endif()
+
+target_link_libraries(${LIBNAME} ${EXTRA_LIBS})
+
+install(TARGETS ${LIBNAME} DESTINATION lib)
diff --git a/third_party/openvr/src/src/README b/third_party/openvr/src/src/README
new file mode 100644
index 0000000..953e105
--- /dev/null
+++ b/third_party/openvr/src/src/README
@@ -0,0 +1,35 @@
+This is the source code for the OpenVR API client binding library which connects
+OpenVR applications to the SteamVR runtime, taking into account the version
+of the OpenVR interface they were compiled against.
+
+The client binding library - openvr_api.dll on Windows, openvr_api.so on
+Linux, and openvr_api.dylib on macOS - knows how to find and read the
+SteamVR runtime installation information which allows it to find and
+dynamically connect to the installed runtime. In combination with the
+interface version identifiers from /include/openvr.h which are baked
+into applications at the time they are built, the OpenVR API client
+binding library captures and conveys to the SteamVR runtime the version
+of the OpenVR API interface behavior that the application expects.
+
+Applications carry with them a private/local copy of the client binding
+library when they ship, and they should install it locally to their
+application.  Applications should not install the client binding library
+globally or attempt to link to a globally installed client binding library.
+Doing so negates at least part of the ability for the client binding library
+to accurately reflect the version of the OpenVR API that the application
+was built against, and so hinders compatibility support in the face of
+API changes.
+
+Most applications should simply link to and redistribute with their application
+the pre-built client binding library found in the /bin directory of this
+repository. Some small number of applications which have specific requirements
+around redistributing only binaries they build themselves should build
+the client library from this source and either statically link it into
+their application or redistribute the binary they build.
+
+This is a cmake project, to build it use the version of cmake appropriate
+for your platform. For example, to build on a POSIX system simply perform
+
+  cd src; mkdir _build; cd _build; cmake ..; make
+
+and you will end up with the static library /src/_build/libopenvr_api.a
\ No newline at end of file
diff --git a/third_party/openvr/src/src/ivrclientcore.h b/third_party/openvr/src/src/ivrclientcore.h
new file mode 100644
index 0000000..b4c6f3a
--- /dev/null
+++ b/third_party/openvr/src/src/ivrclientcore.h
@@ -0,0 +1,35 @@
+//========= Copyright Valve Corporation ============//
+#pragma once
+
+namespace vr
+{
+
+class IVRClientCore
+{
+public:
+	/** Initializes the system */
+	virtual EVRInitError Init( vr::EVRApplicationType eApplicationType ) = 0;
+
+	/** cleans up everything in vrclient.dll and prepares the DLL to be unloaded */
+	virtual void Cleanup() = 0;
+
+	/** checks to see if the specified interface/version is supported in this vrclient.dll */
+	virtual EVRInitError IsInterfaceVersionValid( const char *pchInterfaceVersion ) = 0;
+
+	/** Retrieves any interface from vrclient.dll */
+	virtual void *GetGenericInterface( const char *pchNameAndVersion, EVRInitError *peError ) = 0;
+
+	/** Returns true if any driver has an HMD attached. Can be called outside of Init/Cleanup */
+	virtual bool BIsHmdPresent() = 0;
+
+	/** Returns an english error string from inside vrclient.dll which might be newer than the API DLL */
+	virtual const char *GetEnglishStringForHmdError( vr::EVRInitError eError ) = 0;
+
+	/** Returns an error symbol from inside vrclient.dll which might be newer than the API DLL */
+	virtual const char *GetIDForVRInitError( vr::EVRInitError eError ) = 0;
+};
+
+static const char * const IVRClientCore_Version = "IVRClientCore_002";
+
+
+}
diff --git a/third_party/openvr/src/src/json/json-forwards.h b/third_party/openvr/src/src/json/json-forwards.h
new file mode 100644
index 0000000..910c7de9
--- /dev/null
+++ b/third_party/openvr/src/src/json/json-forwards.h
@@ -0,0 +1,284 @@
+/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/).
+/// It is intended to be used with #include "json/json-forwards.h"
+/// This header provides forward declaration for all JsonCpp types.
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation, 
+tests and demonstration applications, are licensed under the following
+conditions...
+
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+jurisdictions which recognize such a disclaimer. In such jurisdictions, 
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
+released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this 
+software may choose to accept it either as 1) Public Domain, 2) under the 
+conditions of the MIT License (see below), or 3) under the terms of dual 
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+   
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+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.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
+# define JSON_FORWARD_AMALGATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+#define JSON_IS_AMALGAMATION
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+#define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of
+/// std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+
+// If non-zero, the library uses exceptions to report bad input instead of C
+// assertion macros. The default is to use exceptions.
+#ifndef JSON_USE_EXCEPTION
+#define JSON_USE_EXCEPTION 1
+#endif
+
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgated header.
+// #define JSON_IS_AMALGAMATION
+
+#ifdef JSON_IN_CPPTL
+#include <cpptl/config.h>
+#ifndef JSON_USE_CPPTL
+#define JSON_USE_CPPTL 1
+#endif
+#endif
+
+#ifdef JSON_IN_CPPTL
+#define JSON_API CPPTL_API
+#elif defined(JSON_DLL_BUILD)
+#if defined(_MSC_VER)
+#define JSON_API __declspec(dllexport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#elif defined(JSON_DLL)
+#if defined(_MSC_VER)
+#define JSON_API __declspec(dllimport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#endif // ifdef JSON_IN_CPPTL
+#if !defined(JSON_API)
+#define JSON_API
+#endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+#if defined(_MSC_VER) // MSVC
+#  if _MSC_VER <= 1200 // MSVC 6
+    // Microsoft Visual Studio 6 only support conversion from __int64 to double
+    // (no conversion from unsigned __int64).
+#    define JSON_USE_INT64_DOUBLE_CONVERSION 1
+    // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
+    // characters in the debug information)
+    // All projects I've ever seen with VS6 were using this globally (not bothering
+    // with pragma push/pop).
+#    pragma warning(disable : 4786)
+#  endif // MSVC 6
+
+#  if _MSC_VER >= 1500 // MSVC 2008
+    /// Indicates that the following function is deprecated.
+#    define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#  endif
+
+#endif // defined(_MSC_VER)
+
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // MSVC >= 2010
+
+#ifdef __clang__
+#if __has_feature(cxx_rvalue_references)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // has_feature
+
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // GXX_EXPERIMENTAL
+
+#endif // __clang__ || __GNUC__
+
+#endif // not defined JSON_HAS_RVALUE_REFERENCES
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+#define JSON_HAS_RVALUE_REFERENCES 0
+#endif
+
+#ifdef __clang__
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#  if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#    define JSONCPP_DEPRECATED(message)  __attribute__ ((deprecated(message)))
+#  elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#    define JSONCPP_DEPRECATED(message)  __attribute__((__deprecated__))
+#  endif  // GNUC version
+#endif // __clang__ || __GNUC__
+
+#if !defined(JSONCPP_DEPRECATED)
+#define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+namespace Json {
+typedef int Int;
+typedef unsigned int UInt;
+#if defined(JSON_NO_INT64)
+typedef int LargestInt;
+typedef unsigned int LargestUInt;
+#undef JSON_HAS_INT64
+#else                 // if defined(JSON_NO_INT64)
+// For Microsoft Visual use specific types as long long is not supported
+#if defined(_MSC_VER) // Microsoft Visual Studio
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else                 // if defined(_MSC_VER) // Other platforms, use long long
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif // if defined(_MSC_VER)
+typedef Int64 LargestInt;
+typedef UInt64 LargestUInt;
+#define JSON_HAS_INT64
+#endif // if defined(JSON_NO_INT64)
+} // end namespace Json
+
+#endif // JSON_CONFIG_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+#define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// writer.h
+class FastWriter;
+class StyledWriter;
+
+// reader.h
+class Reader;
+
+// features.h
+class Features;
+
+// value.h
+typedef unsigned int ArrayIndex;
+class StaticString;
+class Path;
+class PathArgument;
+class Value;
+class ValueIteratorBase;
+class ValueIterator;
+class ValueConstIterator;
+
+} // namespace Json
+
+#endif // JSON_FORWARDS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED
diff --git a/third_party/openvr/src/src/json/json.h b/third_party/openvr/src/src/json/json.h
new file mode 100644
index 0000000..d27f65d
--- /dev/null
+++ b/third_party/openvr/src/src/json/json.h
@@ -0,0 +1,2077 @@
+/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).
+/// It is intended to be used with #include "json/json.h"
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation, 
+tests and demonstration applications, are licensed under the following
+conditions...
+
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+jurisdictions which recognize such a disclaimer. In such jurisdictions, 
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
+released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this 
+software may choose to accept it either as 1) Public Domain, 2) under the 
+conditions of the MIT License (see below), or 3) under the terms of dual 
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+   
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+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.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#ifndef JSON_AMALGATED_H_INCLUDED
+# define JSON_AMALGATED_H_INCLUDED
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+#define JSON_IS_AMALGAMATION
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+// DO NOT EDIT. This file (and "version") is generated by CMake.
+// Run CMake configure step to update it.
+#ifndef JSON_VERSION_H_INCLUDED
+# define JSON_VERSION_H_INCLUDED
+
+# define JSONCPP_VERSION_STRING "1.6.5"
+# define JSONCPP_VERSION_MAJOR 1
+# define JSONCPP_VERSION_MINOR 6
+# define JSONCPP_VERSION_PATCH 5
+# define JSONCPP_VERSION_QUALIFIER
+# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
+
+#endif // JSON_VERSION_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/version.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_CONFIG_H_INCLUDED
+#define JSON_CONFIG_H_INCLUDED
+
+/// If defined, indicates that json library is embedded in CppTL library.
+//# define JSON_IN_CPPTL 1
+
+/// If defined, indicates that json may leverage CppTL library
+//#  define JSON_USE_CPPTL 1
+/// If defined, indicates that cpptl vector based map should be used instead of
+/// std::map
+/// as Value container.
+//#  define JSON_USE_CPPTL_SMALLMAP 1
+
+// If non-zero, the library uses exceptions to report bad input instead of C
+// assertion macros. The default is to use exceptions.
+#ifndef JSON_USE_EXCEPTION
+#define JSON_USE_EXCEPTION 1
+#endif
+
+/// If defined, indicates that the source file is amalgated
+/// to prevent private header inclusion.
+/// Remarks: it is automatically defined in the generated amalgated header.
+// #define JSON_IS_AMALGAMATION
+
+#ifdef JSON_IN_CPPTL
+#include <cpptl/config.h>
+#ifndef JSON_USE_CPPTL
+#define JSON_USE_CPPTL 1
+#endif
+#endif
+
+#ifdef JSON_IN_CPPTL
+#define JSON_API CPPTL_API
+#elif defined(JSON_DLL_BUILD)
+#if defined(_MSC_VER)
+#define JSON_API __declspec(dllexport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#elif defined(JSON_DLL)
+#if defined(_MSC_VER)
+#define JSON_API __declspec(dllimport)
+#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
+#endif // if defined(_MSC_VER)
+#endif // ifdef JSON_IN_CPPTL
+#if !defined(JSON_API)
+#define JSON_API
+#endif
+
+// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
+// integer
+// Storages, and 64 bits integer support is disabled.
+// #define JSON_NO_INT64 1
+
+#if defined(_MSC_VER) // MSVC
+#  if _MSC_VER <= 1200 // MSVC 6
+    // Microsoft Visual Studio 6 only support conversion from __int64 to double
+    // (no conversion from unsigned __int64).
+#    define JSON_USE_INT64_DOUBLE_CONVERSION 1
+    // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
+    // characters in the debug information)
+    // All projects I've ever seen with VS6 were using this globally (not bothering
+    // with pragma push/pop).
+#    pragma warning(disable : 4786)
+#  endif // MSVC 6
+
+#  if _MSC_VER >= 1500 // MSVC 2008
+    /// Indicates that the following function is deprecated.
+#    define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
+#  endif
+
+#endif // defined(_MSC_VER)
+
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+
+#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif // MSVC >= 2010
+
+#ifdef __clang__
+#if __has_feature(cxx_rvalue_references)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // has_feature
+
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+#define JSON_HAS_RVALUE_REFERENCES 1
+#endif  // GXX_EXPERIMENTAL
+
+#endif // __clang__ || __GNUC__
+
+#endif // not defined JSON_HAS_RVALUE_REFERENCES
+
+#ifndef JSON_HAS_RVALUE_REFERENCES
+#define JSON_HAS_RVALUE_REFERENCES 0
+#endif
+
+#ifdef __clang__
+#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
+#  if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
+#    define JSONCPP_DEPRECATED(message)  __attribute__ ((deprecated(message)))
+#  elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+#    define JSONCPP_DEPRECATED(message)  __attribute__((__deprecated__))
+#  endif  // GNUC version
+#endif // __clang__ || __GNUC__
+
+#if !defined(JSONCPP_DEPRECATED)
+#define JSONCPP_DEPRECATED(message)
+#endif // if !defined(JSONCPP_DEPRECATED)
+
+namespace Json {
+typedef int Int;
+typedef unsigned int UInt;
+#if defined(JSON_NO_INT64)
+typedef int LargestInt;
+typedef unsigned int LargestUInt;
+#undef JSON_HAS_INT64
+#else                 // if defined(JSON_NO_INT64)
+// For Microsoft Visual use specific types as long long is not supported
+#if defined(_MSC_VER) // Microsoft Visual Studio
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else                 // if defined(_MSC_VER) // Other platforms, use long long
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif // if defined(_MSC_VER)
+typedef Int64 LargestInt;
+typedef UInt64 LargestUInt;
+#define JSON_HAS_INT64
+#endif // if defined(JSON_NO_INT64)
+} // end namespace Json
+
+#endif // JSON_CONFIG_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/config.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_FORWARDS_H_INCLUDED
+#define JSON_FORWARDS_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+// writer.h
+class FastWriter;
+class StyledWriter;
+
+// reader.h
+class Reader;
+
+// features.h
+class Features;
+
+// value.h
+typedef unsigned int ArrayIndex;
+class StaticString;
+class Path;
+class PathArgument;
+class Value;
+class ValueIteratorBase;
+class ValueIterator;
+class ValueConstIterator;
+
+} // namespace Json
+
+#endif // JSON_FORWARDS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/forwards.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/features.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
+#define CPPTL_JSON_FEATURES_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+/** \brief Configuration passed to reader and writer.
+ * This configuration object can be used to force the Reader or Writer
+ * to behave in a standard conforming way.
+ */
+class JSON_API Features {
+public:
+  /** \brief A configuration that allows all features and assumes all strings
+   * are UTF-8.
+   * - C & C++ comments are allowed
+   * - Root object can be any JSON value
+   * - Assumes Value strings are encoded in UTF-8
+   */
+  static Features all();
+
+  /** \brief A configuration that is strictly compatible with the JSON
+   * specification.
+   * - Comments are forbidden.
+   * - Root object must be either an array or an object value.
+   * - Assumes Value strings are encoded in UTF-8
+   */
+  static Features strictMode();
+
+  /** \brief Initialize the configuration like JsonConfig::allFeatures;
+   */
+  Features();
+
+  /// \c true if comments are allowed. Default: \c true.
+  bool allowComments_;
+
+  /// \c true if root must be either an array or an object value. Default: \c
+  /// false.
+  bool strictRoot_;
+
+  /// \c true if dropped null placeholders are allowed. Default: \c false.
+  bool allowDroppedNullPlaceholders_;
+
+  /// \c true if numeric object key are allowed. Default: \c false.
+  bool allowNumericKeys_;
+};
+
+} // namespace Json
+
+#endif // CPPTL_JSON_FEATURES_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/features.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/value.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_H_INCLUDED
+#define CPPTL_JSON_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "forwards.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <string>
+#include <vector>
+#include <exception>
+
+#ifndef JSON_USE_CPPTL_SMALLMAP
+#include <map>
+#else
+#include <cpptl/smallmap.h>
+#endif
+#ifdef JSON_USE_CPPTL
+#include <cpptl/forwards.h>
+#endif
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+/** \brief JSON (JavaScript Object Notation).
+ */
+namespace Json {
+
+/** Base class for all exceptions we throw.
+ *
+ * We use nothing but these internally. Of course, STL can throw others.
+ */
+class JSON_API Exception : public std::exception {
+public:
+  Exception(std::string const& msg);
+  ~Exception() throw();
+  char const* what() const throw();
+protected:
+  std::string msg_;
+};
+
+/** Exceptions which the user cannot easily avoid.
+ *
+ * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
+ * 
+ * \remark derived from Json::Exception
+ */
+class JSON_API RuntimeError : public Exception {
+public:
+  RuntimeError(std::string const& msg);
+};
+
+/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
+ *
+ * These are precondition-violations (user bugs) and internal errors (our bugs).
+ * 
+ * \remark derived from Json::Exception
+ */
+class JSON_API LogicError : public Exception {
+public:
+  LogicError(std::string const& msg);
+};
+
+/// used internally
+void throwRuntimeError(std::string const& msg);
+/// used internally
+void throwLogicError(std::string const& msg);
+
+/** \brief Type of the value held by a Value object.
+ */
+enum ValueType {
+  nullValue = 0, ///< 'null' value
+  intValue,      ///< signed integer value
+  uintValue,     ///< unsigned integer value
+  realValue,     ///< double value
+  stringValue,   ///< UTF-8 string value
+  booleanValue,  ///< bool value
+  arrayValue,    ///< array value (ordered list)
+  objectValue    ///< object value (collection of name/value pairs).
+};
+
+enum CommentPlacement {
+  commentBefore = 0,      ///< a comment placed on the line before a value
+  commentAfterOnSameLine, ///< a comment just after a value on the same line
+  commentAfter, ///< a comment on the line after a value (only make sense for
+  /// root value)
+  numberOfCommentPlacement
+};
+
+//# ifdef JSON_USE_CPPTL
+//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
+//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
+//# endif
+
+/** \brief Lightweight wrapper to tag static string.
+ *
+ * Value constructor and objectValue member assignement takes advantage of the
+ * StaticString and avoid the cost of string duplication when storing the
+ * string or the member name.
+ *
+ * Example of usage:
+ * \code
+ * Json::Value aValue( StaticString("some text") );
+ * Json::Value object;
+ * static const StaticString code("code");
+ * object[code] = 1234;
+ * \endcode
+ */
+class JSON_API StaticString {
+public:
+  explicit StaticString(const char* czstring) : c_str_(czstring) {}
+
+  operator const char*() const { return c_str_; }
+
+  const char* c_str() const { return c_str_; }
+
+private:
+  const char* c_str_;
+};
+
+/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
+ *
+ * This class is a discriminated union wrapper that can represents a:
+ * - signed integer [range: Value::minInt - Value::maxInt]
+ * - unsigned integer (range: 0 - Value::maxUInt)
+ * - double
+ * - UTF-8 string
+ * - boolean
+ * - 'null'
+ * - an ordered list of Value
+ * - collection of name/value pairs (javascript object)
+ *
+ * The type of the held value is represented by a #ValueType and
+ * can be obtained using type().
+ *
+ * Values of an #objectValue or #arrayValue can be accessed using operator[]()
+ * methods.
+ * Non-const methods will automatically create the a #nullValue element
+ * if it does not exist.
+ * The sequence of an #arrayValue will be automatically resized and initialized
+ * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
+ *
+ * The get() methods can be used to obtain default value in the case the
+ * required element does not exist.
+ *
+ * It is possible to iterate over the list of a #objectValue values using
+ * the getMemberNames() method.
+ *
+ * \note #Value string-length fit in size_t, but keys must be < 2^30.
+ * (The reason is an implementation detail.) A #CharReader will raise an
+ * exception if a bound is exceeded to avoid security holes in your app,
+ * but the Value API does *not* check bounds. That is the responsibility
+ * of the caller.
+ */
+class JSON_API Value {
+  friend class ValueIteratorBase;
+public:
+  typedef std::vector<std::string> Members;
+  typedef ValueIterator iterator;
+  typedef ValueConstIterator const_iterator;
+  typedef Json::UInt UInt;
+  typedef Json::Int Int;
+#if defined(JSON_HAS_INT64)
+  typedef Json::UInt64 UInt64;
+  typedef Json::Int64 Int64;
+#endif // defined(JSON_HAS_INT64)
+  typedef Json::LargestInt LargestInt;
+  typedef Json::LargestUInt LargestUInt;
+  typedef Json::ArrayIndex ArrayIndex;
+
+  static const Value& null;  ///< We regret this reference to a global instance; prefer the simpler Value().
+  static const Value& nullRef;  ///< just a kludge for binary-compatibility; same as null
+  /// Minimum signed integer value that can be stored in a Json::Value.
+  static const LargestInt minLargestInt;
+  /// Maximum signed integer value that can be stored in a Json::Value.
+  static const LargestInt maxLargestInt;
+  /// Maximum unsigned integer value that can be stored in a Json::Value.
+  static const LargestUInt maxLargestUInt;
+
+  /// Minimum signed int value that can be stored in a Json::Value.
+  static const Int minInt;
+  /// Maximum signed int value that can be stored in a Json::Value.
+  static const Int maxInt;
+  /// Maximum unsigned int value that can be stored in a Json::Value.
+  static const UInt maxUInt;
+
+#if defined(JSON_HAS_INT64)
+  /// Minimum signed 64 bits int value that can be stored in a Json::Value.
+  static const Int64 minInt64;
+  /// Maximum signed 64 bits int value that can be stored in a Json::Value.
+  static const Int64 maxInt64;
+  /// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
+  static const UInt64 maxUInt64;
+#endif // defined(JSON_HAS_INT64)
+
+private:
+#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+  class CZString {
+  public:
+    enum DuplicationPolicy {
+      noDuplication = 0,
+      duplicate,
+      duplicateOnCopy
+    };
+    CZString(ArrayIndex index);
+    CZString(char const* str, unsigned length, DuplicationPolicy allocate);
+    CZString(CZString const& other);
+#if JSON_HAS_RVALUE_REFERENCES
+    CZString(CZString&& other);
+#endif
+    ~CZString();
+    CZString& operator=(CZString other);
+    bool operator<(CZString const& other) const;
+    bool operator==(CZString const& other) const;
+    ArrayIndex index() const;
+    //const char* c_str() const; ///< \deprecated
+    char const* data() const;
+    unsigned length() const;
+    bool isStaticString() const;
+
+  private:
+    void swap(CZString& other);
+
+    struct StringStorage {
+      unsigned policy_: 2;
+      unsigned length_: 30; // 1GB max
+    };
+
+    char const* cstr_;  // actually, a prefixed string, unless policy is noDup
+    union {
+      ArrayIndex index_;
+      StringStorage storage_;
+    };
+  };
+
+public:
+#ifndef JSON_USE_CPPTL_SMALLMAP
+  typedef std::map<CZString, Value> ObjectValues;
+#else
+  typedef CppTL::SmallMap<CZString, Value> ObjectValues;
+#endif // ifndef JSON_USE_CPPTL_SMALLMAP
+#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
+
+public:
+  /** \brief Create a default Value of the given type.
+
+    This is a very useful constructor.
+    To create an empty array, pass arrayValue.
+    To create an empty object, pass objectValue.
+    Another Value can then be set to this one by assignment.
+This is useful since clear() and resize() will not alter types.
+
+    Examples:
+\code
+Json::Value null_value; // null
+Json::Value arr_value(Json::arrayValue); // []
+Json::Value obj_value(Json::objectValue); // {}
+\endcode
+  */
+  Value(ValueType type = nullValue);
+  Value(Int value);
+  Value(UInt value);
+#if defined(JSON_HAS_INT64)
+  Value(Int64 value);
+  Value(UInt64 value);
+#endif // if defined(JSON_HAS_INT64)
+  Value(double value);
+  Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
+  Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
+  /** \brief Constructs a value from a static string.
+
+   * Like other value string constructor but do not duplicate the string for
+   * internal storage. The given string must remain alive after the call to this
+   * constructor.
+   * \note This works only for null-terminated strings. (We cannot change the
+   *   size of this class, so we have nowhere to store the length,
+   *   which might be computed later for various operations.)
+   *
+   * Example of usage:
+   * \code
+   * static StaticString foo("some text");
+   * Json::Value aValue(foo);
+   * \endcode
+   */
+  Value(const StaticString& value);
+  Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too.
+#ifdef JSON_USE_CPPTL
+  Value(const CppTL::ConstString& value);
+#endif
+  Value(bool value);
+  /// Deep copy.
+  Value(const Value& other);
+#if JSON_HAS_RVALUE_REFERENCES
+  /// Move constructor
+  Value(Value&& other);
+#endif
+  ~Value();
+
+  /// Deep copy, then swap(other).
+  /// \note Over-write existing comments. To preserve comments, use #swapPayload().
+  Value& operator=(Value other);
+  /// Swap everything.
+  void swap(Value& other);
+  /// Swap values but leave comments and source offsets in place.
+  void swapPayload(Value& other);
+
+  ValueType type() const;
+
+  /// Compare payload only, not comments etc.
+  bool operator<(const Value& other) const;
+  bool operator<=(const Value& other) const;
+  bool operator>=(const Value& other) const;
+  bool operator>(const Value& other) const;
+  bool operator==(const Value& other) const;
+  bool operator!=(const Value& other) const;
+  int compare(const Value& other) const;
+
+  const char* asCString() const; ///< Embedded zeroes could cause you trouble!
+  std::string asString() const; ///< Embedded zeroes are possible.
+  /** Get raw char* of string-value.
+   *  \return false if !string. (Seg-fault if str or end are NULL.)
+   */
+  bool getString(
+      char const** begin, char const** end) const;
+#ifdef JSON_USE_CPPTL
+  CppTL::ConstString asConstString() const;
+#endif
+  Int asInt() const;
+  UInt asUInt() const;
+#if defined(JSON_HAS_INT64)
+  Int64 asInt64() const;
+  UInt64 asUInt64() const;
+#endif // if defined(JSON_HAS_INT64)
+  LargestInt asLargestInt() const;
+  LargestUInt asLargestUInt() const;
+  float asFloat() const;
+  double asDouble() const;
+  bool asBool() const;
+
+  bool isNull() const;
+  bool isBool() const;
+  bool isInt() const;
+  bool isInt64() const;
+  bool isUInt() const;
+  bool isUInt64() const;
+  bool isIntegral() const;
+  bool isDouble() const;
+  bool isNumeric() const;
+  bool isString() const;
+  bool isArray() const;
+  bool isObject() const;
+
+  bool isConvertibleTo(ValueType other) const;
+
+  /// Number of values in array or object
+  ArrayIndex size() const;
+
+  /// \brief Return true if empty array, empty object, or null;
+  /// otherwise, false.
+  bool empty() const;
+
+  /// Return isNull()
+  bool operator!() const;
+
+  /// Remove all object members and array elements.
+  /// \pre type() is arrayValue, objectValue, or nullValue
+  /// \post type() is unchanged
+  void clear();
+
+  /// Resize the array to size elements.
+  /// New elements are initialized to null.
+  /// May only be called on nullValue or arrayValue.
+  /// \pre type() is arrayValue or nullValue
+  /// \post type() is arrayValue
+  void resize(ArrayIndex size);
+
+  /// Access an array element (zero based index ).
+  /// If the array contains less than index element, then null value are
+  /// inserted
+  /// in the array so that its size is index+1.
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  Value& operator[](ArrayIndex index);
+
+  /// Access an array element (zero based index ).
+  /// If the array contains less than index element, then null value are
+  /// inserted
+  /// in the array so that its size is index+1.
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  Value& operator[](int index);
+
+  /// Access an array element (zero based index )
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  const Value& operator[](ArrayIndex index) const;
+
+  /// Access an array element (zero based index )
+  /// (You may need to say 'value[0u]' to get your compiler to distinguish
+  ///  this from the operator[] which takes a string.)
+  const Value& operator[](int index) const;
+
+  /// If the array contains at least index+1 elements, returns the element
+  /// value,
+  /// otherwise returns defaultValue.
+  Value get(ArrayIndex index, const Value& defaultValue) const;
+  /// Return true if index < size().
+  bool isValidIndex(ArrayIndex index) const;
+  /// \brief Append value to array at the end.
+  ///
+  /// Equivalent to jsonvalue[jsonvalue.size()] = value;
+  Value& append(const Value& value);
+
+  /// Access an object value by name, create a null member if it does not exist.
+  /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
+  ///  Exceeding that will cause an exception.
+  Value& operator[](const char* key);
+  /// Access an object value by name, returns null if there is no member with
+  /// that name.
+  const Value& operator[](const char* key) const;
+  /// Access an object value by name, create a null member if it does not exist.
+  /// \param key may contain embedded nulls.
+  Value& operator[](const std::string& key);
+  /// Access an object value by name, returns null if there is no member with
+  /// that name.
+  /// \param key may contain embedded nulls.
+  const Value& operator[](const std::string& key) const;
+  /** \brief Access an object value by name, create a null member if it does not
+   exist.
+
+   * If the object has no entry for that name, then the member name used to store
+   * the new entry is not duplicated.
+   * Example of use:
+   * \code
+   * Json::Value object;
+   * static const StaticString code("code");
+   * object[code] = 1234;
+   * \endcode
+   */
+  Value& operator[](const StaticString& key);
+#ifdef JSON_USE_CPPTL
+  /// Access an object value by name, create a null member if it does not exist.
+  Value& operator[](const CppTL::ConstString& key);
+  /// Access an object value by name, returns null if there is no member with
+  /// that name.
+  const Value& operator[](const CppTL::ConstString& key) const;
+#endif
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  Value get(const char* key, const Value& defaultValue) const;
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  /// \note key may contain embedded nulls.
+  Value get(const char* begin, const char* end, const Value& defaultValue) const;
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  /// \param key may contain embedded nulls.
+  Value get(const std::string& key, const Value& defaultValue) const;
+#ifdef JSON_USE_CPPTL
+  /// Return the member named key if it exist, defaultValue otherwise.
+  /// \note deep copy
+  Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
+#endif
+  /// Most general and efficient version of isMember()const, get()const,
+  /// and operator[]const
+  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+  Value const* find(char const* begin, char const* end) const;
+  /// Most general and efficient version of object-mutators.
+  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
+  /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
+  Value const* demand(char const* begin, char const* end);
+  /// \brief Remove and return the named member.
+  ///
+  /// Do nothing if it did not exist.
+  /// \return the removed Value, or null.
+  /// \pre type() is objectValue or nullValue
+  /// \post type() is unchanged
+  /// \deprecated
+  Value removeMember(const char* key);
+  /// Same as removeMember(const char*)
+  /// \param key may contain embedded nulls.
+  /// \deprecated
+  Value removeMember(const std::string& key);
+  /// Same as removeMember(const char* begin, const char* end, Value* removed),
+  /// but 'key' is null-terminated.
+  bool removeMember(const char* key, Value* removed);
+  /** \brief Remove the named map member.
+
+      Update 'removed' iff removed.
+      \param key may contain embedded nulls.
+      \return true iff removed (no exceptions)
+  */
+  bool removeMember(std::string const& key, Value* removed);
+  /// Same as removeMember(std::string const& key, Value* removed)
+  bool removeMember(const char* begin, const char* end, Value* removed);
+  /** \brief Remove the indexed array element.
+
+      O(n) expensive operations.
+      Update 'removed' iff removed.
+      \return true iff removed (no exceptions)
+  */
+  bool removeIndex(ArrayIndex i, Value* removed);
+
+  /// Return true if the object has a member named key.
+  /// \note 'key' must be null-terminated.
+  bool isMember(const char* key) const;
+  /// Return true if the object has a member named key.
+  /// \param key may contain embedded nulls.
+  bool isMember(const std::string& key) const;
+  /// Same as isMember(std::string const& key)const
+  bool isMember(const char* begin, const char* end) const;
+#ifdef JSON_USE_CPPTL
+  /// Return true if the object has a member named key.
+  bool isMember(const CppTL::ConstString& key) const;
+#endif
+
+  /// \brief Return a list of the member names.
+  ///
+  /// If null, return an empty list.
+  /// \pre type() is objectValue or nullValue
+  /// \post if type() was nullValue, it remains nullValue
+  Members getMemberNames() const;
+
+  //# ifdef JSON_USE_CPPTL
+  //      EnumMemberNames enumMemberNames() const;
+  //      EnumValues enumValues() const;
+  //# endif
+
+  /// \deprecated Always pass len.
+  JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.")
+  void setComment(const char* comment, CommentPlacement placement);
+  /// Comments must be //... or /* ... */
+  void setComment(const char* comment, size_t len, CommentPlacement placement);
+  /// Comments must be //... or /* ... */
+  void setComment(const std::string& comment, CommentPlacement placement);
+  bool hasComment(CommentPlacement placement) const;
+  /// Include delimiters and embedded newlines.
+  std::string getComment(CommentPlacement placement) const;
+
+  std::string toStyledString() const;
+
+  const_iterator begin() const;
+  const_iterator end() const;
+
+  iterator begin();
+  iterator end();
+
+  // Accessors for the [start, limit) range of bytes within the JSON text from
+  // which this value was parsed, if any.
+  void setOffsetStart(size_t start);
+  void setOffsetLimit(size_t limit);
+  size_t getOffsetStart() const;
+  size_t getOffsetLimit() const;
+
+private:
+  void initBasic(ValueType type, bool allocated = false);
+
+  Value& resolveReference(const char* key);
+  Value& resolveReference(const char* key, const char* end);
+
+  struct CommentInfo {
+    CommentInfo();
+    ~CommentInfo();
+
+    void setComment(const char* text, size_t len);
+
+    char* comment_;
+  };
+
+  // struct MemberNamesTransform
+  //{
+  //   typedef const char *result_type;
+  //   const char *operator()( const CZString &name ) const
+  //   {
+  //      return name.c_str();
+  //   }
+  //};
+
+  union ValueHolder {
+    LargestInt int_;
+    LargestUInt uint_;
+    double real_;
+    bool bool_;
+    char* string_;  // actually ptr to unsigned, followed by str, unless !allocated_
+    ObjectValues* map_;
+  } value_;
+  ValueType type_ : 8;
+  unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
+                               // If not allocated_, string_ must be null-terminated.
+  CommentInfo* comments_;
+  Value *default_value_;  // if via .get( "key", default ), this was the default
+
+  // [start, limit) byte offsets in the source JSON text from which this Value
+  // was extracted.
+  size_t start_;
+  size_t limit_;
+};
+
+/** \brief Experimental and untested: represents an element of the "path" to
+ * access a node.
+ */
+class JSON_API PathArgument {
+public:
+  friend class Path;
+
+  PathArgument();
+  PathArgument(ArrayIndex index);
+  PathArgument(const char* key);
+  PathArgument(const std::string& key);
+
+private:
+  enum Kind {
+    kindNone = 0,
+    kindIndex,
+    kindKey
+  };
+  std::string key_;
+  ArrayIndex index_;
+  Kind kind_;
+};
+
+/** \brief Experimental and untested: represents a "path" to access a node.
+ *
+ * Syntax:
+ * - "." => root node
+ * - ".[n]" => elements at index 'n' of root node (an array value)
+ * - ".name" => member named 'name' of root node (an object value)
+ * - ".name1.name2.name3"
+ * - ".[0][1][2].name1[3]"
+ * - ".%" => member name is provided as parameter
+ * - ".[%]" => index is provied as parameter
+ */
+class JSON_API Path {
+public:
+  Path(const std::string& path,
+       const PathArgument& a1 = PathArgument(),
+       const PathArgument& a2 = PathArgument(),
+       const PathArgument& a3 = PathArgument(),
+       const PathArgument& a4 = PathArgument(),
+       const PathArgument& a5 = PathArgument());
+
+  const Value& resolve(const Value& root) const;
+  Value resolve(const Value& root, const Value& defaultValue) const;
+  /// Creates the "path" to access the specified node and returns a reference on
+  /// the node.
+  Value& make(Value& root) const;
+
+private:
+  typedef std::vector<const PathArgument*> InArgs;
+  typedef std::vector<PathArgument> Args;
+
+  void makePath(const std::string& path, const InArgs& in);
+  void addPathInArg(const std::string& path,
+                    const InArgs& in,
+                    InArgs::const_iterator& itInArg,
+                    PathArgument::Kind kind);
+  void invalidPath(const std::string& path, int location);
+
+  Args args_;
+};
+
+/** \brief base class for Value iterators.
+ *
+ */
+class JSON_API ValueIteratorBase {
+public:
+  typedef std::bidirectional_iterator_tag iterator_category;
+  typedef unsigned int size_t;
+  typedef int difference_type;
+  typedef ValueIteratorBase SelfType;
+
+  bool operator==(const SelfType& other) const { return isEqual(other); }
+
+  bool operator!=(const SelfType& other) const { return !isEqual(other); }
+
+  difference_type operator-(const SelfType& other) const {
+    return other.computeDistance(*this);
+  }
+
+  /// Return either the index or the member name of the referenced value as a
+  /// Value.
+  Value key() const;
+
+  /// Return the index of the referenced Value, or -1 if it is not an arrayValue.
+  UInt index() const;
+
+  /// Return the member name of the referenced Value, or "" if it is not an
+  /// objectValue.
+  /// \note Avoid `c_str()` on result, as embedded zeroes are possible.
+  std::string name() const;
+
+  /// Return the member name of the referenced Value. "" if it is not an
+  /// objectValue.
+  /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
+  JSONCPP_DEPRECATED("Use `key = name();` instead.")
+  char const* memberName() const;
+  /// Return the member name of the referenced Value, or NULL if it is not an
+  /// objectValue.
+  /// \note Better version than memberName(). Allows embedded nulls.
+  char const* memberName(char const** end) const;
+
+protected:
+  Value& deref() const;
+
+  void increment();
+
+  void decrement();
+
+  difference_type computeDistance(const SelfType& other) const;
+
+  bool isEqual(const SelfType& other) const;
+
+  void copy(const SelfType& other);
+
+private:
+  Value::ObjectValues::iterator current_;
+  // Indicates that iterator is for a null value.
+  bool isNull_;
+
+public:
+  // For some reason, BORLAND needs these at the end, rather
+  // than earlier. No idea why.
+  ValueIteratorBase();
+  explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
+};
+
+/** \brief const iterator for object and array value.
+ *
+ */
+class JSON_API ValueConstIterator : public ValueIteratorBase {
+  friend class Value;
+
+public:
+  typedef const Value value_type;
+  //typedef unsigned int size_t;
+  //typedef int difference_type;
+  typedef const Value& reference;
+  typedef const Value* pointer;
+  typedef ValueConstIterator SelfType;
+
+  ValueConstIterator();
+  ValueConstIterator(ValueIterator const& other);
+
+private:
+/*! \internal Use by Value to create an iterator.
+ */
+  explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
+public:
+  SelfType& operator=(const ValueIteratorBase& other);
+
+  SelfType operator++(int) {
+    SelfType temp(*this);
+    ++*this;
+    return temp;
+  }
+
+  SelfType operator--(int) {
+    SelfType temp(*this);
+    --*this;
+    return temp;
+  }
+
+  SelfType& operator--() {
+    decrement();
+    return *this;
+  }
+
+  SelfType& operator++() {
+    increment();
+    return *this;
+  }
+
+  reference operator*() const { return deref(); }
+
+  pointer operator->() const { return &deref(); }
+};
+
+/** \brief Iterator for object and array value.
+ */
+class JSON_API ValueIterator : public ValueIteratorBase {
+  friend class Value;
+
+public:
+  typedef Value value_type;
+  typedef unsigned int size_t;
+  typedef int difference_type;
+  typedef Value& reference;
+  typedef Value* pointer;
+  typedef ValueIterator SelfType;
+
+  ValueIterator();
+  explicit ValueIterator(const ValueConstIterator& other);
+  ValueIterator(const ValueIterator& other);
+
+private:
+/*! \internal Use by Value to create an iterator.
+ */
+  explicit ValueIterator(const Value::ObjectValues::iterator& current);
+public:
+  SelfType& operator=(const SelfType& other);
+
+  SelfType operator++(int) {
+    SelfType temp(*this);
+    ++*this;
+    return temp;
+  }
+
+  SelfType operator--(int) {
+    SelfType temp(*this);
+    --*this;
+    return temp;
+  }
+
+  SelfType& operator--() {
+    decrement();
+    return *this;
+  }
+
+  SelfType& operator++() {
+    increment();
+    return *this;
+  }
+
+  reference operator*() const { return deref(); }
+
+  pointer operator->() const { return &deref(); }
+};
+
+} // namespace Json
+
+
+namespace std {
+/// Specialize std::swap() for Json::Value.
+template<>
+inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
+}
+
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // CPPTL_JSON_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/value.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/reader.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_READER_H_INCLUDED
+#define CPPTL_JSON_READER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "features.h"
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <deque>
+#include <iosfwd>
+#include <stack>
+#include <string>
+#include <istream>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+namespace Json {
+
+/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
+ *Value.
+ *
+ * \deprecated Use CharReader and CharReaderBuilder.
+ */
+class JSON_API Reader {
+public:
+  typedef char Char;
+  typedef const Char* Location;
+
+  /** \brief An error tagged with where in the JSON text it was encountered.
+   *
+   * The offsets give the [start, limit) range of bytes within the text. Note
+   * that this is bytes, not codepoints.
+   *
+   */
+  struct StructuredError {
+    size_t offset_start;
+    size_t offset_limit;
+    std::string message;
+  };
+
+  /** \brief Constructs a Reader allowing all features
+   * for parsing.
+   */
+  Reader();
+
+  /** \brief Constructs a Reader allowing the specified feature set
+   * for parsing.
+   */
+  Reader(const Features& features);
+
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   * document.
+   * \param document UTF-8 encoded string containing the document to read.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param collectComments \c true to collect comment and allow writing them
+   * back during
+   *                        serialization, \c false to discard comments.
+   *                        This parameter is ignored if
+   * Features::allowComments_
+   *                        is \c false.
+   * \return \c true if the document was successfully parsed, \c false if an
+   * error occurred.
+   */
+  bool
+  parse(const std::string& document, Value& root, bool collectComments = true);
+
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   document.
+   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
+   document to read.
+   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+   document to read.
+   *               Must be >= beginDoc.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param collectComments \c true to collect comment and allow writing them
+   back during
+   *                        serialization, \c false to discard comments.
+   *                        This parameter is ignored if
+   Features::allowComments_
+   *                        is \c false.
+   * \return \c true if the document was successfully parsed, \c false if an
+   error occurred.
+   */
+  bool parse(const char* beginDoc,
+             const char* endDoc,
+             Value& root,
+             bool collectComments = true);
+
+  /// \brief Parse from input stream.
+  /// \see Json::operator>>(std::istream&, Json::Value&).
+  bool parse(std::istream& is, Value& root, bool collectComments = true);
+
+  /** \brief Returns a user friendly string that list errors in the parsed
+   * document.
+   * \return Formatted error message with the list of errors with their location
+   * in
+   *         the parsed document. An empty string is returned if no error
+   * occurred
+   *         during parsing.
+   * \deprecated Use getFormattedErrorMessages() instead (typo fix).
+   */
+  JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
+  std::string getFormatedErrorMessages() const;
+
+  /** \brief Returns a user friendly string that list errors in the parsed
+   * document.
+   * \return Formatted error message with the list of errors with their location
+   * in
+   *         the parsed document. An empty string is returned if no error
+   * occurred
+   *         during parsing.
+   */
+  std::string getFormattedErrorMessages() const;
+
+  /** \brief Returns a vector of structured erros encounted while parsing.
+   * \return A (possibly empty) vector of StructuredError objects. Currently
+   *         only one error can be returned, but the caller should tolerate
+   * multiple
+   *         errors.  This can occur if the parser recovers from a non-fatal
+   *         parse error and then encounters additional errors.
+   */
+  std::vector<StructuredError> getStructuredErrors() const;
+
+  /** \brief Add a semantic error message.
+   * \param value JSON Value location associated with the error
+   * \param message The error message.
+   * \return \c true if the error was successfully added, \c false if the
+   * Value offset exceeds the document size.
+   */
+  bool pushError(const Value& value, const std::string& message);
+
+  /** \brief Add a semantic error message with extra context.
+   * \param value JSON Value location associated with the error
+   * \param message The error message.
+   * \param extra Additional JSON Value location to contextualize the error
+   * \return \c true if the error was successfully added, \c false if either
+   * Value offset exceeds the document size.
+   */
+  bool pushError(const Value& value, const std::string& message, const Value& extra);
+
+  /** \brief Return whether there are any errors.
+   * \return \c true if there are no errors to report \c false if
+   * errors have occurred.
+   */
+  bool good() const;
+
+private:
+  enum TokenType {
+    tokenEndOfStream = 0,
+    tokenObjectBegin,
+    tokenObjectEnd,
+    tokenArrayBegin,
+    tokenArrayEnd,
+    tokenString,
+    tokenNumber,
+    tokenTrue,
+    tokenFalse,
+    tokenNull,
+    tokenArraySeparator,
+    tokenMemberSeparator,
+    tokenComment,
+    tokenError
+  };
+
+  class Token {
+  public:
+    TokenType type_;
+    Location start_;
+    Location end_;
+  };
+
+  class ErrorInfo {
+  public:
+    Token token_;
+    std::string message_;
+    Location extra_;
+  };
+
+  typedef std::deque<ErrorInfo> Errors;
+
+  bool readToken(Token& token);
+  void skipSpaces();
+  bool match(Location pattern, int patternLength);
+  bool readComment();
+  bool readCStyleComment();
+  bool readCppStyleComment();
+  bool readString();
+  void readNumber();
+  bool readValue();
+  bool readObject(Token& token);
+  bool readArray(Token& token);
+  bool decodeNumber(Token& token);
+  bool decodeNumber(Token& token, Value& decoded);
+  bool decodeString(Token& token);
+  bool decodeString(Token& token, std::string& decoded);
+  bool decodeDouble(Token& token);
+  bool decodeDouble(Token& token, Value& decoded);
+  bool decodeUnicodeCodePoint(Token& token,
+                              Location& current,
+                              Location end,
+                              unsigned int& unicode);
+  bool decodeUnicodeEscapeSequence(Token& token,
+                                   Location& current,
+                                   Location end,
+                                   unsigned int& unicode);
+  bool addError(const std::string& message, Token& token, Location extra = 0);
+  bool recoverFromError(TokenType skipUntilToken);
+  bool addErrorAndRecover(const std::string& message,
+                          Token& token,
+                          TokenType skipUntilToken);
+  void skipUntilSpace();
+  Value& currentValue();
+  Char getNextChar();
+  void
+  getLocationLineAndColumn(Location location, int& line, int& column) const;
+  std::string getLocationLineAndColumn(Location location) const;
+  std::string getLocationSnippet(Location location) const;
+  void addComment(Location begin, Location end, CommentPlacement placement);
+  void skipCommentTokens(Token& token);
+
+  typedef std::stack<Value*> Nodes;
+  Nodes nodes_;
+  Errors errors_;
+  std::string document_;
+  Location begin_;
+  Location end_;
+  Location current_;
+  Location lastValueEnd_;
+  Value* lastValue_;
+  std::string commentsBefore_;
+  Features features_;
+  bool collectComments_;
+};  // Reader
+
+/** Interface for reading JSON from a char array.
+ */
+class JSON_API CharReader {
+public:
+  virtual ~CharReader() {}
+  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
+   document.
+   * The document must be a UTF-8 encoded string containing the document to read.
+   *
+   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
+   document to read.
+   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
+   document to read.
+   *        Must be >= beginDoc.
+   * \param root [out] Contains the root value of the document if it was
+   *             successfully parsed.
+   * \param errs [out] Formatted error messages (if not NULL)
+   *        a user friendly string that lists errors in the parsed
+   * document.
+   * \return \c true if the document was successfully parsed, \c false if an
+   error occurred.
+   */
+  virtual bool parse(
+      char const* beginDoc, char const* endDoc,
+      Value* root, std::string* errs) = 0;
+
+  class JSON_API Factory {
+  public:
+    virtual ~Factory() {}
+    /** \brief Allocate a CharReader via operator new().
+     * \throw std::exception if something goes wrong (e.g. invalid settings)
+     */
+    virtual CharReader* newCharReader() const = 0;
+  };  // Factory
+};  // CharReader
+
+/** \brief Build a CharReader implementation.
+
+Usage:
+\code
+  using namespace Json;
+  CharReaderBuilder builder;
+  builder["collectComments"] = false;
+  Value value;
+  std::string errs;
+  bool ok = parseFromStream(builder, std::cin, &value, &errs);
+\endcode
+*/
+class JSON_API CharReaderBuilder : public CharReader::Factory {
+public:
+  // Note: We use a Json::Value so that we can add data-members to this class
+  // without a major version bump.
+  /** Configuration of this builder.
+    These are case-sensitive.
+    Available settings (case-sensitive):
+    - `"collectComments": false or true`
+      - true to collect comment and allow writing them
+        back during serialization, false to discard comments.
+        This parameter is ignored if allowComments is false.
+    - `"allowComments": false or true`
+      - true if comments are allowed.
+    - `"strictRoot": false or true`
+      - true if root must be either an array or an object value
+    - `"allowDroppedNullPlaceholders": false or true`
+      - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
+    - `"allowNumericKeys": false or true`
+      - true if numeric object keys are allowed.
+    - `"allowSingleQuotes": false or true`
+      - true if '' are allowed for strings (both keys and values)
+    - `"stackLimit": integer`
+      - Exceeding stackLimit (recursive depth of `readValue()`) will
+        cause an exception.
+      - This is a security issue (seg-faults caused by deeply nested JSON),
+        so the default is low.
+    - `"failIfExtra": false or true`
+      - If true, `parse()` returns false when extra non-whitespace trails
+        the JSON value in the input string.
+    - `"rejectDupKeys": false or true`
+      - If true, `parse()` returns false when a key is duplicated within an object.
+    - `"allowSpecialFloats": false or true`
+      - If true, special float values (NaNs and infinities) are allowed 
+        and their values are lossfree restorable.
+
+    You can examine 'settings_` yourself
+    to see the defaults. You can also write and read them just like any
+    JSON Value.
+    \sa setDefaults()
+    */
+  Json::Value settings_;
+
+  CharReaderBuilder();
+  ~CharReaderBuilder();
+
+  CharReader* newCharReader() const;
+
+  /** \return true if 'settings' are legal and consistent;
+   *   otherwise, indicate bad settings via 'invalid'.
+   */
+  bool validate(Json::Value* invalid) const;
+
+  /** A simple way to update a specific setting.
+   */
+  Value& operator[](std::string key);
+
+  /** Called by ctor, but you can use this to reset settings_.
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
+   */
+  static void setDefaults(Json::Value* settings);
+  /** Same as old Features::strictMode().
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
+   */
+  static void strictMode(Json::Value* settings);
+};
+
+/** Consume entire stream and use its begin/end.
+  * Someday we might have a real StreamReader, but for now this
+  * is convenient.
+  */
+bool JSON_API parseFromStream(
+    CharReader::Factory const&,
+    std::istream&,
+    Value* root, std::string* errs);
+
+/** \brief Read from 'sin' into 'root'.
+
+ Always keep comments from the input JSON.
+
+ This can be used to read a file into a particular sub-object.
+ For example:
+ \code
+ Json::Value root;
+ cin >> root["dir"]["file"];
+ cout << root;
+ \endcode
+ Result:
+ \verbatim
+ {
+ "dir": {
+     "file": {
+     // The input stream JSON would be nested here.
+     }
+ }
+ }
+ \endverbatim
+ \throw std::exception on parse error.
+ \see Json::operator<<()
+*/
+JSON_API std::istream& operator>>(std::istream&, Value&);
+
+} // namespace Json
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // CPPTL_JSON_READER_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/reader.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/writer.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef JSON_WRITER_H_INCLUDED
+#define JSON_WRITER_H_INCLUDED
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "value.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <vector>
+#include <string>
+#include <ostream>
+
+// Disable warning C4251: <data member>: <type> needs to have dll-interface to
+// be used by...
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(push)
+#pragma warning(disable : 4251)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+namespace Json {
+
+class Value;
+
+/**
+
+Usage:
+\code
+  using namespace Json;
+  void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
+    std::unique_ptr<StreamWriter> const writer(
+      factory.newStreamWriter());
+    writer->write(value, &std::cout);
+    std::cout << std::endl;  // add lf and flush
+  }
+\endcode
+*/
+class JSON_API StreamWriter {
+protected:
+  std::ostream* sout_;  // not owned; will not delete
+public:
+  StreamWriter();
+  virtual ~StreamWriter();
+  /** Write Value into document as configured in sub-class.
+      Do not take ownership of sout, but maintain a reference during function.
+      \pre sout != NULL
+      \return zero on success (For now, we always return zero, so check the stream instead.)
+      \throw std::exception possibly, depending on configuration
+   */
+  virtual int write(Value const& root, std::ostream* sout) = 0;
+
+  /** \brief A simple abstract factory.
+   */
+  class JSON_API Factory {
+  public:
+    virtual ~Factory();
+    /** \brief Allocate a CharReader via operator new().
+     * \throw std::exception if something goes wrong (e.g. invalid settings)
+     */
+    virtual StreamWriter* newStreamWriter() const = 0;
+  };  // Factory
+};  // StreamWriter
+
+/** \brief Write into stringstream, then return string, for convenience.
+ * A StreamWriter will be created from the factory, used, and then deleted.
+ */
+std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
+
+
+/** \brief Build a StreamWriter implementation.
+
+Usage:
+\code
+  using namespace Json;
+  Value value = ...;
+  StreamWriterBuilder builder;
+  builder["commentStyle"] = "None";
+  builder["indentation"] = "   ";  // or whatever you like
+  std::unique_ptr<Json::StreamWriter> writer(
+      builder.newStreamWriter());
+  writer->write(value, &std::cout);
+  std::cout << std::endl;  // add lf and flush
+\endcode
+*/
+class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
+public:
+  // Note: We use a Json::Value so that we can add data-members to this class
+  // without a major version bump.
+  /** Configuration of this builder.
+    Available settings (case-sensitive):
+    - "commentStyle": "None" or "All"
+    - "indentation":  "<anything>"
+    - "enableYAMLCompatibility": false or true
+      - slightly change the whitespace around colons
+    - "dropNullPlaceholders": false or true
+      - Drop the "null" string from the writer's output for nullValues.
+        Strictly speaking, this is not valid JSON. But when the output is being
+        fed to a browser's Javascript, it makes for smaller output and the
+        browser can handle the output just fine.
+    - "useSpecialFloats": false or true
+      - If true, outputs non-finite floating point values in the following way:
+        NaN values as "NaN", positive infinity as "Infinity", and negative infinity
+        as "-Infinity".
+
+    You can examine 'settings_` yourself
+    to see the defaults. You can also write and read them just like any
+    JSON Value.
+    \sa setDefaults()
+    */
+  Json::Value settings_;
+
+  StreamWriterBuilder();
+  ~StreamWriterBuilder();
+
+  /**
+   * \throw std::exception if something goes wrong (e.g. invalid settings)
+   */
+  StreamWriter* newStreamWriter() const;
+
+  /** \return true if 'settings' are legal and consistent;
+   *   otherwise, indicate bad settings via 'invalid'.
+   */
+  bool validate(Json::Value* invalid) const;
+  /** A simple way to update a specific setting.
+   */
+  Value& operator[](std::string key);
+
+  /** Called by ctor, but you can use this to reset settings_.
+   * \pre 'settings' != NULL (but Json::null is fine)
+   * \remark Defaults:
+   * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
+   */
+  static void setDefaults(Json::Value* settings);
+};
+
+/** \brief Abstract class for writers.
+ * \deprecated Use StreamWriter. (And really, this is an implementation detail.)
+ */
+class JSON_API Writer {
+public:
+  virtual ~Writer();
+
+  virtual std::string write(const Value& root) = 0;
+};
+
+/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
+ *without formatting (not human friendly).
+ *
+ * The JSON document is written in a single line. It is not intended for 'human'
+ *consumption,
+ * but may be usefull to support feature such as RPC where bandwith is limited.
+ * \sa Reader, Value
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API FastWriter : public Writer {
+
+public:
+  FastWriter();
+  ~FastWriter() {}
+
+  void enableYAMLCompatibility();
+
+  /** \brief Drop the "null" string from the writer's output for nullValues.
+   * Strictly speaking, this is not valid JSON. But when the output is being
+   * fed to a browser's Javascript, it makes for smaller output and the
+   * browser can handle the output just fine.
+   */
+  void dropNullPlaceholders();
+
+  void omitEndingLineFeed();
+
+public: // overridden from Writer
+  std::string write(const Value& root);
+
+private:
+  void writeValue(const Value& value);
+
+  std::string document_;
+  bool yamlCompatiblityEnabled_;
+  bool dropNullPlaceholders_;
+  bool omitEndingLineFeed_;
+};
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ *human friendly way.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ *     - if empty then print {} without indent and line break
+ *     - if not empty the print '{', line break & indent, print one value per
+ *line
+ *       and then unindent and line break and print '}'.
+ * - Array value:
+ *     - if empty then print [] without indent and line break
+ *     - if the array contains no object value, empty array or some other value
+ *types,
+ *       and all the values fit on one lines, then print the array on a single
+ *line.
+ *     - otherwise, it the values do not fit on one line, or the array contains
+ *       object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ *#CommentPlacement.
+ *
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API StyledWriter : public Writer {
+public:
+  StyledWriter();
+  ~StyledWriter() {}
+
+public: // overridden from Writer
+  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+   * \param root Value to serialize.
+   * \return String containing the JSON document that represents the root value.
+   */
+  std::string write(const Value& root);
+
+private:
+  void writeValue(const Value& value);
+  void writeArrayValue(const Value& value);
+  bool isMultineArray(const Value& value);
+  void pushValue(const std::string& value);
+  void writeIndent();
+  void writeWithIndent(const std::string& value);
+  void indent();
+  void unindent();
+  void writeCommentBeforeValue(const Value& root);
+  void writeCommentAfterValueOnSameLine(const Value& root);
+  bool hasCommentForValue(const Value& value);
+  static std::string normalizeEOL(const std::string& text);
+
+  typedef std::vector<std::string> ChildValues;
+
+  ChildValues childValues_;
+  std::string document_;
+  std::string indentString_;
+  int rightMargin_;
+  int indentSize_;
+  bool addChildValues_;
+};
+
+/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
+ human friendly way,
+     to a stream rather than to a string.
+ *
+ * The rules for line break and indent are as follow:
+ * - Object value:
+ *     - if empty then print {} without indent and line break
+ *     - if not empty the print '{', line break & indent, print one value per
+ line
+ *       and then unindent and line break and print '}'.
+ * - Array value:
+ *     - if empty then print [] without indent and line break
+ *     - if the array contains no object value, empty array or some other value
+ types,
+ *       and all the values fit on one lines, then print the array on a single
+ line.
+ *     - otherwise, it the values do not fit on one line, or the array contains
+ *       object or non empty array, then print one value per line.
+ *
+ * If the Value have comments then they are outputed according to their
+ #CommentPlacement.
+ *
+ * \param indentation Each level will be indented by this amount extra.
+ * \sa Reader, Value, Value::setComment()
+ * \deprecated Use StreamWriterBuilder.
+ */
+class JSON_API StyledStreamWriter {
+public:
+  StyledStreamWriter(std::string indentation = "\t");
+  ~StyledStreamWriter() {}
+
+public:
+  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
+   * \param out Stream to write to. (Can be ostringstream, e.g.)
+   * \param root Value to serialize.
+   * \note There is no point in deriving from Writer, since write() should not
+   * return a value.
+   */
+  void write(std::ostream& out, const Value& root);
+
+private:
+  void writeValue(const Value& value);
+  void writeArrayValue(const Value& value);
+  bool isMultineArray(const Value& value);
+  void pushValue(const std::string& value);
+  void writeIndent();
+  void writeWithIndent(const std::string& value);
+  void indent();
+  void unindent();
+  void writeCommentBeforeValue(const Value& root);
+  void writeCommentAfterValueOnSameLine(const Value& root);
+  bool hasCommentForValue(const Value& value);
+  static std::string normalizeEOL(const std::string& text);
+
+  typedef std::vector<std::string> ChildValues;
+
+  ChildValues childValues_;
+  std::ostream* document_;
+  std::string indentString_;
+  int rightMargin_;
+  std::string indentation_;
+  bool addChildValues_ : 1;
+  bool indented_ : 1;
+};
+
+#if defined(JSON_HAS_INT64)
+std::string JSON_API valueToString(Int value);
+std::string JSON_API valueToString(UInt value);
+#endif // if defined(JSON_HAS_INT64)
+std::string JSON_API valueToString(LargestInt value);
+std::string JSON_API valueToString(LargestUInt value);
+std::string JSON_API valueToString(double value);
+std::string JSON_API valueToString(bool value);
+std::string JSON_API valueToQuotedString(const char* value);
+
+/// \brief Output using the StyledStreamWriter.
+/// \see Json::operator>>()
+JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
+
+} // namespace Json
+
+#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+#pragma warning(pop)
+#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
+
+#endif // JSON_WRITER_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/writer.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: include/json/assertions.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
+#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
+
+#include <stdlib.h>
+#include <sstream>
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include "config.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+/** It should not be possible for a maliciously designed file to
+ *  cause an abort() or seg-fault, so these macros are used only
+ *  for pre-condition violations and internal logic errors.
+ */
+#if JSON_USE_EXCEPTION
+
+// @todo <= add detail about condition in exception
+# define JSON_ASSERT(condition)                                                \
+  {if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
+
+# define JSON_FAIL_MESSAGE(message)                                            \
+  {                                                                            \
+    std::ostringstream oss; oss << message;                                    \
+    Json::throwLogicError(oss.str());                                          \
+    abort();                                                                   \
+  }
+
+#else // JSON_USE_EXCEPTION
+
+# define JSON_ASSERT(condition) assert(condition)
+
+// The call to assert() will show the failure message in debug builds. In
+// release builds we abort, for a core-dump or debugger.
+# define JSON_FAIL_MESSAGE(message)                                            \
+  {                                                                            \
+    std::ostringstream oss; oss << message;                                    \
+    assert(false && oss.str().c_str());                                        \
+    abort();                                                                   \
+  }
+
+
+#endif
+
+#define JSON_ASSERT_MESSAGE(condition, message)                                \
+  if (!(condition)) {                                                          \
+    JSON_FAIL_MESSAGE(message);                                                \
+  }
+
+#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: include/json/assertions.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+#endif //ifndef JSON_AMALGATED_H_INCLUDED
diff --git a/third_party/openvr/src/src/jsoncpp.cpp b/third_party/openvr/src/src/jsoncpp.cpp
new file mode 100644
index 0000000..e67d353
--- /dev/null
+++ b/third_party/openvr/src/src/jsoncpp.cpp
@@ -0,0 +1,5266 @@
+/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
+/// It is intended to be used with #include "json/json.h"
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+/*
+The JsonCpp library's source code, including accompanying documentation, 
+tests and demonstration applications, are licensed under the following
+conditions...
+
+The author (Baptiste Lepilleur) explicitly disclaims copyright in all 
+jurisdictions which recognize such a disclaimer. In such jurisdictions, 
+this software is released into the Public Domain.
+
+In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
+2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
+released under the terms of the MIT License (see below).
+
+In jurisdictions which recognize Public Domain property, the user of this 
+software may choose to accept it either as 1) Public Domain, 2) under the 
+conditions of the MIT License (see below), or 3) under the terms of dual 
+Public Domain/MIT License conditions described here, as they choose.
+
+The MIT License is about as close to Public Domain as a license can get, and is
+described in clear, concise terms at:
+
+   http://en.wikipedia.org/wiki/MIT_License
+   
+The full text of the MIT License follows:
+
+========================================================================
+Copyright (c) 2007-2010 Baptiste Lepilleur
+
+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.
+========================================================================
+(END LICENSE TEXT)
+
+The MIT license is compatible with both the GPL and commercial
+software, affording one all of the rights of Public Domain with the
+minor nuisance of being required to keep the above copyright notice
+and license text in the source code. Note also that by accepting the
+Public Domain "license" you can re-license your copy using whatever
+license you like.
+
+*/
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: LICENSE
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+#include "json/json.h"
+
+#ifndef JSON_IS_AMALGAMATION
+#error "Compile with -I PATH_TO_JSON_DIRECTORY"
+#endif
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_tool.h
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+
+/* This header provides common string manipulation support, such as UTF-8,
+ * portable conversion from/to string...
+ *
+ * It is an internal header that must not be exposed.
+ */
+
+namespace Json {
+
+/// Converts a unicode code-point to UTF-8.
+static inline std::string codePointToUTF8(unsigned int cp) {
+  std::string result;
+
+  // based on description from http://en.wikipedia.org/wiki/UTF-8
+
+  if (cp <= 0x7f) {
+    result.resize(1);
+    result[0] = static_cast<char>(cp);
+  } else if (cp <= 0x7FF) {
+    result.resize(2);
+    result[1] = static_cast<char>(0x80 | (0x3f & cp));
+    result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
+  } else if (cp <= 0xFFFF) {
+    result.resize(3);
+    result[2] = static_cast<char>(0x80 | (0x3f & cp));
+    result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+    result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
+  } else if (cp <= 0x10FFFF) {
+    result.resize(4);
+    result[3] = static_cast<char>(0x80 | (0x3f & cp));
+    result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
+    result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
+    result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
+  }
+
+  return result;
+}
+
+/// Returns true if ch is a control character (in range [1,31]).
+static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
+
+enum {
+  /// Constant that specify the size of the buffer that must be passed to
+  /// uintToString.
+  uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
+};
+
+// Defines a char buffer for use with uintToString().
+typedef char UIntToStringBuffer[uintToStringBufferSize];
+
+/** Converts an unsigned integer to string.
+ * @param value Unsigned interger to convert to string
+ * @param current Input/Output string buffer.
+ *        Must have at least uintToStringBufferSize chars free.
+ */
+static inline void uintToString(LargestUInt value, char*& current) {
+  *--current = 0;
+  do {
+    *--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0'));
+    value /= 10;
+  } while (value != 0);
+}
+
+/** Change ',' to '.' everywhere in buffer.
+ *
+ * We had a sophisticated way, but it did not work in WinCE.
+ * @see https://github.com/open-source-parsers/jsoncpp/pull/9
+ */
+static inline void fixNumericLocale(char* begin, char* end) {
+  while (begin < end) {
+    if (*begin == ',') {
+      *begin = '.';
+    }
+    ++begin;
+  }
+}
+
+} // namespace Json {
+
+#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_tool.h
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_reader.cpp
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2011 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/assertions.h>
+#include <json/reader.h>
+#include <json/value.h>
+#include "json_tool.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <utility>
+#include <cstdio>
+#include <cassert>
+#include <cstring>
+#include <istream>
+#include <sstream>
+#include <memory>
+#include <set>
+#include <limits>
+
+#if defined(_MSC_VER)
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
+#define snprintf _snprintf
+#endif
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
+#define snprintf snprintf
+#elif __cplusplus >= 201103L
+#define snprintf std::snprintf
+#endif
+
+#if defined(__QNXNTO__)
+#define sscanf std::sscanf
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+// Disable warning about strdup being deprecated.
+#pragma warning(disable : 4996)
+#endif
+
+static int const stackLimit_g = 1000;
+static int       stackDepth_g = 0;  // see readValue()
+
+namespace Json {
+
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<CharReader> CharReaderPtr;
+#else
+typedef std::auto_ptr<CharReader>   CharReaderPtr;
+#endif
+
+// Implementation of class Features
+// ////////////////////////////////
+
+Features::Features()
+    : allowComments_(true), strictRoot_(false),
+      allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
+
+Features Features::all() { return Features(); }
+
+Features Features::strictMode() {
+  Features features;
+  features.allowComments_ = false;
+  features.strictRoot_ = true;
+  features.allowDroppedNullPlaceholders_ = false;
+  features.allowNumericKeys_ = false;
+  return features;
+}
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+static bool containsNewLine(Reader::Location begin, Reader::Location end) {
+  for (; begin < end; ++begin)
+    if (*begin == '\n' || *begin == '\r')
+      return true;
+  return false;
+}
+
+// Class Reader
+// //////////////////////////////////////////////////////////////////
+
+Reader::Reader()
+    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+      lastValue_(), commentsBefore_(), features_(Features::all()),
+      collectComments_() {}
+
+Reader::Reader(const Features& features)
+    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+      lastValue_(), commentsBefore_(), features_(features), collectComments_() {
+}
+
+bool
+Reader::parse(const std::string& document, Value& root, bool collectComments) {
+  document_ = document;
+  const char* begin = document_.c_str();
+  const char* end = begin + document_.length();
+  return parse(begin, end, root, collectComments);
+}
+
+bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
+  // std::istream_iterator<char> begin(sin);
+  // std::istream_iterator<char> end;
+  // Those would allow streamed input from a file, if parse() were a
+  // template function.
+
+  // Since std::string is reference-counted, this at least does not
+  // create an extra copy.
+  std::string doc;
+  std::getline(sin, doc, (char)EOF);
+  return parse(doc, root, collectComments);
+}
+
+bool Reader::parse(const char* beginDoc,
+                   const char* endDoc,
+                   Value& root,
+                   bool collectComments) {
+  if (!features_.allowComments_) {
+    collectComments = false;
+  }
+
+  begin_ = beginDoc;
+  end_ = endDoc;
+  collectComments_ = collectComments;
+  current_ = begin_;
+  lastValueEnd_ = 0;
+  lastValue_ = 0;
+  commentsBefore_ = "";
+  errors_.clear();
+  while (!nodes_.empty())
+    nodes_.pop();
+  nodes_.push(&root);
+
+  stackDepth_g = 0;  // Yes, this is bad coding, but options are limited.
+  bool successful = readValue();
+  Token token;
+  skipCommentTokens(token);
+  if (collectComments_ && !commentsBefore_.empty())
+    root.setComment(commentsBefore_, commentAfter);
+  if (features_.strictRoot_) {
+    if (!root.isArray() && !root.isObject()) {
+      // Set error location to start of doc, ideally should be first token found
+      // in doc
+      token.type_ = tokenError;
+      token.start_ = beginDoc;
+      token.end_ = endDoc;
+      addError(
+          "A valid JSON document must be either an array or an object value.",
+          token);
+      return false;
+    }
+  }
+  return successful;
+}
+
+bool Reader::readValue() {
+  // This is a non-reentrant way to support a stackLimit. Terrible!
+  // But this deprecated class has a security problem: Bad input can
+  // cause a seg-fault. This seems like a fair, binary-compatible way
+  // to prevent the problem.
+  if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
+  ++stackDepth_g;
+
+  Token token;
+  skipCommentTokens(token);
+  bool successful = true;
+
+  if (collectComments_ && !commentsBefore_.empty()) {
+    currentValue().setComment(commentsBefore_, commentBefore);
+    commentsBefore_ = "";
+  }
+
+  switch (token.type_) {
+  case tokenObjectBegin:
+    successful = readObject(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenArrayBegin:
+    successful = readArray(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenNumber:
+    successful = decodeNumber(token);
+    break;
+  case tokenString:
+    successful = decodeString(token);
+    break;
+  case tokenTrue:
+    {
+    Value v(true);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenFalse:
+    {
+    Value v(false);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNull:
+    {
+    Value v;
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenArraySeparator:
+  case tokenObjectEnd:
+  case tokenArrayEnd:
+    if (features_.allowDroppedNullPlaceholders_) {
+      // "Un-read" the current token and mark the current value as a null
+      // token.
+      current_--;
+      Value v;
+      currentValue().swapPayload(v);
+      currentValue().setOffsetStart(current_ - begin_ - 1);
+      currentValue().setOffsetLimit(current_ - begin_);
+      break;
+    } // Else, fall through...
+  default:
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    return addError("Syntax error: value, object or array expected.", token);
+  }
+
+  if (collectComments_) {
+    lastValueEnd_ = current_;
+    lastValue_ = &currentValue();
+  }
+
+  --stackDepth_g;
+  return successful;
+}
+
+void Reader::skipCommentTokens(Token& token) {
+  if (features_.allowComments_) {
+    do {
+      readToken(token);
+    } while (token.type_ == tokenComment);
+  } else {
+    readToken(token);
+  }
+}
+
+bool Reader::readToken(Token& token) {
+  skipSpaces();
+  token.start_ = current_;
+  Char c = getNextChar();
+  bool ok = true;
+  switch (c) {
+  case '{':
+    token.type_ = tokenObjectBegin;
+    break;
+  case '}':
+    token.type_ = tokenObjectEnd;
+    break;
+  case '[':
+    token.type_ = tokenArrayBegin;
+    break;
+  case ']':
+    token.type_ = tokenArrayEnd;
+    break;
+  case '"':
+    token.type_ = tokenString;
+    ok = readString();
+    break;
+  case '/':
+    token.type_ = tokenComment;
+    ok = readComment();
+    break;
+  case '0':
+  case '1':
+  case '2':
+  case '3':
+  case '4':
+  case '5':
+  case '6':
+  case '7':
+  case '8':
+  case '9':
+  case '-':
+    token.type_ = tokenNumber;
+    readNumber();
+    break;
+  case 't':
+    token.type_ = tokenTrue;
+    ok = match("rue", 3);
+    break;
+  case 'f':
+    token.type_ = tokenFalse;
+    ok = match("alse", 4);
+    break;
+  case 'n':
+    token.type_ = tokenNull;
+    ok = match("ull", 3);
+    break;
+  case ',':
+    token.type_ = tokenArraySeparator;
+    break;
+  case ':':
+    token.type_ = tokenMemberSeparator;
+    break;
+  case 0:
+    token.type_ = tokenEndOfStream;
+    break;
+  default:
+    ok = false;
+    break;
+  }
+  if (!ok)
+    token.type_ = tokenError;
+  token.end_ = current_;
+  return true;
+}
+
+void Reader::skipSpaces() {
+  while (current_ != end_) {
+    Char c = *current_;
+    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+      ++current_;
+    else
+      break;
+  }
+}
+
+bool Reader::match(Location pattern, int patternLength) {
+  if (end_ - current_ < patternLength)
+    return false;
+  int index = patternLength;
+  while (index--)
+    if (current_[index] != pattern[index])
+      return false;
+  current_ += patternLength;
+  return true;
+}
+
+bool Reader::readComment() {
+  Location commentBegin = current_ - 1;
+  Char c = getNextChar();
+  bool successful = false;
+  if (c == '*')
+    successful = readCStyleComment();
+  else if (c == '/')
+    successful = readCppStyleComment();
+  if (!successful)
+    return false;
+
+  if (collectComments_) {
+    CommentPlacement placement = commentBefore;
+    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+      if (c != '*' || !containsNewLine(commentBegin, current_))
+        placement = commentAfterOnSameLine;
+    }
+
+    addComment(commentBegin, current_, placement);
+  }
+  return true;
+}
+
+static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
+  std::string normalized;
+  normalized.reserve(end - begin);
+  Reader::Location current = begin;
+  while (current != end) {
+    char c = *current++;
+    if (c == '\r') {
+      if (current != end && *current == '\n')
+         // convert dos EOL
+         ++current;
+      // convert Mac EOL
+      normalized += '\n';
+    } else {
+      normalized += c;
+    }
+  }
+  return normalized;
+}
+
+void
+Reader::addComment(Location begin, Location end, CommentPlacement placement) {
+  assert(collectComments_);
+  const std::string& normalized = normalizeEOL(begin, end);
+  if (placement == commentAfterOnSameLine) {
+    assert(lastValue_ != 0);
+    lastValue_->setComment(normalized, placement);
+  } else {
+    commentsBefore_ += normalized;
+  }
+}
+
+bool Reader::readCStyleComment() {
+  while (current_ != end_) {
+    Char c = getNextChar();
+    if (c == '*' && *current_ == '/')
+      break;
+  }
+  return getNextChar() == '/';
+}
+
+bool Reader::readCppStyleComment() {
+  while (current_ != end_) {
+    Char c = getNextChar();
+    if (c == '\n')
+      break;
+    if (c == '\r') {
+      // Consume DOS EOL. It will be normalized in addComment.
+      if (current_ != end_ && *current_ == '\n')
+        getNextChar();
+      // Break on Moc OS 9 EOL.
+      break;
+    }
+  }
+  return true;
+}
+
+void Reader::readNumber() {
+  const char *p = current_;
+  char c = '0'; // stopgap for already consumed character
+  // integral part
+  while (c >= '0' && c <= '9')
+    c = (current_ = p) < end_ ? *p++ : 0;
+  // fractional part
+  if (c == '.') {
+    c = (current_ = p) < end_ ? *p++ : 0;
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : 0;
+  }
+  // exponential part
+  if (c == 'e' || c == 'E') {
+    c = (current_ = p) < end_ ? *p++ : 0;
+    if (c == '+' || c == '-')
+      c = (current_ = p) < end_ ? *p++ : 0;
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : 0;
+  }
+}
+
+bool Reader::readString() {
+  Char c = 0;
+  while (current_ != end_) {
+    c = getNextChar();
+    if (c == '\\')
+      getNextChar();
+    else if (c == '"')
+      break;
+  }
+  return c == '"';
+}
+
+bool Reader::readObject(Token& tokenStart) {
+  Token tokenName;
+  std::string name;
+  Value init(objectValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  while (readToken(tokenName)) {
+    bool initialTokenOk = true;
+    while (tokenName.type_ == tokenComment && initialTokenOk)
+      initialTokenOk = readToken(tokenName);
+    if (!initialTokenOk)
+      break;
+    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+      return true;
+    name = "";
+    if (tokenName.type_ == tokenString) {
+      if (!decodeString(tokenName, name))
+        return recoverFromError(tokenObjectEnd);
+    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+      Value numberName;
+      if (!decodeNumber(tokenName, numberName))
+        return recoverFromError(tokenObjectEnd);
+      name = numberName.asString();
+    } else {
+      break;
+    }
+
+    Token colon;
+    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+      return addErrorAndRecover(
+          "Missing ':' after object member name", colon, tokenObjectEnd);
+    }
+    Value& value = currentValue()[name];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenObjectEnd);
+
+    Token comma;
+    if (!readToken(comma) ||
+        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
+         comma.type_ != tokenComment)) {
+      return addErrorAndRecover(
+          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+    }
+    bool finalizeTokenOk = true;
+    while (comma.type_ == tokenComment && finalizeTokenOk)
+      finalizeTokenOk = readToken(comma);
+    if (comma.type_ == tokenObjectEnd)
+      return true;
+  }
+  return addErrorAndRecover(
+      "Missing '}' or object member name", tokenName, tokenObjectEnd);
+}
+
+bool Reader::readArray(Token& tokenStart) {
+  Value init(arrayValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  skipSpaces();
+  if (*current_ == ']') // empty array
+  {
+    Token endArray;
+    readToken(endArray);
+    return true;
+  }
+  int index = 0;
+  for (;;) {
+    Value& value = currentValue()[index++];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenArrayEnd);
+
+    Token token;
+    // Accept Comment after last item in the array.
+    ok = readToken(token);
+    while (token.type_ == tokenComment && ok) {
+      ok = readToken(token);
+    }
+    bool badTokenType =
+        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+    if (!ok || badTokenType) {
+      return addErrorAndRecover(
+          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+    }
+    if (token.type_ == tokenArrayEnd)
+      break;
+  }
+  return true;
+}
+
+bool Reader::decodeNumber(Token& token) {
+  Value decoded;
+  if (!decodeNumber(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool Reader::decodeNumber(Token& token, Value& decoded) {
+  // Attempts to parse the number as an integer. If the number is
+  // larger than the maximum supported value of an integer then
+  // we decode the number as a double.
+  Location current = token.start_;
+  bool isNegative = *current == '-';
+  if (isNegative)
+    ++current;
+  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+  Value::LargestUInt maxIntegerValue =
+      isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
+                 : Value::maxLargestUInt;
+  Value::LargestUInt threshold = maxIntegerValue / 10;
+  Value::LargestUInt value = 0;
+  while (current < token.end_) {
+    Char c = *current++;
+    if (c < '0' || c > '9')
+      return decodeDouble(token, decoded);
+    Value::UInt digit(c - '0');
+    if (value >= threshold) {
+      // We've hit or exceeded the max value divided by 10 (rounded down). If
+      // a) we've only just touched the limit, b) this is the last digit, and
+      // c) it's small enough to fit in that rounding delta, we're okay.
+      // Otherwise treat this number as a double to avoid overflow.
+      if (value > threshold || current != token.end_ ||
+          digit > maxIntegerValue % 10) {
+        return decodeDouble(token, decoded);
+      }
+    }
+    value = value * 10 + digit;
+  }
+  if (isNegative && value == maxIntegerValue)
+    decoded = Value::minLargestInt;
+  else if (isNegative)
+    decoded = -Value::LargestInt(value);
+  else if (value <= Value::LargestUInt(Value::maxInt))
+    decoded = Value::LargestInt(value);
+  else
+    decoded = value;
+  return true;
+}
+
+bool Reader::decodeDouble(Token& token) {
+  Value decoded;
+  if (!decodeDouble(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool Reader::decodeDouble(Token& token, Value& decoded) {
+  double value = 0;
+  std::string buffer(token.start_, token.end_);
+  std::istringstream is(buffer);
+  if (!(is >> value))
+    return addError("'" + std::string(token.start_, token.end_) +
+                        "' is not a number.",
+                    token);
+  decoded = value;
+  return true;
+}
+
+bool Reader::decodeString(Token& token) {
+  std::string decoded_string;
+  if (!decodeString(token, decoded_string))
+    return false;
+  Value decoded(decoded_string);
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool Reader::decodeString(Token& token, std::string& decoded) {
+  decoded.reserve(token.end_ - token.start_ - 2);
+  Location current = token.start_ + 1; // skip '"'
+  Location end = token.end_ - 1;       // do not include '"'
+  while (current != end) {
+    Char c = *current++;
+    if (c == '"')
+      break;
+    else if (c == '\\') {
+      if (current == end)
+        return addError("Empty escape sequence in string", token, current);
+      Char escape = *current++;
+      switch (escape) {
+      case '"':
+        decoded += '"';
+        break;
+      case '/':
+        decoded += '/';
+        break;
+      case '\\':
+        decoded += '\\';
+        break;
+      case 'b':
+        decoded += '\b';
+        break;
+      case 'f':
+        decoded += '\f';
+        break;
+      case 'n':
+        decoded += '\n';
+        break;
+      case 'r':
+        decoded += '\r';
+        break;
+      case 't':
+        decoded += '\t';
+        break;
+      case 'u': {
+        unsigned int unicode;
+        if (!decodeUnicodeCodePoint(token, current, end, unicode))
+          return false;
+        decoded += codePointToUTF8(unicode);
+      } break;
+      default:
+        return addError("Bad escape sequence in string", token, current);
+      }
+    } else {
+      decoded += c;
+    }
+  }
+  return true;
+}
+
+bool Reader::decodeUnicodeCodePoint(Token& token,
+                                    Location& current,
+                                    Location end,
+                                    unsigned int& unicode) {
+
+  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+    return false;
+  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+    // surrogate pairs
+    if (end - current < 6)
+      return addError(
+          "additional six characters expected to parse unicode surrogate pair.",
+          token,
+          current);
+    unsigned int surrogatePair;
+    if (*(current++) == '\\' && *(current++) == 'u') {
+      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+      } else
+        return false;
+    } else
+      return addError("expecting another \\u token to begin the second half of "
+                      "a unicode surrogate pair",
+                      token,
+                      current);
+  }
+  return true;
+}
+
+bool Reader::decodeUnicodeEscapeSequence(Token& token,
+                                         Location& current,
+                                         Location end,
+                                         unsigned int& unicode) {
+  if (end - current < 4)
+    return addError(
+        "Bad unicode escape sequence in string: four digits expected.",
+        token,
+        current);
+  unicode = 0;
+  for (int index = 0; index < 4; ++index) {
+    Char c = *current++;
+    unicode *= 16;
+    if (c >= '0' && c <= '9')
+      unicode += c - '0';
+    else if (c >= 'a' && c <= 'f')
+      unicode += c - 'a' + 10;
+    else if (c >= 'A' && c <= 'F')
+      unicode += c - 'A' + 10;
+    else
+      return addError(
+          "Bad unicode escape sequence in string: hexadecimal digit expected.",
+          token,
+          current);
+  }
+  return true;
+}
+
+bool
+Reader::addError(const std::string& message, Token& token, Location extra) {
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = extra;
+  errors_.push_back(info);
+  return false;
+}
+
+bool Reader::recoverFromError(TokenType skipUntilToken) {
+  int errorCount = int(errors_.size());
+  Token skip;
+  for (;;) {
+    if (!readToken(skip))
+      errors_.resize(errorCount); // discard errors caused by recovery
+    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+      break;
+  }
+  errors_.resize(errorCount);
+  return false;
+}
+
+bool Reader::addErrorAndRecover(const std::string& message,
+                                Token& token,
+                                TokenType skipUntilToken) {
+  addError(message, token);
+  return recoverFromError(skipUntilToken);
+}
+
+Value& Reader::currentValue() { return *(nodes_.top()); }
+
+Reader::Char Reader::getNextChar() {
+  if (current_ == end_)
+    return 0;
+  return *current_++;
+}
+
+void Reader::getLocationLineAndColumn(Location location,
+                                      int& line,
+                                      int& column) const {
+  Location current = begin_;
+  Location lastLineStart = current;
+  line = 0;
+  while (current < location && current != end_) {
+    Char c = *current++;
+    if (c == '\r') {
+      if (*current == '\n')
+        ++current;
+      lastLineStart = current;
+      ++line;
+    } else if (c == '\n') {
+      lastLineStart = current;
+      ++line;
+    }
+  }
+  // column & line start at 1
+  column = int(location - lastLineStart) + 1;
+  ++line;
+}
+
+std::string Reader::getLocationLineAndColumn(Location location) const {
+  int line, column;
+  getLocationLineAndColumn(location, line, column);
+  char buffer[18 + 16 + 16 + 1];
+  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+  return buffer;
+}
+
+std::string Reader::getLocationSnippet(Location location) const {
+	std::string snippet = "";
+	std::istringstream docStream(document_);
+	int lin, col;
+	getLocationLineAndColumn(location, lin, col);
+	std::string line;
+	for (int i=1; i<lin+2 && std::getline(docStream, line); i++)
+	{
+		if (lin-i < 2)
+		{
+			snippet += "  " + std::to_string(i) + ": " + line + "\n";
+		}
+	}
+	return snippet;
+}
+
+// Deprecated. Preserved for backward compatibility
+std::string Reader::getFormatedErrorMessages() const {
+  return getFormattedErrorMessages();
+}
+
+std::string Reader::getFormattedErrorMessages() const {
+  std::string formattedMessage;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    formattedMessage +=
+        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+	formattedMessage += getLocationSnippet(error.token_.start_) + "\n";
+    formattedMessage += "  " + error.message_ + "\n";
+    if (error.extra_)
+      formattedMessage +=
+          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+  }
+  return formattedMessage;
+}
+
+std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
+  std::vector<Reader::StructuredError> allErrors;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    Reader::StructuredError structured;
+    structured.offset_start = error.token_.start_ - begin_;
+    structured.offset_limit = error.token_.end_ - begin_;
+    structured.message = error.message_;
+    allErrors.push_back(structured);
+  }
+  return allErrors;
+}
+
+bool Reader::pushError(const Value& value, const std::string& message) {
+  size_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = end_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = 0;
+  errors_.push_back(info);
+  return true;
+}
+
+bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
+  size_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length
+    || extra.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = begin_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = begin_ + extra.getOffsetStart();
+  errors_.push_back(info);
+  return true;
+}
+
+bool Reader::good() const {
+  return !errors_.size();
+}
+
+// exact copy of Features
+class OurFeatures {
+public:
+  static OurFeatures all();
+  bool allowComments_;
+  bool strictRoot_;
+  bool allowDroppedNullPlaceholders_;
+  bool allowNumericKeys_;
+  bool allowSingleQuotes_;
+  bool failIfExtra_;
+  bool rejectDupKeys_;
+  bool allowSpecialFloats_;
+  int stackLimit_;
+};  // OurFeatures
+
+// exact copy of Implementation of class Features
+// ////////////////////////////////
+
+OurFeatures OurFeatures::all() { return OurFeatures(); }
+
+// Implementation of class Reader
+// ////////////////////////////////
+
+// exact copy of Reader, renamed to OurReader
+class OurReader {
+public:
+  typedef char Char;
+  typedef const Char* Location;
+  struct StructuredError {
+    size_t offset_start;
+    size_t offset_limit;
+    std::string message;
+  };
+
+  OurReader(OurFeatures const& features);
+  bool parse(const char* beginDoc,
+             const char* endDoc,
+             Value& root,
+             bool collectComments = true);
+  std::string getFormattedErrorMessages() const;
+  std::vector<StructuredError> getStructuredErrors() const;
+  bool pushError(const Value& value, const std::string& message);
+  bool pushError(const Value& value, const std::string& message, const Value& extra);
+  bool good() const;
+
+private:
+  OurReader(OurReader const&);  // no impl
+  void operator=(OurReader const&);  // no impl
+
+  enum TokenType {
+    tokenEndOfStream = 0,
+    tokenObjectBegin,
+    tokenObjectEnd,
+    tokenArrayBegin,
+    tokenArrayEnd,
+    tokenString,
+    tokenNumber,
+    tokenTrue,
+    tokenFalse,
+    tokenNull,
+    tokenNaN,
+    tokenPosInf,
+    tokenNegInf,
+    tokenArraySeparator,
+    tokenMemberSeparator,
+    tokenComment,
+    tokenError
+  };
+
+  class Token {
+  public:
+    TokenType type_;
+    Location start_;
+    Location end_;
+  };
+
+  class ErrorInfo {
+  public:
+    Token token_;
+    std::string message_;
+    Location extra_;
+  };
+
+  typedef std::deque<ErrorInfo> Errors;
+
+  bool readToken(Token& token);
+  void skipSpaces();
+  bool match(Location pattern, int patternLength);
+  bool readComment();
+  bool readCStyleComment();
+  bool readCppStyleComment();
+  bool readString();
+  bool readStringSingleQuote();
+  bool readNumber(bool checkInf);
+  bool readValue();
+  bool readObject(Token& token);
+  bool readArray(Token& token);
+  bool decodeNumber(Token& token);
+  bool decodeNumber(Token& token, Value& decoded);
+  bool decodeString(Token& token);
+  bool decodeString(Token& token, std::string& decoded);
+  bool decodeDouble(Token& token);
+  bool decodeDouble(Token& token, Value& decoded);
+  bool decodeUnicodeCodePoint(Token& token,
+                              Location& current,
+                              Location end,
+                              unsigned int& unicode);
+  bool decodeUnicodeEscapeSequence(Token& token,
+                                   Location& current,
+                                   Location end,
+                                   unsigned int& unicode);
+  bool addError(const std::string& message, Token& token, Location extra = 0);
+  bool recoverFromError(TokenType skipUntilToken);
+  bool addErrorAndRecover(const std::string& message,
+                          Token& token,
+                          TokenType skipUntilToken);
+  void skipUntilSpace();
+  Value& currentValue();
+  Char getNextChar();
+  void
+  getLocationLineAndColumn(Location location, int& line, int& column) const;
+  std::string getLocationLineAndColumn(Location location) const;
+  void addComment(Location begin, Location end, CommentPlacement placement);
+  void skipCommentTokens(Token& token);
+
+  typedef std::stack<Value*> Nodes;
+  Nodes nodes_;
+  Errors errors_;
+  std::string document_;
+  Location begin_;
+  Location end_;
+  Location current_;
+  Location lastValueEnd_;
+  Value* lastValue_;
+  std::string commentsBefore_;
+  int stackDepth_;
+
+  OurFeatures const features_;
+  bool collectComments_;
+};  // OurReader
+
+// complete copy of Read impl, for OurReader
+
+OurReader::OurReader(OurFeatures const& features)
+    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
+      lastValue_(), commentsBefore_(),
+      stackDepth_(0),
+      features_(features), collectComments_() {
+}
+
+bool OurReader::parse(const char* beginDoc,
+                   const char* endDoc,
+                   Value& root,
+                   bool collectComments) {
+  if (!features_.allowComments_) {
+    collectComments = false;
+  }
+
+  begin_ = beginDoc;
+  end_ = endDoc;
+  collectComments_ = collectComments;
+  current_ = begin_;
+  lastValueEnd_ = 0;
+  lastValue_ = 0;
+  commentsBefore_ = "";
+  errors_.clear();
+  while (!nodes_.empty())
+    nodes_.pop();
+  nodes_.push(&root);
+
+  stackDepth_ = 0;
+  bool successful = readValue();
+  Token token;
+  skipCommentTokens(token);
+  if (features_.failIfExtra_) {
+    if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
+      addError("Extra non-whitespace after JSON value.", token);
+      return false;
+    }
+  }
+  if (collectComments_ && !commentsBefore_.empty())
+    root.setComment(commentsBefore_, commentAfter);
+  if (features_.strictRoot_) {
+    if (!root.isArray() && !root.isObject()) {
+      // Set error location to start of doc, ideally should be first token found
+      // in doc
+      token.type_ = tokenError;
+      token.start_ = beginDoc;
+      token.end_ = endDoc;
+      addError(
+          "A valid JSON document must be either an array or an object value.",
+          token);
+      return false;
+    }
+  }
+  return successful;
+}
+
+bool OurReader::readValue() {
+  if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
+  ++stackDepth_;
+  Token token;
+  skipCommentTokens(token);
+  bool successful = true;
+
+  if (collectComments_ && !commentsBefore_.empty()) {
+    currentValue().setComment(commentsBefore_, commentBefore);
+    commentsBefore_ = "";
+  }
+
+  switch (token.type_) {
+  case tokenObjectBegin:
+    successful = readObject(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenArrayBegin:
+    successful = readArray(token);
+    currentValue().setOffsetLimit(current_ - begin_);
+    break;
+  case tokenNumber:
+    successful = decodeNumber(token);
+    break;
+  case tokenString:
+    successful = decodeString(token);
+    break;
+  case tokenTrue:
+    {
+    Value v(true);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenFalse:
+    {
+    Value v(false);
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNull:
+    {
+    Value v;
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNaN:
+    {
+    Value v(std::numeric_limits<double>::quiet_NaN());
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenPosInf:
+    {
+    Value v(std::numeric_limits<double>::infinity());
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenNegInf:
+    {
+    Value v(-std::numeric_limits<double>::infinity());
+    currentValue().swapPayload(v);
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    }
+    break;
+  case tokenArraySeparator:
+  case tokenObjectEnd:
+  case tokenArrayEnd:
+    if (features_.allowDroppedNullPlaceholders_) {
+      // "Un-read" the current token and mark the current value as a null
+      // token.
+      current_--;
+      Value v;
+      currentValue().swapPayload(v);
+      currentValue().setOffsetStart(current_ - begin_ - 1);
+      currentValue().setOffsetLimit(current_ - begin_);
+      break;
+    } // else, fall through ...
+  default:
+    currentValue().setOffsetStart(token.start_ - begin_);
+    currentValue().setOffsetLimit(token.end_ - begin_);
+    return addError("Syntax error: value, object or array expected.", token);
+  }
+
+  if (collectComments_) {
+    lastValueEnd_ = current_;
+    lastValue_ = &currentValue();
+  }
+
+  --stackDepth_;
+  return successful;
+}
+
+void OurReader::skipCommentTokens(Token& token) {
+  if (features_.allowComments_) {
+    do {
+      readToken(token);
+    } while (token.type_ == tokenComment);
+  } else {
+    readToken(token);
+  }
+}
+
+bool OurReader::readToken(Token& token) {
+  skipSpaces();
+  token.start_ = current_;
+  Char c = getNextChar();
+  bool ok = true;
+  switch (c) {
+  case '{':
+    token.type_ = tokenObjectBegin;
+    break;
+  case '}':
+    token.type_ = tokenObjectEnd;
+    break;
+  case '[':
+    token.type_ = tokenArrayBegin;
+    break;
+  case ']':
+    token.type_ = tokenArrayEnd;
+    break;
+  case '"':
+    token.type_ = tokenString;
+    ok = readString();
+    break;
+  case '\'':
+    if (features_.allowSingleQuotes_) {
+    token.type_ = tokenString;
+    ok = readStringSingleQuote();
+    break;
+    } // else continue
+  case '/':
+    token.type_ = tokenComment;
+    ok = readComment();
+    break;
+  case '0':
+  case '1':
+  case '2':
+  case '3':
+  case '4':
+  case '5':
+  case '6':
+  case '7':
+  case '8':
+  case '9':
+    token.type_ = tokenNumber;
+    readNumber(false);
+    break;
+  case '-':
+    if (readNumber(true)) {
+      token.type_ = tokenNumber;
+    } else {
+      token.type_ = tokenNegInf;
+      ok = features_.allowSpecialFloats_ && match("nfinity", 7);
+    }
+    break;
+  case 't':
+    token.type_ = tokenTrue;
+    ok = match("rue", 3);
+    break;
+  case 'f':
+    token.type_ = tokenFalse;
+    ok = match("alse", 4);
+    break;
+  case 'n':
+    token.type_ = tokenNull;
+    ok = match("ull", 3);
+    break;
+  case 'N':
+    if (features_.allowSpecialFloats_) {
+      token.type_ = tokenNaN;
+      ok = match("aN", 2);
+    } else {
+      ok = false;
+    }
+    break;
+  case 'I':
+    if (features_.allowSpecialFloats_) {
+      token.type_ = tokenPosInf;
+      ok = match("nfinity", 7);
+    } else {
+      ok = false;
+    }
+    break;
+  case ',':
+    token.type_ = tokenArraySeparator;
+    break;
+  case ':':
+    token.type_ = tokenMemberSeparator;
+    break;
+  case 0:
+    token.type_ = tokenEndOfStream;
+    break;
+  default:
+    ok = false;
+    break;
+  }
+  if (!ok)
+    token.type_ = tokenError;
+  token.end_ = current_;
+  return true;
+}
+
+void OurReader::skipSpaces() {
+  while (current_ != end_) {
+    Char c = *current_;
+    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+      ++current_;
+    else
+      break;
+  }
+}
+
+bool OurReader::match(Location pattern, int patternLength) {
+  if (end_ - current_ < patternLength)
+    return false;
+  int index = patternLength;
+  while (index--)
+    if (current_[index] != pattern[index])
+      return false;
+  current_ += patternLength;
+  return true;
+}
+
+bool OurReader::readComment() {
+  Location commentBegin = current_ - 1;
+  Char c = getNextChar();
+  bool successful = false;
+  if (c == '*')
+    successful = readCStyleComment();
+  else if (c == '/')
+    successful = readCppStyleComment();
+  if (!successful)
+    return false;
+
+  if (collectComments_) {
+    CommentPlacement placement = commentBefore;
+    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
+      if (c != '*' || !containsNewLine(commentBegin, current_))
+        placement = commentAfterOnSameLine;
+    }
+
+    addComment(commentBegin, current_, placement);
+  }
+  return true;
+}
+
+void
+OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
+  assert(collectComments_);
+  const std::string& normalized = normalizeEOL(begin, end);
+  if (placement == commentAfterOnSameLine) {
+    assert(lastValue_ != 0);
+    lastValue_->setComment(normalized, placement);
+  } else {
+    commentsBefore_ += normalized;
+  }
+}
+
+bool OurReader::readCStyleComment() {
+  while (current_ != end_) {
+    Char c = getNextChar();
+    if (c == '*' && *current_ == '/')
+      break;
+  }
+  return getNextChar() == '/';
+}
+
+bool OurReader::readCppStyleComment() {
+  while (current_ != end_) {
+    Char c = getNextChar();
+    if (c == '\n')
+      break;
+    if (c == '\r') {
+      // Consume DOS EOL. It will be normalized in addComment.
+      if (current_ != end_ && *current_ == '\n')
+        getNextChar();
+      // Break on Moc OS 9 EOL.
+      break;
+    }
+  }
+  return true;
+}
+
+bool OurReader::readNumber(bool checkInf) {
+  const char *p = current_;
+  if (checkInf && p != end_ && *p == 'I') {
+    current_ = ++p;
+    return false;
+  }
+  char c = '0'; // stopgap for already consumed character
+  // integral part
+  while (c >= '0' && c <= '9')
+    c = (current_ = p) < end_ ? *p++ : 0;
+  // fractional part
+  if (c == '.') {
+    c = (current_ = p) < end_ ? *p++ : 0;
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : 0;
+  }
+  // exponential part
+  if (c == 'e' || c == 'E') {
+    c = (current_ = p) < end_ ? *p++ : 0;
+    if (c == '+' || c == '-')
+      c = (current_ = p) < end_ ? *p++ : 0;
+    while (c >= '0' && c <= '9')
+      c = (current_ = p) < end_ ? *p++ : 0;
+  }
+  return true;
+}
+bool OurReader::readString() {
+  Char c = 0;
+  while (current_ != end_) {
+    c = getNextChar();
+    if (c == '\\')
+      getNextChar();
+    else if (c == '"')
+      break;
+  }
+  return c == '"';
+}
+
+
+bool OurReader::readStringSingleQuote() {
+  Char c = 0;
+  while (current_ != end_) {
+    c = getNextChar();
+    if (c == '\\')
+      getNextChar();
+    else if (c == '\'')
+      break;
+  }
+  return c == '\'';
+}
+
+bool OurReader::readObject(Token& tokenStart) {
+  Token tokenName;
+  std::string name;
+  Value init(objectValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  while (readToken(tokenName)) {
+    bool initialTokenOk = true;
+    while (tokenName.type_ == tokenComment && initialTokenOk)
+      initialTokenOk = readToken(tokenName);
+    if (!initialTokenOk)
+      break;
+    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
+      return true;
+    name = "";
+    if (tokenName.type_ == tokenString) {
+      if (!decodeString(tokenName, name))
+        return recoverFromError(tokenObjectEnd);
+    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
+      Value numberName;
+      if (!decodeNumber(tokenName, numberName))
+        return recoverFromError(tokenObjectEnd);
+      name = numberName.asString();
+    } else {
+      break;
+    }
+
+    Token colon;
+    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
+      return addErrorAndRecover(
+          "Missing ':' after object member name", colon, tokenObjectEnd);
+    }
+    if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
+    if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
+      std::string msg = "Duplicate key: '" + name + "'";
+      return addErrorAndRecover(
+          msg, tokenName, tokenObjectEnd);
+    }
+    Value& value = currentValue()[name];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenObjectEnd);
+
+    Token comma;
+    if (!readToken(comma) ||
+        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
+         comma.type_ != tokenComment)) {
+      return addErrorAndRecover(
+          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
+    }
+    bool finalizeTokenOk = true;
+    while (comma.type_ == tokenComment && finalizeTokenOk)
+      finalizeTokenOk = readToken(comma);
+    if (comma.type_ == tokenObjectEnd)
+      return true;
+  }
+  return addErrorAndRecover(
+      "Missing '}' or object member name", tokenName, tokenObjectEnd);
+}
+
+bool OurReader::readArray(Token& tokenStart) {
+  Value init(arrayValue);
+  currentValue().swapPayload(init);
+  currentValue().setOffsetStart(tokenStart.start_ - begin_);
+  skipSpaces();
+  if (*current_ == ']') // empty array
+  {
+    Token endArray;
+    readToken(endArray);
+    return true;
+  }
+  int index = 0;
+  for (;;) {
+    Value& value = currentValue()[index++];
+    nodes_.push(&value);
+    bool ok = readValue();
+    nodes_.pop();
+    if (!ok) // error already set
+      return recoverFromError(tokenArrayEnd);
+
+    Token token;
+    // Accept Comment after last item in the array.
+    ok = readToken(token);
+    while (token.type_ == tokenComment && ok) {
+      ok = readToken(token);
+    }
+    bool badTokenType =
+        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
+    if (!ok || badTokenType) {
+      return addErrorAndRecover(
+          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
+    }
+    if (token.type_ == tokenArrayEnd)
+      break;
+  }
+  return true;
+}
+
+bool OurReader::decodeNumber(Token& token) {
+  Value decoded;
+  if (!decodeNumber(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool OurReader::decodeNumber(Token& token, Value& decoded) {
+  // Attempts to parse the number as an integer. If the number is
+  // larger than the maximum supported value of an integer then
+  // we decode the number as a double.
+  Location current = token.start_;
+  bool isNegative = *current == '-';
+  if (isNegative)
+    ++current;
+  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
+  Value::LargestUInt maxIntegerValue =
+      isNegative ? Value::LargestUInt(-Value::minLargestInt)
+                 : Value::maxLargestUInt;
+  Value::LargestUInt threshold = maxIntegerValue / 10;
+  Value::LargestUInt value = 0;
+  while (current < token.end_) {
+    Char c = *current++;
+    if (c < '0' || c > '9')
+      return decodeDouble(token, decoded);
+    Value::UInt digit(c - '0');
+    if (value >= threshold) {
+      // We've hit or exceeded the max value divided by 10 (rounded down). If
+      // a) we've only just touched the limit, b) this is the last digit, and
+      // c) it's small enough to fit in that rounding delta, we're okay.
+      // Otherwise treat this number as a double to avoid overflow.
+      if (value > threshold || current != token.end_ ||
+          digit > maxIntegerValue % 10) {
+        return decodeDouble(token, decoded);
+      }
+    }
+    value = value * 10 + digit;
+  }
+  if (isNegative)
+    decoded = -Value::LargestInt(value);
+  else if (value <= Value::LargestUInt(Value::maxInt))
+    decoded = Value::LargestInt(value);
+  else
+    decoded = value;
+  return true;
+}
+
+bool OurReader::decodeDouble(Token& token) {
+  Value decoded;
+  if (!decodeDouble(token, decoded))
+    return false;
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool OurReader::decodeDouble(Token& token, Value& decoded) {
+  double value = 0;
+  const int bufferSize = 32;
+  int count;
+  int length = int(token.end_ - token.start_);
+
+  // Sanity check to avoid buffer overflow exploits.
+  if (length < 0) {
+    return addError("Unable to parse token length", token);
+  }
+
+  // Avoid using a string constant for the format control string given to
+  // sscanf, as this can cause hard to debug crashes on OS X. See here for more
+  // info:
+  //
+  //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
+  char format[] = "%lf";
+
+  if (length <= bufferSize) {
+    Char buffer[bufferSize + 1];
+    memcpy(buffer, token.start_, length);
+    buffer[length] = 0;
+    count = sscanf(buffer, format, &value);
+  } else {
+    std::string buffer(token.start_, token.end_);
+    count = sscanf(buffer.c_str(), format, &value);
+  }
+
+  if (count != 1)
+    return addError("'" + std::string(token.start_, token.end_) +
+                        "' is not a number.",
+                    token);
+  decoded = value;
+  return true;
+}
+
+bool OurReader::decodeString(Token& token) {
+  std::string decoded_string;
+  if (!decodeString(token, decoded_string))
+    return false;
+  Value decoded(decoded_string);
+  currentValue().swapPayload(decoded);
+  currentValue().setOffsetStart(token.start_ - begin_);
+  currentValue().setOffsetLimit(token.end_ - begin_);
+  return true;
+}
+
+bool OurReader::decodeString(Token& token, std::string& decoded) {
+  decoded.reserve(token.end_ - token.start_ - 2);
+  Location current = token.start_ + 1; // skip '"'
+  Location end = token.end_ - 1;       // do not include '"'
+  while (current != end) {
+    Char c = *current++;
+    if (c == '"')
+      break;
+    else if (c == '\\') {
+      if (current == end)
+        return addError("Empty escape sequence in string", token, current);
+      Char escape = *current++;
+      switch (escape) {
+      case '"':
+        decoded += '"';
+        break;
+      case '/':
+        decoded += '/';
+        break;
+      case '\\':
+        decoded += '\\';
+        break;
+      case 'b':
+        decoded += '\b';
+        break;
+      case 'f':
+        decoded += '\f';
+        break;
+      case 'n':
+        decoded += '\n';
+        break;
+      case 'r':
+        decoded += '\r';
+        break;
+      case 't':
+        decoded += '\t';
+        break;
+      case 'u': {
+        unsigned int unicode;
+        if (!decodeUnicodeCodePoint(token, current, end, unicode))
+          return false;
+        decoded += codePointToUTF8(unicode);
+      } break;
+      default:
+        return addError("Bad escape sequence in string", token, current);
+      }
+    } else {
+      decoded += c;
+    }
+  }
+  return true;
+}
+
+bool OurReader::decodeUnicodeCodePoint(Token& token,
+                                    Location& current,
+                                    Location end,
+                                    unsigned int& unicode) {
+
+  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
+    return false;
+  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
+    // surrogate pairs
+    if (end - current < 6)
+      return addError(
+          "additional six characters expected to parse unicode surrogate pair.",
+          token,
+          current);
+    unsigned int surrogatePair;
+    if (*(current++) == '\\' && *(current++) == 'u') {
+      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
+        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
+      } else
+        return false;
+    } else
+      return addError("expecting another \\u token to begin the second half of "
+                      "a unicode surrogate pair",
+                      token,
+                      current);
+  }
+  return true;
+}
+
+bool OurReader::decodeUnicodeEscapeSequence(Token& token,
+                                         Location& current,
+                                         Location end,
+                                         unsigned int& unicode) {
+  if (end - current < 4)
+    return addError(
+        "Bad unicode escape sequence in string: four digits expected.",
+        token,
+        current);
+  unicode = 0;
+  for (int index = 0; index < 4; ++index) {
+    Char c = *current++;
+    unicode *= 16;
+    if (c >= '0' && c <= '9')
+      unicode += c - '0';
+    else if (c >= 'a' && c <= 'f')
+      unicode += c - 'a' + 10;
+    else if (c >= 'A' && c <= 'F')
+      unicode += c - 'A' + 10;
+    else
+      return addError(
+          "Bad unicode escape sequence in string: hexadecimal digit expected.",
+          token,
+          current);
+  }
+  return true;
+}
+
+bool
+OurReader::addError(const std::string& message, Token& token, Location extra) {
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = extra;
+  errors_.push_back(info);
+  return false;
+}
+
+bool OurReader::recoverFromError(TokenType skipUntilToken) {
+  int errorCount = int(errors_.size());
+  Token skip;
+  for (;;) {
+    if (!readToken(skip))
+      errors_.resize(errorCount); // discard errors caused by recovery
+    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
+      break;
+  }
+  errors_.resize(errorCount);
+  return false;
+}
+
+bool OurReader::addErrorAndRecover(const std::string& message,
+                                Token& token,
+                                TokenType skipUntilToken) {
+  addError(message, token);
+  return recoverFromError(skipUntilToken);
+}
+
+Value& OurReader::currentValue() { return *(nodes_.top()); }
+
+OurReader::Char OurReader::getNextChar() {
+  if (current_ == end_)
+    return 0;
+  return *current_++;
+}
+
+void OurReader::getLocationLineAndColumn(Location location,
+                                      int& line,
+                                      int& column) const {
+  Location current = begin_;
+  Location lastLineStart = current;
+  line = 0;
+  while (current < location && current != end_) {
+    Char c = *current++;
+    if (c == '\r') {
+      if (*current == '\n')
+        ++current;
+      lastLineStart = current;
+      ++line;
+    } else if (c == '\n') {
+      lastLineStart = current;
+      ++line;
+    }
+  }
+  // column & line start at 1
+  column = int(location - lastLineStart) + 1;
+  ++line;
+}
+
+std::string OurReader::getLocationLineAndColumn(Location location) const {
+  int line, column;
+  getLocationLineAndColumn(location, line, column);
+  char buffer[18 + 16 + 16 + 1];
+  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
+  return buffer;
+}
+
+std::string OurReader::getFormattedErrorMessages() const {
+  std::string formattedMessage;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    formattedMessage +=
+        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
+    formattedMessage += "  " + error.message_ + "\n";
+    if (error.extra_)
+      formattedMessage +=
+          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
+  }
+  return formattedMessage;
+}
+
+std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
+  std::vector<OurReader::StructuredError> allErrors;
+  for (Errors::const_iterator itError = errors_.begin();
+       itError != errors_.end();
+       ++itError) {
+    const ErrorInfo& error = *itError;
+    OurReader::StructuredError structured;
+    structured.offset_start = error.token_.start_ - begin_;
+    structured.offset_limit = error.token_.end_ - begin_;
+    structured.message = error.message_;
+    allErrors.push_back(structured);
+  }
+  return allErrors;
+}
+
+bool OurReader::pushError(const Value& value, const std::string& message) {
+  size_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = end_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = 0;
+  errors_.push_back(info);
+  return true;
+}
+
+bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) {
+  size_t length = end_ - begin_;
+  if(value.getOffsetStart() > length
+    || value.getOffsetLimit() > length
+    || extra.getOffsetLimit() > length)
+    return false;
+  Token token;
+  token.type_ = tokenError;
+  token.start_ = begin_ + value.getOffsetStart();
+  token.end_ = begin_ + value.getOffsetLimit();
+  ErrorInfo info;
+  info.token_ = token;
+  info.message_ = message;
+  info.extra_ = begin_ + extra.getOffsetStart();
+  errors_.push_back(info);
+  return true;
+}
+
+bool OurReader::good() const {
+  return !errors_.size();
+}
+
+
+class OurCharReader : public CharReader {
+  bool const collectComments_;
+  OurReader reader_;
+public:
+  OurCharReader(
+    bool collectComments,
+    OurFeatures const& features)
+  : collectComments_(collectComments)
+  , reader_(features)
+  {}
+  bool parse(
+      char const* beginDoc, char const* endDoc,
+      Value* root, std::string* errs) {
+    bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
+    if (errs) {
+      *errs = reader_.getFormattedErrorMessages();
+    }
+    return ok;
+  }
+};
+
+CharReaderBuilder::CharReaderBuilder()
+{
+  setDefaults(&settings_);
+}
+CharReaderBuilder::~CharReaderBuilder()
+{}
+CharReader* CharReaderBuilder::newCharReader() const
+{
+  bool collectComments = settings_["collectComments"].asBool();
+  OurFeatures features = OurFeatures::all();
+  features.allowComments_ = settings_["allowComments"].asBool();
+  features.strictRoot_ = settings_["strictRoot"].asBool();
+  features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
+  features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
+  features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
+  features.stackLimit_ = settings_["stackLimit"].asInt();
+  features.failIfExtra_ = settings_["failIfExtra"].asBool();
+  features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
+  features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
+  return new OurCharReader(collectComments, features);
+}
+static void getValidReaderKeys(std::set<std::string>* valid_keys)
+{
+  valid_keys->clear();
+  valid_keys->insert("collectComments");
+  valid_keys->insert("allowComments");
+  valid_keys->insert("strictRoot");
+  valid_keys->insert("allowDroppedNullPlaceholders");
+  valid_keys->insert("allowNumericKeys");
+  valid_keys->insert("allowSingleQuotes");
+  valid_keys->insert("stackLimit");
+  valid_keys->insert("failIfExtra");
+  valid_keys->insert("rejectDupKeys");
+  valid_keys->insert("allowSpecialFloats");
+}
+bool CharReaderBuilder::validate(Json::Value* invalid) const
+{
+  Json::Value my_invalid;
+  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
+  Json::Value& inv = *invalid;
+  std::set<std::string> valid_keys;
+  getValidReaderKeys(&valid_keys);
+  Value::Members keys = settings_.getMemberNames();
+  size_t n = keys.size();
+  for (size_t i = 0; i < n; ++i) {
+    std::string const& key = keys[i];
+    if (valid_keys.find(key) == valid_keys.end()) {
+      inv[key] = settings_[key];
+    }
+  }
+  return 0u == inv.size();
+}
+Value& CharReaderBuilder::operator[](std::string key)
+{
+  return settings_[key];
+}
+// static
+void CharReaderBuilder::strictMode(Json::Value* settings)
+{
+//! [CharReaderBuilderStrictMode]
+  (*settings)["allowComments"] = false;
+  (*settings)["strictRoot"] = true;
+  (*settings)["allowDroppedNullPlaceholders"] = false;
+  (*settings)["allowNumericKeys"] = false;
+  (*settings)["allowSingleQuotes"] = false;
+  (*settings)["stackLimit"] = 1000;
+  (*settings)["failIfExtra"] = true;
+  (*settings)["rejectDupKeys"] = true;
+  (*settings)["allowSpecialFloats"] = false;
+//! [CharReaderBuilderStrictMode]
+}
+// static
+void CharReaderBuilder::setDefaults(Json::Value* settings)
+{
+//! [CharReaderBuilderDefaults]
+  (*settings)["collectComments"] = true;
+  (*settings)["allowComments"] = true;
+  (*settings)["strictRoot"] = false;
+  (*settings)["allowDroppedNullPlaceholders"] = false;
+  (*settings)["allowNumericKeys"] = false;
+  (*settings)["allowSingleQuotes"] = false;
+  (*settings)["stackLimit"] = 1000;
+  (*settings)["failIfExtra"] = false;
+  (*settings)["rejectDupKeys"] = false;
+  (*settings)["allowSpecialFloats"] = false;
+//! [CharReaderBuilderDefaults]
+}
+
+//////////////////////////////////
+// global functions
+
+bool parseFromStream(
+    CharReader::Factory const& fact, std::istream& sin,
+    Value* root, std::string* errs)
+{
+  std::ostringstream ssin;
+  ssin << sin.rdbuf();
+  std::string doc = ssin.str();
+  char const* begin = doc.data();
+  char const* end = begin + doc.size();
+  // Note that we do not actually need a null-terminator.
+  CharReaderPtr const reader(fact.newCharReader());
+  return reader->parse(begin, end, root, errs);
+}
+
+std::istream& operator>>(std::istream& sin, Value& root) {
+  CharReaderBuilder b;
+  std::string errs;
+  bool ok = parseFromStream(b, sin, &root, &errs);
+  if (!ok) {
+    fprintf(stderr,
+            "Error from reader: %s",
+            errs.c_str());
+
+    throwRuntimeError(errs);
+  }
+  return sin;
+}
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_reader.cpp
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_valueiterator.inl
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2007-2010 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+// included by json_value.cpp
+
+namespace Json {
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIteratorBase
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIteratorBase::ValueIteratorBase()
+    : current_(), isNull_(true) {
+}
+
+ValueIteratorBase::ValueIteratorBase(
+    const Value::ObjectValues::iterator& current)
+    : current_(current), isNull_(false) {}
+
+Value& ValueIteratorBase::deref() const {
+  return current_->second;
+}
+
+void ValueIteratorBase::increment() {
+  ++current_;
+}
+
+void ValueIteratorBase::decrement() {
+  --current_;
+}
+
+ValueIteratorBase::difference_type
+ValueIteratorBase::computeDistance(const SelfType& other) const {
+#ifdef JSON_USE_CPPTL_SMALLMAP
+  return other.current_ - current_;
+#else
+  // Iterator for null value are initialized using the default
+  // constructor, which initialize current_ to the default
+  // std::map::iterator. As begin() and end() are two instance
+  // of the default std::map::iterator, they can not be compared.
+  // To allow this, we handle this comparison specifically.
+  if (isNull_ && other.isNull_) {
+    return 0;
+  }
+
+  // Usage of std::distance is not portable (does not compile with Sun Studio 12
+  // RogueWave STL,
+  // which is the one used by default).
+  // Using a portable hand-made version for non random iterator instead:
+  //   return difference_type( std::distance( current_, other.current_ ) );
+  difference_type myDistance = 0;
+  for (Value::ObjectValues::iterator it = current_; it != other.current_;
+       ++it) {
+    ++myDistance;
+  }
+  return myDistance;
+#endif
+}
+
+bool ValueIteratorBase::isEqual(const SelfType& other) const {
+  if (isNull_) {
+    return other.isNull_;
+  }
+  return current_ == other.current_;
+}
+
+void ValueIteratorBase::copy(const SelfType& other) {
+  current_ = other.current_;
+  isNull_ = other.isNull_;
+}
+
+Value ValueIteratorBase::key() const {
+  const Value::CZString czstring = (*current_).first;
+  if (czstring.data()) {
+    if (czstring.isStaticString())
+      return Value(StaticString(czstring.data()));
+    return Value(czstring.data(), czstring.data() + czstring.length());
+  }
+  return Value(czstring.index());
+}
+
+UInt ValueIteratorBase::index() const {
+  const Value::CZString czstring = (*current_).first;
+  if (!czstring.data())
+    return czstring.index();
+  return Value::UInt(-1);
+}
+
+std::string ValueIteratorBase::name() const {
+  char const* keey;
+  char const* end;
+  keey = memberName(&end);
+  if (!keey) return std::string();
+  return std::string(keey, end);
+}
+
+char const* ValueIteratorBase::memberName() const {
+  const char* cname = (*current_).first.data();
+  return cname ? cname : "";
+}
+
+char const* ValueIteratorBase::memberName(char const** end) const {
+  const char* cname = (*current_).first.data();
+  if (!cname) {
+    *end = NULL;
+    return NULL;
+  }
+  *end = cname + (*current_).first.length();
+  return cname;
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueConstIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueConstIterator::ValueConstIterator() {}
+
+ValueConstIterator::ValueConstIterator(
+    const Value::ObjectValues::iterator& current)
+    : ValueIteratorBase(current) {}
+
+ValueConstIterator::ValueConstIterator(ValueIterator const& other)
+    : ValueIteratorBase(other) {}
+
+ValueConstIterator& ValueConstIterator::
+operator=(const ValueIteratorBase& other) {
+  copy(other);
+  return *this;
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class ValueIterator
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+ValueIterator::ValueIterator() {}
+
+ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
+    : ValueIteratorBase(current) {}
+
+ValueIterator::ValueIterator(const ValueConstIterator& other)
+    : ValueIteratorBase(other) {
+  throwRuntimeError("ConstIterator to Iterator should never be allowed.");
+}
+
+ValueIterator::ValueIterator(const ValueIterator& other)
+    : ValueIteratorBase(other) {}
+
+ValueIterator& ValueIterator::operator=(const SelfType& other) {
+  copy(other);
+  return *this;
+}
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_valueiterator.inl
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_value.cpp
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2011 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/assertions.h>
+#include <json/value.h>
+#include <json/writer.h>
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <math.h>
+#include <sstream>
+#include <utility>
+#include <cstring>
+#include <cassert>
+#ifdef JSON_USE_CPPTL
+#include <cpptl/conststring.h>
+#endif
+#include <cstddef> // size_t
+#include <algorithm> // min()
+
+#define JSON_ASSERT_UNREACHABLE assert(false)
+
+/*
+-- Valve 1/7/16
+4702 unreachable code
+*/
+#pragma warning (push)
+#pragma warning (disable: 4702)
+
+namespace Json {
+
+// This is a walkaround to avoid the static initialization of Value::null.
+// kNull must be word-aligned to avoid crashing on ARM.  We use an alignment of
+// 8 (instead of 4) as a bit of future-proofing.
+#if defined(__ARMEL__)
+#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
+#else
+#define ALIGNAS(byte_alignment)
+#endif
+static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
+const unsigned char& kNullRef = kNull[0];
+const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
+const Value& Value::nullRef = null;
+
+const Int Value::minInt = Int(~(UInt(-1) / 2));
+const Int Value::maxInt = Int(UInt(-1) / 2);
+const UInt Value::maxUInt = UInt(-1);
+#if defined(JSON_HAS_INT64)
+const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
+const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
+const UInt64 Value::maxUInt64 = UInt64(-1);
+// The constant is hard-coded because some compiler have trouble
+// converting Value::maxUInt64 to a double correctly (AIX/xlC).
+// Assumes that UInt64 is a 64 bits integer.
+static const double maxUInt64AsDouble = 18446744073709551615.0;
+#endif // defined(JSON_HAS_INT64)
+const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
+const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
+const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
+
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+template <typename T, typename U>
+static inline bool InRange(double d, T min, U max) {
+  return d >= min && d <= max;
+}
+#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+static inline double integerToDouble(Json::UInt64 value) {
+  return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
+}
+
+template <typename T> static inline double integerToDouble(T value) {
+  return static_cast<double>(value);
+}
+
+template <typename T, typename U>
+static inline bool InRange(double d, T min, U max) {
+  return d >= integerToDouble(min) && d <= integerToDouble(max);
+}
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+
+/** Duplicates the specified string value.
+ * @param value Pointer to the string to duplicate. Must be zero-terminated if
+ *              length is "unknown".
+ * @param length Length of the value. if equals to unknown, then it will be
+ *               computed using strlen(value).
+ * @return Pointer on the duplicate instance of string.
+ */
+static inline char* duplicateStringValue(const char* value,
+                                         size_t length) {
+  // Avoid an integer overflow in the call to malloc below by limiting length
+  // to a sane value.
+  if (length >= (size_t)Value::maxInt)
+    length = Value::maxInt - 1;
+
+  char* newString = static_cast<char*>(malloc(length + 1));
+  if (newString == NULL) {
+    throwRuntimeError(
+        "in Json::Value::duplicateStringValue(): "
+        "Failed to allocate string value buffer");
+  }
+  memcpy(newString, value, length);
+  newString[length] = 0;
+  return newString;
+}
+
+/* Record the length as a prefix.
+ */
+static inline char* duplicateAndPrefixStringValue(
+    const char* value,
+    unsigned int length)
+{
+  // Avoid an integer overflow in the call to malloc below by limiting length
+  // to a sane value.
+  JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U,
+                      "in Json::Value::duplicateAndPrefixStringValue(): "
+                      "length too big for prefixing");
+  unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
+  char* newString = static_cast<char*>(malloc(actualLength));
+  if (newString == 0) {
+    throwRuntimeError(
+        "in Json::Value::duplicateAndPrefixStringValue(): "
+        "Failed to allocate string value buffer");
+  }
+  *reinterpret_cast<unsigned*>(newString) = length;
+  memcpy(newString + sizeof(unsigned), value, length);
+  newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
+  return newString;
+}
+inline static void decodePrefixedString(
+    bool isPrefixed, char const* prefixed,
+    unsigned* length, char const** value)
+{
+  if (!isPrefixed) {
+    *length = static_cast<unsigned>(strlen(prefixed));
+    *value = prefixed;
+  } else {
+    *length = *reinterpret_cast<unsigned const*>(prefixed);
+    *value = prefixed + sizeof(unsigned);
+  }
+}
+/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
+ */
+static inline void releaseStringValue(char* value) { free(value); }
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// ValueInternals...
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+#if !defined(JSON_IS_AMALGAMATION)
+
+#include "json_valueiterator.inl"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+
+namespace Json {
+
+Exception::Exception(std::string const& msg)
+  : msg_(msg)
+{}
+Exception::~Exception() throw()
+{}
+char const* Exception::what() const throw()
+{
+  return msg_.c_str();
+}
+RuntimeError::RuntimeError(std::string const& msg)
+  : Exception(msg)
+{}
+LogicError::LogicError(std::string const& msg)
+  : Exception(msg)
+{}
+void throwRuntimeError(std::string const& msg)
+{
+  throw RuntimeError(msg);
+}
+void throwLogicError(std::string const& msg)
+{
+  throw LogicError(msg);
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CommentInfo
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+Value::CommentInfo::CommentInfo() : comment_(0) {}
+
+Value::CommentInfo::~CommentInfo() {
+  if (comment_)
+    releaseStringValue(comment_);
+}
+
+void Value::CommentInfo::setComment(const char* text, size_t len) {
+  if (comment_) {
+    releaseStringValue(comment_);
+    comment_ = 0;
+  }
+  JSON_ASSERT(text != 0);
+  JSON_ASSERT_MESSAGE(
+      text[0] == '\0' || text[0] == '/',
+      "in Json::Value::setComment(): Comments must start with /");
+  // It seems that /**/ style comments are acceptable as well.
+  comment_ = duplicateStringValue(text, len);
+}
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::CZString
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+// Notes: policy_ indicates if the string was allocated when
+// a string is stored.
+
+Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
+
+Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
+    : cstr_(str) {
+  // allocate != duplicate
+  storage_.policy_ = allocate & 0x3;
+  storage_.length_ = ulength & 0x3FFFFFFF;
+}
+
+Value::CZString::CZString(const CZString& other)
+    : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0
+                ? duplicateStringValue(other.cstr_, other.storage_.length_)
+                : other.cstr_) {
+  storage_.policy_ = (other.cstr_
+                 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
+                     ? noDuplication : duplicate)
+                 : static_cast<DuplicationPolicy>(other.storage_.policy_));
+  storage_.length_ = other.storage_.length_;
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+Value::CZString::CZString(CZString&& other)
+  : cstr_(other.cstr_), index_(other.index_) {
+  other.cstr_ = nullptr;
+}
+#endif
+
+Value::CZString::~CZString() {
+  if (cstr_ && storage_.policy_ == duplicate)
+    releaseStringValue(const_cast<char*>(cstr_));
+}
+
+void Value::CZString::swap(CZString& other) {
+  std::swap(cstr_, other.cstr_);
+  std::swap(index_, other.index_);
+}
+
+Value::CZString& Value::CZString::operator=(CZString other) {
+  swap(other);
+  return *this;
+}
+
+bool Value::CZString::operator<(const CZString& other) const {
+  if (!cstr_) return index_ < other.index_;
+  //return strcmp(cstr_, other.cstr_) < 0;
+  // Assume both are strings.
+  unsigned this_len = this->storage_.length_;
+  unsigned other_len = other.storage_.length_;
+  unsigned min_len = std::min(this_len, other_len);
+  int comp = memcmp(this->cstr_, other.cstr_, min_len);
+  if (comp < 0) return true;
+  if (comp > 0) return false;
+  return (this_len < other_len);
+}
+
+bool Value::CZString::operator==(const CZString& other) const {
+  if (!cstr_) return index_ == other.index_;
+  //return strcmp(cstr_, other.cstr_) == 0;
+  // Assume both are strings.
+  unsigned this_len = this->storage_.length_;
+  unsigned other_len = other.storage_.length_;
+  if (this_len != other_len) return false;
+  int comp = memcmp(this->cstr_, other.cstr_, this_len);
+  return comp == 0;
+}
+
+ArrayIndex Value::CZString::index() const { return index_; }
+
+//const char* Value::CZString::c_str() const { return cstr_; }
+const char* Value::CZString::data() const { return cstr_; }
+unsigned Value::CZString::length() const { return storage_.length_; }
+bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
+
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// class Value::Value
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+// //////////////////////////////////////////////////////////////////
+
+/*! \internal Default constructor initialization must be equivalent to:
+ * memset( this, 0, sizeof(Value) )
+ * This optimization is used in ValueInternalMap fast allocator.
+ */
+Value::Value(ValueType vtype) {
+  initBasic(vtype);
+  switch (vtype) {
+  case nullValue:
+    break;
+  case intValue:
+  case uintValue:
+    value_.int_ = 0;
+    break;
+  case realValue:
+    value_.real_ = 0.0;
+    break;
+  case stringValue:
+    value_.string_ = 0;
+    break;
+  case arrayValue:
+  case objectValue:
+    value_.map_ = new ObjectValues();
+    break;
+  case booleanValue:
+    value_.bool_ = false;
+    break;
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+}
+
+Value::Value(Int value) {
+  initBasic(intValue);
+  value_.int_ = value;
+}
+
+Value::Value(UInt value) {
+  initBasic(uintValue);
+  value_.uint_ = value;
+}
+#if defined(JSON_HAS_INT64)
+Value::Value(Int64 value) {
+  initBasic(intValue);
+  value_.int_ = value;
+}
+Value::Value(UInt64 value) {
+  initBasic(uintValue);
+  value_.uint_ = value;
+}
+#endif // defined(JSON_HAS_INT64)
+
+Value::Value(double value) {
+  initBasic(realValue);
+  value_.real_ = value;
+}
+
+Value::Value(const char* value) {
+  initBasic(stringValue, true);
+  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
+}
+
+Value::Value(const char* beginValue, const char* endValue) {
+  initBasic(stringValue, true);
+  value_.string_ =
+      duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
+}
+
+Value::Value(const std::string& value) {
+  initBasic(stringValue, true);
+  value_.string_ =
+      duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
+}
+
+Value::Value(const StaticString& value) {
+  initBasic(stringValue);
+  value_.string_ = const_cast<char*>(value.c_str());
+}
+
+#ifdef JSON_USE_CPPTL
+Value::Value(const CppTL::ConstString& value) {
+  initBasic(stringValue, true);
+  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
+}
+#endif
+
+Value::Value(bool value) {
+  initBasic(booleanValue);
+  value_.bool_ = value;
+}
+
+Value::Value(Value const& other)
+    : type_(other.type_), allocated_(false)
+      ,
+      comments_(nullptr), default_value_(nullptr), start_(other.start_), limit_(other.limit_)
+{
+  switch (type_) {
+  case nullValue:
+  case intValue:
+  case uintValue:
+  case realValue:
+  case booleanValue:
+    value_ = other.value_;
+    break;
+  case stringValue:
+    if (other.value_.string_ && other.allocated_) {
+      unsigned len;
+      char const* str;
+      decodePrefixedString(other.allocated_, other.value_.string_,
+          &len, &str);
+      value_.string_ = duplicateAndPrefixStringValue(str, len);
+      allocated_ = true;
+    } else {
+      value_.string_ = other.value_.string_;
+      allocated_ = false;
+    }
+    break;
+  case arrayValue:
+  case objectValue:
+    value_.map_ = new ObjectValues(*other.value_.map_);
+    break;
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+  if (other.comments_) {
+    comments_ = new CommentInfo[numberOfCommentPlacement];
+    for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
+      const CommentInfo& otherComment = other.comments_[comment];
+      if (otherComment.comment_)
+        comments_[comment].setComment(
+            otherComment.comment_, strlen(otherComment.comment_));
+    }
+  }
+
+  if ( other.default_value_ )
+  {
+	  default_value_ = new Value( *other.default_value_ );
+  }
+
+}
+
+#if JSON_HAS_RVALUE_REFERENCES
+// Move constructor
+Value::Value(Value&& other) {
+  initBasic(nullValue);
+  swap(other);
+}
+#endif
+
+Value::~Value() {
+  switch (type_) {
+  case nullValue:
+  case intValue:
+  case uintValue:
+  case realValue:
+  case booleanValue:
+    break;
+  case stringValue:
+    if (allocated_)
+      releaseStringValue(value_.string_);
+    break;
+  case arrayValue:
+  case objectValue:
+    delete value_.map_;
+    break;
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+
+  if (comments_)
+    delete[] comments_;
+
+  if ( default_value_)
+	  delete default_value_;
+}
+
+Value& Value::operator=(Value other) {
+  swap(other);
+  return *this;
+}
+
+void Value::swapPayload(Value& other) {
+  ValueType temp = type_;
+  type_ = other.type_;
+  other.type_ = temp;
+  std::swap(value_, other.value_);
+  int temp2 = allocated_;
+  allocated_ = other.allocated_;
+  other.allocated_ = temp2 & 0x1;
+}
+
+void Value::swap(Value& other) {
+  swapPayload(other);
+  std::swap(comments_, other.comments_);
+  std::swap(default_value_, other.default_value_);
+  std::swap(start_, other.start_);
+  std::swap(limit_, other.limit_);
+}
+
+ValueType Value::type() const { return type_; }
+
+int Value::compare(const Value& other) const {
+  if (*this < other)
+    return -1;
+  if (*this > other)
+    return 1;
+  return 0;
+}
+
+bool Value::operator<(const Value& other) const {
+  int typeDelta = type_ - other.type_;
+  if (typeDelta)
+    return typeDelta < 0 ? true : false;
+  switch (type_) {
+  case nullValue:
+    return false;
+  case intValue:
+    return value_.int_ < other.value_.int_;
+  case uintValue:
+    return value_.uint_ < other.value_.uint_;
+  case realValue:
+    return value_.real_ < other.value_.real_;
+  case booleanValue:
+    return value_.bool_ < other.value_.bool_;
+  case stringValue:
+  {
+    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+      if (other.value_.string_) return true;
+      else return false;
+    }
+    unsigned this_len;
+    unsigned other_len;
+    char const* this_str;
+    char const* other_str;
+    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+    unsigned min_len = std::min(this_len, other_len);
+    int comp = memcmp(this_str, other_str, min_len);
+    if (comp < 0) return true;
+    if (comp > 0) return false;
+    return (this_len < other_len);
+  }
+  case arrayValue:
+  case objectValue: {
+    int delta = int(value_.map_->size() - other.value_.map_->size());
+    if (delta)
+      return delta < 0;
+    return (*value_.map_) < (*other.value_.map_);
+  }
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+  return false; // unreachable
+}
+
+bool Value::operator<=(const Value& other) const { return !(other < *this); }
+
+bool Value::operator>=(const Value& other) const { return !(*this < other); }
+
+bool Value::operator>(const Value& other) const { return other < *this; }
+
+bool Value::operator==(const Value& other) const {
+  // if ( type_ != other.type_ )
+  // GCC 2.95.3 says:
+  // attempt to take address of bit-field structure member `Json::Value::type_'
+  // Beats me, but a temp solves the problem.
+  int temp = other.type_;
+  if (type_ != temp)
+    return false;
+  switch (type_) {
+  case nullValue:
+    return true;
+  case intValue:
+    return value_.int_ == other.value_.int_;
+  case uintValue:
+    return value_.uint_ == other.value_.uint_;
+  case realValue:
+    return value_.real_ == other.value_.real_;
+  case booleanValue:
+    return value_.bool_ == other.value_.bool_;
+  case stringValue:
+  {
+    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
+      return (value_.string_ == other.value_.string_);
+    }
+    unsigned this_len;
+    unsigned other_len;
+    char const* this_str;
+    char const* other_str;
+    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
+    if (this_len != other_len) return false;
+    int comp = memcmp(this_str, other_str, this_len);
+    return comp == 0;
+  }
+  case arrayValue:
+  case objectValue:
+    return value_.map_->size() == other.value_.map_->size() &&
+           (*value_.map_) == (*other.value_.map_);
+  default:
+    JSON_ASSERT_UNREACHABLE;
+  }
+  return false; // unreachable
+}
+
+bool Value::operator!=(const Value& other) const { return !(*this == other); }
+
+const char* Value::asCString() const {
+  JSON_ASSERT_MESSAGE(type_ == stringValue,
+                      "in Json::Value::asCString(): requires stringValue");
+  if (value_.string_ == 0) return 0;
+  unsigned this_len;
+  char const* this_str;
+  decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+  return this_str;
+}
+
+bool Value::getString(char const** str, char const** cend) const {
+  if (type_ != stringValue) return false;
+  if (value_.string_ == 0) return false;
+  unsigned length;
+  decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
+  *cend = *str + length;
+  return true;
+}
+
+std::string Value::asString() const {
+  switch (type_) {
+  case nullValue:
+    return "";
+  case stringValue:
+  {
+    if (value_.string_ == 0) return "";
+    unsigned this_len;
+    char const* this_str;
+    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
+    return std::string(this_str, this_len);
+  }
+  case booleanValue:
+    return value_.bool_ ? "true" : "false";
+  case intValue:
+    return valueToString(value_.int_);
+  case uintValue:
+    return valueToString(value_.uint_);
+  case realValue:
+    return valueToString(value_.real_);
+  default:
+	  if ( default_value_ )
+		  return default_value_->asString();
+	  else
+		  return "";
+  }
+}
+
+#ifdef JSON_USE_CPPTL
+CppTL::ConstString Value::asConstString() const {
+  unsigned len;
+  char const* str;
+  decodePrefixedString(allocated_, value_.string_,
+      &len, &str);
+  return CppTL::ConstString(str, len);
+}
+#endif
+
+Value::Int Value::asInt() const {
+  switch (type_) {
+  case intValue:
+    JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
+    return Int(value_.int_);
+  case uintValue:
+    JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
+    return Int(value_.uint_);
+  case realValue:
+    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
+                        "double out of Int range");
+    return Int(value_.real_);
+  case nullValue:
+    return 0;
+  case booleanValue:
+    return value_.bool_ ? 1 : 0;
+  default:
+	  if ( default_value_ )
+		  return default_value_->asInt();
+	  else
+		  return 0;
+  }
+}
+
+Value::UInt Value::asUInt() const {
+  switch (type_) {
+  case intValue:
+    JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
+    return UInt(value_.int_);
+  case uintValue:
+    JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
+    return UInt(value_.uint_);
+  case realValue:
+    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
+                        "double out of UInt range");
+    return UInt(value_.real_);
+  case nullValue:
+    return 0;
+  case booleanValue:
+    return value_.bool_ ? 1 : 0;
+  default:
+	  if ( default_value_ )
+		  return default_value_->asUInt();
+	  else
+		  return 0u;
+  }
+}
+
+#if defined(JSON_HAS_INT64)
+
+Value::Int64 Value::asInt64() const {
+  switch (type_) {
+  case intValue:
+    return Int64(value_.int_);
+  case uintValue:
+    JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
+    return Int64(value_.uint_);
+  case realValue:
+    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
+                        "double out of Int64 range");
+    return Int64(value_.real_);
+  case nullValue:
+    return 0;
+  case booleanValue:
+    return value_.bool_ ? 1 : 0;
+  default:
+	  if ( default_value_ )
+		  return default_value_->asInt64();
+	  else
+		  return 0l;
+  }
+}
+
+Value::UInt64 Value::asUInt64() const {
+  switch (type_) {
+  case intValue:
+    JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
+    return UInt64(value_.int_);
+  case uintValue:
+    return UInt64(value_.uint_);
+  case realValue:
+    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
+                        "double out of UInt64 range");
+    return UInt64(value_.real_);
+  case nullValue:
+    return 0;
+  case booleanValue:
+    return value_.bool_ ? 1 : 0;
+  default:
+	  if ( default_value_ )
+		  return default_value_->asUInt64();
+	  else
+		  return 0ul;
+  }
+}
+#endif // if defined(JSON_HAS_INT64)
+
+LargestInt Value::asLargestInt() const {
+#if defined(JSON_NO_INT64)
+  return asInt();
+#else
+  return asInt64();
+#endif
+}
+
+LargestUInt Value::asLargestUInt() const {
+#if defined(JSON_NO_INT64)
+  return asUInt();
+#else
+  return asUInt64();
+#endif
+}
+
+double Value::asDouble() const {
+  switch (type_) {
+  case intValue:
+    return static_cast<double>(value_.int_);
+  case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+    return static_cast<double>(value_.uint_);
+#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+    return integerToDouble(value_.uint_);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+  case realValue:
+    return value_.real_;
+  case nullValue:
+    return 0.0;
+  case booleanValue:
+    return value_.bool_ ? 1.0 : 0.0;
+  default:
+	  if ( default_value_ )
+		  return default_value_->asDouble();
+	  else
+		  return 0.0;
+  }
+}
+
+float Value::asFloat() const {
+  switch (type_) {
+  case intValue:
+    return static_cast<float>(value_.int_);
+  case uintValue:
+#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+    return static_cast<float>(value_.uint_);
+#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+    return integerToDouble(value_.uint_);
+#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
+  case realValue:
+    return static_cast<float>(value_.real_);
+  case nullValue:
+    return 0.0;
+  case booleanValue:
+    return value_.bool_ ? 1.0f : 0.0f;
+  default:
+	if ( default_value_ )
+		return default_value_->asFloat();
+	else
+		return 0.0f;
+  }
+}
+
+bool Value::asBool() const {
+  switch (type_) {
+  case booleanValue:
+    return value_.bool_;
+  case nullValue:
+    return false;
+  case intValue:
+    return value_.int_ ? true : false;
+  case uintValue:
+    return value_.uint_ ? true : false;
+  case realValue:
+    // This is kind of strange. Not recommended.
+    return (value_.real_ != 0.0) ? true : false;
+  default:
+	if ( default_value_ )
+		return default_value_->asBool();
+	else
+		return false;
+  }
+}
+
+bool Value::isConvertibleTo(ValueType other) const {
+  switch (other) {
+  case nullValue:
+    return (isNumeric() && asDouble() == 0.0) ||
+           (type_ == booleanValue && value_.bool_ == false) ||
+           (type_ == stringValue && asString() == "") ||
+           (type_ == arrayValue && value_.map_->size() == 0) ||
+           (type_ == objectValue && value_.map_->size() == 0) ||
+           type_ == nullValue;
+  case intValue:
+    return isInt() ||
+           (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
+           type_ == booleanValue || type_ == nullValue;
+  case uintValue:
+    return isUInt() ||
+           (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
+           type_ == booleanValue || type_ == nullValue;
+  case realValue:
+    return isNumeric() || type_ == booleanValue || type_ == nullValue;
+  case booleanValue:
+    return isNumeric() || type_ == booleanValue || type_ == nullValue;
+  case stringValue:
+    return isNumeric() || type_ == booleanValue || type_ == stringValue ||
+           type_ == nullValue;
+  case arrayValue:
+    return type_ == arrayValue || type_ == nullValue;
+  case objectValue:
+    return type_ == objectValue || type_ == nullValue;
+  }
+  JSON_ASSERT_UNREACHABLE;
+  return false;
+}
+
+/// Number of values in array or object
+ArrayIndex Value::size() const {
+  switch (type_) {
+  case nullValue:
+  case intValue:
+  case uintValue:
+  case realValue:
+  case booleanValue:
+  case stringValue:
+    return 0;
+  case arrayValue: // size of the array is highest index + 1
+    if (!value_.map_->empty()) {
+      ObjectValues::const_iterator itLast = value_.map_->end();
+      --itLast;
+      return (*itLast).first.index() + 1;
+    }
+    return 0;
+  case objectValue:
+    return ArrayIndex(value_.map_->size());
+  }
+  JSON_ASSERT_UNREACHABLE;
+  return 0; // unreachable;
+}
+
+bool Value::empty() const {
+  if (isNull() || isArray() || isObject())
+    return size() == 0u;
+  else
+    return false;
+}
+
+bool Value::operator!() const { return isNull(); }
+
+void Value::clear() {
+  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
+                          type_ == objectValue,
+                      "in Json::Value::clear(): requires complex value");
+  start_ = 0;
+  limit_ = 0;
+  delete default_value_;
+  default_value_ = nullptr;
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    value_.map_->clear();
+    break;
+  default:
+    break;
+  }
+}
+
+void Value::resize(ArrayIndex newSize) {
+  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
+                      "in Json::Value::resize(): requires arrayValue");
+  if (type_ == nullValue)
+    *this = Value(arrayValue);
+  ArrayIndex oldSize = size();
+  if (newSize == 0)
+    clear();
+  else if (newSize > oldSize)
+    (*this)[newSize - 1];
+  else {
+    for (ArrayIndex index = newSize; index < oldSize; ++index) {
+      value_.map_->erase(index);
+    }
+    assert(size() == newSize);
+  }
+}
+
+Value& Value::operator[](ArrayIndex index) {
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == arrayValue,
+      "in Json::Value::operator[](ArrayIndex): requires arrayValue");
+  if (type_ == nullValue)
+    *this = Value(arrayValue);
+  CZString key(index);
+  ObjectValues::iterator it = value_.map_->lower_bound(key);
+  if (it != value_.map_->end() && (*it).first == key)
+    return (*it).second;
+
+  ObjectValues::value_type defaultValue(key, nullRef);
+  it = value_.map_->insert(it, defaultValue);
+  return (*it).second;
+}
+
+Value& Value::operator[](int index) {
+  JSON_ASSERT_MESSAGE(
+      index >= 0,
+      "in Json::Value::operator[](int index): index cannot be negative");
+  return (*this)[ArrayIndex(index)];
+}
+
+const Value& Value::operator[](ArrayIndex index) const {
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == arrayValue,
+      "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
+  if (type_ == nullValue)
+    return nullRef;
+  CZString key(index);
+  ObjectValues::const_iterator it = value_.map_->find(key);
+  if (it == value_.map_->end())
+    return nullRef;
+  return (*it).second;
+}
+
+const Value& Value::operator[](int index) const {
+  JSON_ASSERT_MESSAGE(
+      index >= 0,
+      "in Json::Value::operator[](int index) const: index cannot be negative");
+  return (*this)[ArrayIndex(index)];
+}
+
+void Value::initBasic(ValueType vtype, bool allocated) {
+  type_ = vtype;
+  allocated_ = allocated;
+  comments_ = 0;
+  start_ = 0;
+  limit_ = 0;
+  default_value_ = nullptr;
+}
+
+// Access an object value by name, create a null member if it does not exist.
+// @pre Type of '*this' is object or null.
+// @param key is null-terminated.
+Value& Value::resolveReference(const char* key) {
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == objectValue,
+      "in Json::Value::resolveReference(): requires objectValue");
+  if (type_ == nullValue)
+    *this = Value(objectValue);
+  CZString actualKey(
+      key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
+  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+  if (it != value_.map_->end() && (*it).first == actualKey)
+    return (*it).second;
+
+  ObjectValues::value_type defaultValue(actualKey, nullRef);
+  it = value_.map_->insert(it, defaultValue);
+  Value& value = (*it).second;
+  return value;
+}
+
+// @param key is not null-terminated.
+Value& Value::resolveReference(char const* key, char const* cend)
+{
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == objectValue,
+      "in Json::Value::resolveReference(key, end): requires objectValue");
+  if (type_ == nullValue)
+    *this = Value(objectValue);
+  CZString actualKey(
+      key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
+  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
+  if (it != value_.map_->end() && (*it).first == actualKey)
+    return (*it).second;
+
+  ObjectValues::value_type defaultValue(actualKey, nullRef);
+  it = value_.map_->insert(it, defaultValue);
+  Value& value = (*it).second;
+  return value;
+}
+
+Value Value::get(ArrayIndex index, const Value& defaultValue) const {
+  const Value* value = &((*this)[index]);
+  if ( value == &nullRef )
+  {
+	  return defaultValue;
+  }
+  else
+  {
+	  Value result = *value;
+	  result.default_value_ = new Value( defaultValue );
+	  return result;
+  }
+}
+
+bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
+
+Value const* Value::find(char const* key, char const* cend) const
+{
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == objectValue,
+      "in Json::Value::find(key, end, found): requires objectValue or nullValue");
+  if (type_ == nullValue) return NULL;
+  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
+  ObjectValues::const_iterator it = value_.map_->find(actualKey);
+  if (it == value_.map_->end()) return NULL;
+  return &(*it).second;
+}
+const Value& Value::operator[](const char* key) const
+{
+  Value const* found = find(key, key + strlen(key));
+  if (!found) return nullRef;
+  return *found;
+}
+Value const& Value::operator[](std::string const& key) const
+{
+  Value const* found = find(key.data(), key.data() + key.length());
+  if (!found) return nullRef;
+  return *found;
+}
+
+Value& Value::operator[](const char* key) {
+  return resolveReference(key, key + strlen(key));
+}
+
+Value& Value::operator[](const std::string& key) {
+  return resolveReference(key.data(), key.data() + key.length());
+}
+
+Value& Value::operator[](const StaticString& key) {
+  return resolveReference(key.c_str());
+}
+
+#ifdef JSON_USE_CPPTL
+Value& Value::operator[](const CppTL::ConstString& key) {
+  return resolveReference(key.c_str(), key.end_c_str());
+}
+Value const& Value::operator[](CppTL::ConstString const& key) const
+{
+  Value const* found = find(key.c_str(), key.end_c_str());
+  if (!found) return nullRef;
+  return *found;
+}
+#endif
+
+Value& Value::append(const Value& value) { return (*this)[size()] = value; }
+
+Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
+{
+  Value const* found = find(key, cend);
+  if ( !found )
+  {
+	  return defaultValue;
+  }
+  else
+  {
+	  Value result = *found;
+	  result.default_value_ = new Value( defaultValue );
+	  return result;
+  }
+}
+Value Value::get(char const* key, Value const& defaultValue) const
+{
+  return get(key, key + strlen(key), defaultValue);
+}
+Value Value::get(std::string const& key, Value const& defaultValue) const
+{
+  return get(key.data(), key.data() + key.length(), defaultValue);
+}
+
+
+bool Value::removeMember(const char* key, const char* cend, Value* removed)
+{
+  if (type_ != objectValue) {
+    return false;
+  }
+  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
+  ObjectValues::iterator it = value_.map_->find(actualKey);
+  if (it == value_.map_->end())
+    return false;
+  *removed = it->second;
+  value_.map_->erase(it);
+  return true;
+}
+bool Value::removeMember(const char* key, Value* removed)
+{
+  return removeMember(key, key + strlen(key), removed);
+}
+bool Value::removeMember(std::string const& key, Value* removed)
+{
+  return removeMember(key.data(), key.data() + key.length(), removed);
+}
+Value Value::removeMember(const char* key)
+{
+  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
+                      "in Json::Value::removeMember(): requires objectValue");
+  if (type_ == nullValue)
+    return nullRef;
+
+  Value removed;  // null
+  removeMember(key, key + strlen(key), &removed);
+  return removed; // still null if removeMember() did nothing
+}
+Value Value::removeMember(const std::string& key)
+{
+  return removeMember(key.c_str());
+}
+
+bool Value::removeIndex(ArrayIndex index, Value* removed) {
+  if (type_ != arrayValue) {
+    return false;
+  }
+  CZString key(index);
+  ObjectValues::iterator it = value_.map_->find(key);
+  if (it == value_.map_->end()) {
+    return false;
+  }
+  *removed = it->second;
+  ArrayIndex oldSize = size();
+  // shift left all items left, into the place of the "removed"
+  for (ArrayIndex i = index; i < (oldSize - 1); ++i){
+    CZString keey(i);
+    (*value_.map_)[keey] = (*this)[i + 1];
+  }
+  // erase the last one ("leftover")
+  CZString keyLast(oldSize - 1);
+  ObjectValues::iterator itLast = value_.map_->find(keyLast);
+  value_.map_->erase(itLast);
+  return true;
+}
+
+#ifdef JSON_USE_CPPTL
+Value Value::get(const CppTL::ConstString& key,
+                 const Value& defaultValue) const {
+  return get(key.c_str(), key.end_c_str(), defaultValue);
+}
+#endif
+
+bool Value::isMember(char const* key, char const* cend) const
+{
+  Value const* value = find(key, cend);
+  return NULL != value;
+}
+bool Value::isMember(char const* key) const
+{
+  return isMember(key, key + strlen(key));
+}
+bool Value::isMember(std::string const& key) const
+{
+  return isMember(key.data(), key.data() + key.length());
+}
+
+#ifdef JSON_USE_CPPTL
+bool Value::isMember(const CppTL::ConstString& key) const {
+  return isMember(key.c_str(), key.end_c_str());
+}
+#endif
+
+Value::Members Value::getMemberNames() const {
+  JSON_ASSERT_MESSAGE(
+      type_ == nullValue || type_ == objectValue,
+      "in Json::Value::getMemberNames(), value must be objectValue");
+  if (type_ == nullValue)
+    return Value::Members();
+  Members members;
+  members.reserve(value_.map_->size());
+  ObjectValues::const_iterator it = value_.map_->begin();
+  ObjectValues::const_iterator itEnd = value_.map_->end();
+  for (; it != itEnd; ++it) {
+    members.push_back(std::string((*it).first.data(),
+                                  (*it).first.length()));
+  }
+  return members;
+}
+//
+//# ifdef JSON_USE_CPPTL
+// EnumMemberNames
+// Value::enumMemberNames() const
+//{
+//   if ( type_ == objectValue )
+//   {
+//      return CppTL::Enum::any(  CppTL::Enum::transform(
+//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
+//         MemberNamesTransform() ) );
+//   }
+//   return EnumMemberNames();
+//}
+//
+//
+// EnumValues
+// Value::enumValues() const
+//{
+//   if ( type_ == objectValue  ||  type_ == arrayValue )
+//      return CppTL::Enum::anyValues( *(value_.map_),
+//                                     CppTL::Type<const Value &>() );
+//   return EnumValues();
+//}
+//
+//# endif
+
+static bool IsIntegral(double d) {
+  double integral_part;
+  return modf(d, &integral_part) == 0.0;
+}
+
+bool Value::isNull() const { return type_ == nullValue; }
+
+bool Value::isBool() const { return type_ == booleanValue; }
+
+bool Value::isInt() const {
+  switch (type_) {
+  case intValue:
+    return value_.int_ >= minInt && value_.int_ <= maxInt;
+  case uintValue:
+    return value_.uint_ <= UInt(maxInt);
+  case realValue:
+    return value_.real_ >= minInt && value_.real_ <= maxInt &&
+           IsIntegral(value_.real_);
+  default:
+    break;
+  }
+  return false;
+}
+
+bool Value::isUInt() const {
+  switch (type_) {
+  case intValue:
+    return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
+  case uintValue:
+    return value_.uint_ <= maxUInt;
+  case realValue:
+    return value_.real_ >= 0 && value_.real_ <= maxUInt &&
+           IsIntegral(value_.real_);
+  default:
+    break;
+  }
+  return false;
+}
+
+bool Value::isInt64() const {
+#if defined(JSON_HAS_INT64)
+  switch (type_) {
+  case intValue:
+    return true;
+  case uintValue:
+    return value_.uint_ <= UInt64(maxInt64);
+  case realValue:
+    // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
+    // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
+    // require the value to be strictly less than the limit.
+    return value_.real_ >= double(minInt64) &&
+           value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
+  default:
+    break;
+  }
+#endif // JSON_HAS_INT64
+  return false;
+}
+
+bool Value::isUInt64() const {
+#if defined(JSON_HAS_INT64)
+  switch (type_) {
+  case intValue:
+    return value_.int_ >= 0;
+  case uintValue:
+    return true;
+  case realValue:
+    // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
+    // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
+    // require the value to be strictly less than the limit.
+    return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
+           IsIntegral(value_.real_);
+  default:
+    break;
+  }
+#endif // JSON_HAS_INT64
+  return false;
+}
+
+bool Value::isIntegral() const {
+#if defined(JSON_HAS_INT64)
+  return isInt64() || isUInt64();
+#else
+  return isInt() || isUInt();
+#endif
+}
+
+bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
+
+bool Value::isNumeric() const { return isIntegral() || isDouble(); }
+
+bool Value::isString() const { return type_ == stringValue; }
+
+bool Value::isArray() const { return type_ == arrayValue; }
+
+bool Value::isObject() const { return type_ == objectValue; }
+
+void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
+  if (!comments_)
+    comments_ = new CommentInfo[numberOfCommentPlacement];
+  if ((len > 0) && (comment[len-1] == '\n')) {
+    // Always discard trailing newline, to aid indentation.
+    len -= 1;
+  }
+  comments_[placement].setComment(comment, len);
+}
+
+void Value::setComment(const char* comment, CommentPlacement placement) {
+  setComment(comment, strlen(comment), placement);
+}
+
+void Value::setComment(const std::string& comment, CommentPlacement placement) {
+  setComment(comment.c_str(), comment.length(), placement);
+}
+
+bool Value::hasComment(CommentPlacement placement) const {
+  return comments_ != 0 && comments_[placement].comment_ != 0;
+}
+
+std::string Value::getComment(CommentPlacement placement) const {
+  if (hasComment(placement))
+    return comments_[placement].comment_;
+  return "";
+}
+
+void Value::setOffsetStart(size_t start) { start_ = start; }
+
+void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
+
+size_t Value::getOffsetStart() const { return start_; }
+
+size_t Value::getOffsetLimit() const { return limit_; }
+
+std::string Value::toStyledString() const {
+  StyledWriter writer;
+  return writer.write(*this);
+}
+
+Value::const_iterator Value::begin() const {
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    if (value_.map_)
+      return const_iterator(value_.map_->begin());
+    break;
+  default:
+    break;
+  }
+  return const_iterator();
+}
+
+Value::const_iterator Value::end() const {
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    if (value_.map_)
+      return const_iterator(value_.map_->end());
+    break;
+  default:
+    break;
+  }
+  return const_iterator();
+}
+
+Value::iterator Value::begin() {
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    if (value_.map_)
+      return iterator(value_.map_->begin());
+    break;
+  default:
+    break;
+  }
+  return iterator();
+}
+
+Value::iterator Value::end() {
+  switch (type_) {
+  case arrayValue:
+  case objectValue:
+    if (value_.map_)
+      return iterator(value_.map_->end());
+    break;
+  default:
+    break;
+  }
+  return iterator();
+}
+
+// class PathArgument
+// //////////////////////////////////////////////////////////////////
+
+PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
+
+PathArgument::PathArgument(ArrayIndex index)
+    : key_(), index_(index), kind_(kindIndex) {}
+
+PathArgument::PathArgument(const char* key)
+    : key_(key), index_(), kind_(kindKey) {}
+
+PathArgument::PathArgument(const std::string& key)
+    : key_(key.c_str()), index_(), kind_(kindKey) {}
+
+// class Path
+// //////////////////////////////////////////////////////////////////
+
+Path::Path(const std::string& path,
+           const PathArgument& a1,
+           const PathArgument& a2,
+           const PathArgument& a3,
+           const PathArgument& a4,
+           const PathArgument& a5) {
+  InArgs in;
+  in.push_back(&a1);
+  in.push_back(&a2);
+  in.push_back(&a3);
+  in.push_back(&a4);
+  in.push_back(&a5);
+  makePath(path, in);
+}
+
+void Path::makePath(const std::string& path, const InArgs& in) {
+  const char* current = path.c_str();
+  const char* end = current + path.length();
+  InArgs::const_iterator itInArg = in.begin();
+  while (current != end) {
+    if (*current == '[') {
+      ++current;
+      if (*current == '%')
+        addPathInArg(path, in, itInArg, PathArgument::kindIndex);
+      else {
+        ArrayIndex index = 0;
+        for (; current != end && *current >= '0' && *current <= '9'; ++current)
+          index = index * 10 + ArrayIndex(*current - '0');
+        args_.push_back(index);
+      }
+      if (current == end || *current++ != ']')
+        invalidPath(path, int(current - path.c_str()));
+    } else if (*current == '%') {
+      addPathInArg(path, in, itInArg, PathArgument::kindKey);
+      ++current;
+    } else if (*current == '.') {
+      ++current;
+    } else {
+      const char* beginName = current;
+      while (current != end && !strchr("[.", *current))
+        ++current;
+      args_.push_back(std::string(beginName, current));
+    }
+  }
+}
+
+void Path::addPathInArg(const std::string& /*path*/,
+                        const InArgs& in,
+                        InArgs::const_iterator& itInArg,
+                        PathArgument::Kind kind) {
+  if (itInArg == in.end()) {
+    // Error: missing argument %d
+  } else if ((*itInArg)->kind_ != kind) {
+    // Error: bad argument type
+  } else {
+    args_.push_back(**itInArg);
+  }
+}
+
+void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
+  // Error: invalid path.
+}
+
+const Value& Path::resolve(const Value& root) const {
+  const Value* node = &root;
+  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+    const PathArgument& arg = *it;
+    if (arg.kind_ == PathArgument::kindIndex) {
+      if (!node->isArray() || !node->isValidIndex(arg.index_)) {
+        // Error: unable to resolve path (array value expected at position...
+      }
+      node = &((*node)[arg.index_]);
+    } else if (arg.kind_ == PathArgument::kindKey) {
+      if (!node->isObject()) {
+        // Error: unable to resolve path (object value expected at position...)
+      }
+      node = &((*node)[arg.key_]);
+      if (node == &Value::nullRef) {
+        // Error: unable to resolve path (object has no member named '' at
+        // position...)
+      }
+    }
+  }
+  return *node;
+}
+
+Value Path::resolve(const Value& root, const Value& defaultValue) const {
+  const Value* node = &root;
+  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+    const PathArgument& arg = *it;
+    if (arg.kind_ == PathArgument::kindIndex) {
+      if (!node->isArray() || !node->isValidIndex(arg.index_))
+        return defaultValue;
+      node = &((*node)[arg.index_]);
+    } else if (arg.kind_ == PathArgument::kindKey) {
+      if (!node->isObject())
+        return defaultValue;
+      node = &((*node)[arg.key_]);
+      if (node == &Value::nullRef)
+        return defaultValue;
+    }
+  }
+  return *node;
+}
+
+Value& Path::make(Value& root) const {
+  Value* node = &root;
+  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
+    const PathArgument& arg = *it;
+    if (arg.kind_ == PathArgument::kindIndex) {
+      if (!node->isArray()) {
+        // Error: node is not an array at position ...
+      }
+      node = &((*node)[arg.index_]);
+    } else if (arg.kind_ == PathArgument::kindKey) {
+      if (!node->isObject()) {
+        // Error: node is not an object at position...
+      }
+      node = &((*node)[arg.key_]);
+    }
+  }
+  return *node;
+}
+
+} // namespace Json
+
+#pragma warning (pop)
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_value.cpp
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+// //////////////////////////////////////////////////////////////////////
+// Beginning of content of file: src/lib_json/json_writer.cpp
+// //////////////////////////////////////////////////////////////////////
+
+// Copyright 2011 Baptiste Lepilleur
+// Distributed under MIT license, or public domain if desired and
+// recognized in your jurisdiction.
+// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
+
+#if !defined(JSON_IS_AMALGAMATION)
+#include <json/writer.h>
+#include "json_tool.h"
+#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <iomanip>
+#include <memory>
+#include <sstream>
+#include <utility>
+#include <set>
+#include <cassert>
+#include <cstring>
+#include <cstdio>
+
+#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
+#include <float.h>
+#define isfinite _finite
+#elif defined(__sun) && defined(__SVR4) //Solaris
+#if !defined(isfinite)
+#include <ieeefp.h>
+#define isfinite finite
+#endif
+#elif defined(_AIX)
+#if !defined(isfinite)
+#include <math.h>
+#define isfinite finite
+#endif
+#elif defined(__hpux)
+#if !defined(isfinite)
+#if defined(__ia64) && !defined(finite)
+#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
+                     _Isfinitef(x) : _IsFinite(x)))
+#else
+#include <math.h>
+#define isfinite finite
+#endif
+#endif
+#else
+#include <cmath>
+#if !(defined(__QNXNTO__)) // QNX already defines isfinite
+#define isfinite std::isfinite
+#endif
+#endif
+
+#if defined(_MSC_VER)
+#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
+#define snprintf sprintf_s
+#elif _MSC_VER >= 1900 // VC++ 14.0 and above
+#define snprintf std::snprintf
+#else
+#define snprintf _snprintf
+#endif
+#elif defined(__ANDROID__) || defined(__QNXNTO__)
+#define snprintf snprintf
+#elif __cplusplus >= 201103L
+#define snprintf std::snprintf
+#endif
+
+#if defined(__BORLANDC__)  
+#include <float.h>
+#define isfinite _finite
+#define snprintf _snprintf
+#endif
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+// Disable warning about strdup being deprecated.
+#pragma warning(disable : 4996)
+#endif
+
+namespace Json {
+
+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
+typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
+#else
+typedef std::auto_ptr<StreamWriter>   StreamWriterPtr;
+#endif
+
+static bool containsControlCharacter(const char* str) {
+  while (*str) {
+    if (isControlCharacter(*(str++)))
+      return true;
+  }
+  return false;
+}
+
+static bool containsControlCharacter0(const char* str, unsigned len) {
+  char const* end = str + len;
+  while (end != str) {
+    if (isControlCharacter(*str) || 0==*str)
+      return true;
+    ++str;
+  }
+  return false;
+}
+
+std::string valueToString(LargestInt value) {
+  UIntToStringBuffer buffer;
+  char* current = buffer + sizeof(buffer);
+  if (value == Value::minLargestInt) {
+    uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
+    *--current = '-';
+  } else if (value < 0) {
+    uintToString(LargestUInt(-value), current);
+    *--current = '-';
+  } else {
+    uintToString(LargestUInt(value), current);
+  }
+  assert(current >= buffer);
+  return current;
+}
+
+std::string valueToString(LargestUInt value) {
+  UIntToStringBuffer buffer;
+  char* current = buffer + sizeof(buffer);
+  uintToString(value, current);
+  assert(current >= buffer);
+  return current;
+}
+
+#if defined(JSON_HAS_INT64)
+
+std::string valueToString(Int value) {
+  return valueToString(LargestInt(value));
+}
+
+std::string valueToString(UInt value) {
+  return valueToString(LargestUInt(value));
+}
+
+#endif // # if defined(JSON_HAS_INT64)
+
+std::string valueToString(double value, bool useSpecialFloats, unsigned int precision) {
+  // Allocate a buffer that is more than large enough to store the 16 digits of
+  // precision requested below.
+  char buffer[32];
+  int len = -1;
+
+  char formatString[6];
+  sprintf(formatString, "%%.%dg", precision);
+
+  // Print into the buffer. We need not request the alternative representation
+  // that always has a decimal point because JSON doesn't distingish the
+  // concepts of reals and integers.
+  if (isfinite(value)) {
+    len = snprintf(buffer, sizeof(buffer), formatString, value);
+  } else {
+    // IEEE standard states that NaN values will not compare to themselves
+    if (value != value) {
+      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
+    } else if (value < 0) {
+      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
+    } else {
+      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
+    }
+    // For those, we do not need to call fixNumLoc, but it is fast.
+  }
+  assert(len >= 0);
+  fixNumericLocale(buffer, buffer + len);
+  return buffer;
+}
+
+std::string valueToString(double value) { return valueToString(value, false, 17); }
+
+std::string valueToString(bool value) { return value ? "true" : "false"; }
+
+std::string valueToQuotedString(const char* value) {
+  if (value == NULL)
+    return "";
+  // Not sure how to handle unicode...
+  if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
+      !containsControlCharacter(value))
+    return std::string("\"") + value + "\"";
+  // We have to walk value and escape any special characters.
+  // Appending to std::string is not efficient, but this should be rare.
+  // (Note: forward slashes are *not* rare, but I am not escaping them.)
+  std::string::size_type maxsize =
+      strlen(value) * 2 + 3; // allescaped+quotes+NULL
+  std::string result;
+  result.reserve(maxsize); // to avoid lots of mallocs
+  result += "\"";
+  for (const char* c = value; *c != 0; ++c) {
+    switch (*c) {
+    case '\"':
+      result += "\\\"";
+      break;
+    case '\\':
+      result += "\\\\";
+      break;
+    case '\b':
+      result += "\\b";
+      break;
+    case '\f':
+      result += "\\f";
+      break;
+    case '\n':
+      result += "\\n";
+      break;
+    case '\r':
+      result += "\\r";
+      break;
+    case '\t':
+      result += "\\t";
+      break;
+    // case '/':
+    // Even though \/ is considered a legal escape in JSON, a bare
+    // slash is also legal, so I see no reason to escape it.
+    // (I hope I am not misunderstanding something.
+    // blep notes: actually escaping \/ may be useful in javascript to avoid </
+    // sequence.
+    // Should add a flag to allow this compatibility mode and prevent this
+    // sequence from occurring.
+    default:
+      if (isControlCharacter(*c)) {
+        std::ostringstream oss;
+        oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+            << std::setw(4) << static_cast<int>(*c);
+        result += oss.str();
+      } else {
+        result += *c;
+      }
+      break;
+    }
+  }
+  result += "\"";
+  return result;
+}
+
+// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
+static char const* strnpbrk(char const* s, char const* accept, size_t n) {
+  assert((s || !n) && accept);
+
+  char const* const end = s + n;
+  for (char const* cur = s; cur < end; ++cur) {
+    int const c = *cur;
+    for (char const* a = accept; *a; ++a) {
+      if (*a == c) {
+        return cur;
+      }
+    }
+  }
+  return NULL;
+}
+static std::string valueToQuotedStringN(const char* value, unsigned length) {
+  if (value == NULL)
+    return "";
+  // Not sure how to handle unicode...
+  if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
+      !containsControlCharacter0(value, length))
+    return std::string("\"") + value + "\"";
+  // We have to walk value and escape any special characters.
+  // Appending to std::string is not efficient, but this should be rare.
+  // (Note: forward slashes are *not* rare, but I am not escaping them.)
+  std::string::size_type maxsize =
+      length * 2 + 3; // allescaped+quotes+NULL
+  std::string result;
+  result.reserve(maxsize); // to avoid lots of mallocs
+  result += "\"";
+  char const* end = value + length;
+  for (const char* c = value; c != end; ++c) {
+    switch (*c) {
+    case '\"':
+      result += "\\\"";
+      break;
+    case '\\':
+      result += "\\\\";
+      break;
+    case '\b':
+      result += "\\b";
+      break;
+    case '\f':
+      result += "\\f";
+      break;
+    case '\n':
+      result += "\\n";
+      break;
+    case '\r':
+      result += "\\r";
+      break;
+    case '\t':
+      result += "\\t";
+      break;
+    // case '/':
+    // Even though \/ is considered a legal escape in JSON, a bare
+    // slash is also legal, so I see no reason to escape it.
+    // (I hope I am not misunderstanding something.)
+    // blep notes: actually escaping \/ may be useful in javascript to avoid </
+    // sequence.
+    // Should add a flag to allow this compatibility mode and prevent this
+    // sequence from occurring.
+    default:
+      if ((isControlCharacter(*c)) || (*c == 0)) {
+        std::ostringstream oss;
+        oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
+            << std::setw(4) << static_cast<int>(*c);
+        result += oss.str();
+      } else {
+        result += *c;
+      }
+      break;
+    }
+  }
+  result += "\"";
+  return result;
+}
+
+// Class Writer
+// //////////////////////////////////////////////////////////////////
+Writer::~Writer() {}
+
+// Class FastWriter
+// //////////////////////////////////////////////////////////////////
+
+FastWriter::FastWriter()
+    : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
+      omitEndingLineFeed_(false) {}
+
+void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
+
+void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
+
+void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
+
+std::string FastWriter::write(const Value& root) {
+  document_ = "";
+  writeValue(root);
+  if (!omitEndingLineFeed_)
+    document_ += "\n";
+  return document_;
+}
+
+void FastWriter::writeValue(const Value& value) {
+  switch (value.type()) {
+  case nullValue:
+    if (!dropNullPlaceholders_)
+      document_ += "null";
+    break;
+  case intValue:
+    document_ += valueToString(value.asLargestInt());
+    break;
+  case uintValue:
+    document_ += valueToString(value.asLargestUInt());
+    break;
+  case realValue:
+    document_ += valueToString(value.asDouble());
+    break;
+  case stringValue:
+  {
+    // Is NULL possible for value.string_?
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
+    break;
+  }
+  case booleanValue:
+    document_ += valueToString(value.asBool());
+    break;
+  case arrayValue: {
+    document_ += '[';
+    int size = value.size();
+    for (int index = 0; index < size; ++index) {
+      if (index > 0)
+        document_ += ',';
+      writeValue(value[index]);
+    }
+    document_ += ']';
+  } break;
+  case objectValue: {
+    Value::Members members(value.getMemberNames());
+    document_ += '{';
+    for (Value::Members::iterator it = members.begin(); it != members.end();
+         ++it) {
+      const std::string& name = *it;
+      if (it != members.begin())
+        document_ += ',';
+      document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
+      document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+      writeValue(value[name]);
+    }
+    document_ += '}';
+  } break;
+  }
+}
+
+// Class StyledWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledWriter::StyledWriter()
+    : rightMargin_(74), indentSize_(3), addChildValues_() {}
+
+std::string StyledWriter::write(const Value& root) {
+  document_ = "";
+  addChildValues_ = false;
+  indentString_ = "";
+  writeCommentBeforeValue(root);
+  writeValue(root);
+  writeCommentAfterValueOnSameLine(root);
+  document_ += "\n";
+  return document_;
+}
+
+void StyledWriter::writeValue(const Value& value) {
+  switch (value.type()) {
+  case nullValue:
+    pushValue("null");
+    break;
+  case intValue:
+    pushValue(valueToString(value.asLargestInt()));
+    break;
+  case uintValue:
+    pushValue(valueToString(value.asLargestUInt()));
+    break;
+  case realValue:
+    pushValue(valueToString(value.asDouble()));
+    break;
+  case stringValue:
+  {
+    // Is NULL possible for value.string_?
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+    else pushValue("");
+    break;
+  }
+  case booleanValue:
+    pushValue(valueToString(value.asBool()));
+    break;
+  case arrayValue:
+    writeArrayValue(value);
+    break;
+  case objectValue: {
+    Value::Members members(value.getMemberNames());
+    if (members.empty())
+      pushValue("{}");
+    else {
+      writeWithIndent("{");
+      indent();
+      Value::Members::iterator it = members.begin();
+      for (;;) {
+        const std::string& name = *it;
+        const Value& childValue = value[name];
+        writeCommentBeforeValue(childValue);
+        writeWithIndent(valueToQuotedString(name.c_str()));
+        document_ += " : ";
+        writeValue(childValue);
+        if (++it == members.end()) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        document_ += ',';
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("}");
+    }
+  } break;
+  }
+}
+
+void StyledWriter::writeArrayValue(const Value& value) {
+  unsigned size = value.size();
+  if (size == 0)
+    pushValue("[]");
+  else {
+    bool isArrayMultiLine = isMultineArray(value);
+    if (isArrayMultiLine) {
+      writeWithIndent("[");
+      indent();
+      bool hasChildValue = !childValues_.empty();
+      unsigned index = 0;
+      for (;;) {
+        const Value& childValue = value[index];
+        writeCommentBeforeValue(childValue);
+        if (hasChildValue)
+          writeWithIndent(childValues_[index]);
+        else {
+          writeIndent();
+          writeValue(childValue);
+        }
+        if (++index == size) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        document_ += ',';
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("]");
+    } else // output on a single line
+    {
+      assert(childValues_.size() == size);
+      document_ += "[ ";
+      for (unsigned index = 0; index < size; ++index) {
+        if (index > 0)
+          document_ += ", ";
+        document_ += childValues_[index];
+      }
+      document_ += " ]";
+    }
+  }
+}
+
+bool StyledWriter::isMultineArray(const Value& value) {
+  int size = value.size();
+  bool isMultiLine = size * 3 >= rightMargin_;
+  childValues_.clear();
+  for (int index = 0; index < size && !isMultiLine; ++index) {
+    const Value& childValue = value[index];
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+                        childValue.size() > 0);
+  }
+  if (!isMultiLine) // check if line length > max line length
+  {
+    childValues_.reserve(size);
+    addChildValues_ = true;
+    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+    for (int index = 0; index < size; ++index) {
+      if (hasCommentForValue(value[index])) {
+        isMultiLine = true;
+      }
+      writeValue(value[index]);
+      lineLength += int(childValues_[index].length());
+    }
+    addChildValues_ = false;
+    isMultiLine = isMultiLine || lineLength >= rightMargin_;
+  }
+  return isMultiLine;
+}
+
+void StyledWriter::pushValue(const std::string& value) {
+  if (addChildValues_)
+    childValues_.push_back(value);
+  else
+    document_ += value;
+}
+
+void StyledWriter::writeIndent() {
+  if (!document_.empty()) {
+    char last = document_[document_.length() - 1];
+    if (last == ' ') // already indented
+      return;
+    if (last != '\n') // Comments may add new-line
+      document_ += '\n';
+  }
+  document_ += indentString_;
+}
+
+void StyledWriter::writeWithIndent(const std::string& value) {
+  writeIndent();
+  document_ += value;
+}
+
+void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); }
+
+void StyledWriter::unindent() {
+  assert(int(indentString_.size()) >= indentSize_);
+  indentString_.resize(indentString_.size() - indentSize_);
+}
+
+void StyledWriter::writeCommentBeforeValue(const Value& root) {
+  if (!root.hasComment(commentBefore))
+    return;
+
+  document_ += "\n";
+  writeIndent();
+  const std::string& comment = root.getComment(commentBefore);
+  std::string::const_iterator iter = comment.begin();
+  while (iter != comment.end()) {
+    document_ += *iter;
+    if (*iter == '\n' &&
+       (iter != comment.end() && *(iter + 1) == '/'))
+      writeIndent();
+    ++iter;
+  }
+
+  // Comments are stripped of trailing newlines, so add one here
+  document_ += "\n";
+}
+
+void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+  if (root.hasComment(commentAfterOnSameLine))
+    document_ += " " + root.getComment(commentAfterOnSameLine);
+
+  if (root.hasComment(commentAfter)) {
+    document_ += "\n";
+    document_ += root.getComment(commentAfter);
+    document_ += "\n";
+  }
+}
+
+bool StyledWriter::hasCommentForValue(const Value& value) {
+  return value.hasComment(commentBefore) ||
+         value.hasComment(commentAfterOnSameLine) ||
+         value.hasComment(commentAfter);
+}
+
+// Class StyledStreamWriter
+// //////////////////////////////////////////////////////////////////
+
+StyledStreamWriter::StyledStreamWriter(std::string indentation)
+    : document_(NULL), rightMargin_(74), indentation_(indentation),
+      addChildValues_() {}
+
+void StyledStreamWriter::write(std::ostream& out, const Value& root) {
+  document_ = &out;
+  addChildValues_ = false;
+  indentString_ = "";
+  indented_ = true;
+  writeCommentBeforeValue(root);
+  if (!indented_) writeIndent();
+  indented_ = true;
+  writeValue(root);
+  writeCommentAfterValueOnSameLine(root);
+  *document_ << "\n";
+  document_ = NULL; // Forget the stream, for safety.
+}
+
+void StyledStreamWriter::writeValue(const Value& value) {
+  switch (value.type()) {
+  case nullValue:
+    pushValue("null");
+    break;
+  case intValue:
+    pushValue(valueToString(value.asLargestInt()));
+    break;
+  case uintValue:
+    pushValue(valueToString(value.asLargestUInt()));
+    break;
+  case realValue:
+    pushValue(valueToString(value.asDouble()));
+    break;
+  case stringValue:
+  {
+    // Is NULL possible for value.string_?
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+    else pushValue("");
+    break;
+  }
+  case booleanValue:
+    pushValue(valueToString(value.asBool()));
+    break;
+  case arrayValue:
+    writeArrayValue(value);
+    break;
+  case objectValue: {
+    Value::Members members(value.getMemberNames());
+    if (members.empty())
+      pushValue("{}");
+    else {
+      writeWithIndent("{");
+      indent();
+      Value::Members::iterator it = members.begin();
+      for (;;) {
+        const std::string& name = *it;
+        const Value& childValue = value[name];
+        writeCommentBeforeValue(childValue);
+        writeWithIndent(valueToQuotedString(name.c_str()));
+        *document_ << " : ";
+        writeValue(childValue);
+        if (++it == members.end()) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *document_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("}");
+    }
+  } break;
+  }
+}
+
+void StyledStreamWriter::writeArrayValue(const Value& value) {
+  unsigned size = value.size();
+  if (size == 0)
+    pushValue("[]");
+  else {
+    bool isArrayMultiLine = isMultineArray(value);
+    if (isArrayMultiLine) {
+      writeWithIndent("[");
+      indent();
+      bool hasChildValue = !childValues_.empty();
+      unsigned index = 0;
+      for (;;) {
+        const Value& childValue = value[index];
+        writeCommentBeforeValue(childValue);
+        if (hasChildValue)
+          writeWithIndent(childValues_[index]);
+        else {
+          if (!indented_) writeIndent();
+          indented_ = true;
+          writeValue(childValue);
+          indented_ = false;
+        }
+        if (++index == size) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *document_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("]");
+    } else // output on a single line
+    {
+      assert(childValues_.size() == size);
+      *document_ << "[ ";
+      for (unsigned index = 0; index < size; ++index) {
+        if (index > 0)
+          *document_ << ", ";
+        *document_ << childValues_[index];
+      }
+      *document_ << " ]";
+    }
+  }
+}
+
+bool StyledStreamWriter::isMultineArray(const Value& value) {
+  int size = value.size();
+  bool isMultiLine = size * 3 >= rightMargin_;
+  childValues_.clear();
+  for (int index = 0; index < size && !isMultiLine; ++index) {
+    const Value& childValue = value[index];
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+                        childValue.size() > 0);
+  }
+  if (!isMultiLine) // check if line length > max line length
+  {
+    childValues_.reserve(size);
+    addChildValues_ = true;
+    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+    for (int index = 0; index < size; ++index) {
+      if (hasCommentForValue(value[index])) {
+        isMultiLine = true;
+      }
+      writeValue(value[index]);
+      lineLength += int(childValues_[index].length());
+    }
+    addChildValues_ = false;
+    isMultiLine = isMultiLine || lineLength >= rightMargin_;
+  }
+  return isMultiLine;
+}
+
+void StyledStreamWriter::pushValue(const std::string& value) {
+  if (addChildValues_)
+    childValues_.push_back(value);
+  else
+    *document_ << value;
+}
+
+void StyledStreamWriter::writeIndent() {
+  // blep intended this to look at the so-far-written string
+  // to determine whether we are already indented, but
+  // with a stream we cannot do that. So we rely on some saved state.
+  // The caller checks indented_.
+  *document_ << '\n' << indentString_;
+}
+
+void StyledStreamWriter::writeWithIndent(const std::string& value) {
+  if (!indented_) writeIndent();
+  *document_ << value;
+  indented_ = false;
+}
+
+void StyledStreamWriter::indent() { indentString_ += indentation_; }
+
+void StyledStreamWriter::unindent() {
+  assert(indentString_.size() >= indentation_.size());
+  indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
+  if (!root.hasComment(commentBefore))
+    return;
+
+  if (!indented_) writeIndent();
+  const std::string& comment = root.getComment(commentBefore);
+  std::string::const_iterator iter = comment.begin();
+  while (iter != comment.end()) {
+    *document_ << *iter;
+    if (*iter == '\n' &&
+       (iter != comment.end() && *(iter + 1) == '/'))
+      // writeIndent();  // would include newline
+      *document_ << indentString_;
+    ++iter;
+  }
+  indented_ = false;
+}
+
+void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
+  if (root.hasComment(commentAfterOnSameLine))
+    *document_ << ' ' << root.getComment(commentAfterOnSameLine);
+
+  if (root.hasComment(commentAfter)) {
+    writeIndent();
+    *document_ << root.getComment(commentAfter);
+  }
+  indented_ = false;
+}
+
+bool StyledStreamWriter::hasCommentForValue(const Value& value) {
+  return value.hasComment(commentBefore) ||
+         value.hasComment(commentAfterOnSameLine) ||
+         value.hasComment(commentAfter);
+}
+
+//////////////////////////
+// BuiltStyledStreamWriter
+
+/// Scoped enums are not available until C++11.
+struct CommentStyle {
+  /// Decide whether to write comments.
+  enum Enum {
+    None,  ///< Drop all comments.
+    Most,  ///< Recover odd behavior of previous versions (not implemented yet).
+    All  ///< Keep all comments.
+  };
+};
+
+struct BuiltStyledStreamWriter : public StreamWriter
+{
+  BuiltStyledStreamWriter(
+      std::string const& indentation,
+      CommentStyle::Enum cs,
+      std::string const& colonSymbol,
+      std::string const& nullSymbol,
+      std::string const& endingLineFeedSymbol,
+      bool useSpecialFloats,
+      unsigned int precision);
+  int write(Value const& root, std::ostream* sout);
+private:
+  void writeValue(Value const& value);
+  void writeArrayValue(Value const& value);
+  bool isMultineArray(Value const& value);
+  void pushValue(std::string const& value);
+  void writeIndent();
+  void writeWithIndent(std::string const& value);
+  void indent();
+  void unindent();
+  void writeCommentBeforeValue(Value const& root);
+  void writeCommentAfterValueOnSameLine(Value const& root);
+  static bool hasCommentForValue(const Value& value);
+
+  typedef std::vector<std::string> ChildValues;
+
+  ChildValues childValues_;
+  std::string indentString_;
+  int rightMargin_;
+  std::string indentation_;
+  CommentStyle::Enum cs_;
+  std::string colonSymbol_;
+  std::string nullSymbol_;
+  std::string endingLineFeedSymbol_;
+  bool addChildValues_ : 1;
+  bool indented_ : 1;
+  bool useSpecialFloats_ : 1;
+  unsigned int precision_;
+};
+BuiltStyledStreamWriter::BuiltStyledStreamWriter(
+      std::string const& indentation,
+      CommentStyle::Enum cs,
+      std::string const& colonSymbol,
+      std::string const& nullSymbol,
+      std::string const& endingLineFeedSymbol,
+      bool useSpecialFloats,
+      unsigned int precision)
+  : rightMargin_(74)
+  , indentation_(indentation)
+  , cs_(cs)
+  , colonSymbol_(colonSymbol)
+  , nullSymbol_(nullSymbol)
+  , endingLineFeedSymbol_(endingLineFeedSymbol)
+  , addChildValues_(false)
+  , indented_(false)
+  , useSpecialFloats_(useSpecialFloats)
+  , precision_(precision)
+{
+}
+int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout)
+{
+  sout_ = sout;
+  addChildValues_ = false;
+  indented_ = true;
+  indentString_ = "";
+  writeCommentBeforeValue(root);
+  if (!indented_) writeIndent();
+  indented_ = true;
+  writeValue(root);
+  writeCommentAfterValueOnSameLine(root);
+  *sout_ << endingLineFeedSymbol_;
+  sout_ = NULL;
+  return 0;
+}
+void BuiltStyledStreamWriter::writeValue(Value const& value) {
+  switch (value.type()) {
+  case nullValue:
+    pushValue(nullSymbol_);
+    break;
+  case intValue:
+    pushValue(valueToString(value.asLargestInt()));
+    break;
+  case uintValue:
+    pushValue(valueToString(value.asLargestUInt()));
+    break;
+  case realValue:
+    pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
+    break;
+  case stringValue:
+  {
+    // Is NULL is possible for value.string_?
+    char const* str;
+    char const* end;
+    bool ok = value.getString(&str, &end);
+    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
+    else pushValue("");
+    break;
+  }
+  case booleanValue:
+    pushValue(valueToString(value.asBool()));
+    break;
+  case arrayValue:
+    writeArrayValue(value);
+    break;
+  case objectValue: {
+    Value::Members members(value.getMemberNames());
+    if (members.empty())
+      pushValue("{}");
+    else {
+      writeWithIndent("{");
+      indent();
+      Value::Members::iterator it = members.begin();
+      for (;;) {
+        std::string const& name = *it;
+        Value const& childValue = value[name];
+        writeCommentBeforeValue(childValue);
+        writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
+        *sout_ << colonSymbol_;
+        writeValue(childValue);
+        if (++it == members.end()) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *sout_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("}");
+    }
+  } break;
+  }
+}
+
+void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
+  unsigned size = value.size();
+  if (size == 0)
+    pushValue("[]");
+  else {
+    bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+    if (isMultiLine) {
+      writeWithIndent("[");
+      indent();
+      bool hasChildValue = !childValues_.empty();
+      unsigned index = 0;
+      for (;;) {
+        Value const& childValue = value[index];
+        writeCommentBeforeValue(childValue);
+        if (hasChildValue)
+          writeWithIndent(childValues_[index]);
+        else {
+          if (!indented_) writeIndent();
+          indented_ = true;
+          writeValue(childValue);
+          indented_ = false;
+        }
+        if (++index == size) {
+          writeCommentAfterValueOnSameLine(childValue);
+          break;
+        }
+        *sout_ << ",";
+        writeCommentAfterValueOnSameLine(childValue);
+      }
+      unindent();
+      writeWithIndent("]");
+    } else // output on a single line
+    {
+      assert(childValues_.size() == size);
+      *sout_ << "[";
+      if (!indentation_.empty()) *sout_ << " ";
+      for (unsigned index = 0; index < size; ++index) {
+        if (index > 0)
+          *sout_ << ", ";
+        *sout_ << childValues_[index];
+      }
+      if (!indentation_.empty()) *sout_ << " ";
+      *sout_ << "]";
+    }
+  }
+}
+
+bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+  int size = value.size();
+  bool isMultiLine = size * 3 >= rightMargin_;
+  childValues_.clear();
+  for (int index = 0; index < size && !isMultiLine; ++index) {
+    Value const& childValue = value[index];
+    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
+                        childValue.size() > 0);
+  }
+  if (!isMultiLine) // check if line length > max line length
+  {
+    childValues_.reserve(size);
+    addChildValues_ = true;
+    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
+    for (int index = 0; index < size; ++index) {
+      if (hasCommentForValue(value[index])) {
+        isMultiLine = true;
+      }
+      writeValue(value[index]);
+      lineLength += int(childValues_[index].length());
+    }
+    addChildValues_ = false;
+    isMultiLine = isMultiLine || lineLength >= rightMargin_;
+  }
+  return isMultiLine;
+}
+
+void BuiltStyledStreamWriter::pushValue(std::string const& value) {
+  if (addChildValues_)
+    childValues_.push_back(value);
+  else
+    *sout_ << value;
+}
+
+void BuiltStyledStreamWriter::writeIndent() {
+  // blep intended this to look at the so-far-written string
+  // to determine whether we are already indented, but
+  // with a stream we cannot do that. So we rely on some saved state.
+  // The caller checks indented_.
+
+  if (!indentation_.empty()) {
+    // In this case, drop newlines too.
+    *sout_ << '\n' << indentString_;
+  }
+}
+
+void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) {
+  if (!indented_) writeIndent();
+  *sout_ << value;
+  indented_ = false;
+}
+
+void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
+
+void BuiltStyledStreamWriter::unindent() {
+  assert(indentString_.size() >= indentation_.size());
+  indentString_.resize(indentString_.size() - indentation_.size());
+}
+
+void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
+  if (cs_ == CommentStyle::None) return;
+  if (!root.hasComment(commentBefore))
+    return;
+
+  if (!indented_) writeIndent();
+  const std::string& comment = root.getComment(commentBefore);
+  std::string::const_iterator iter = comment.begin();
+  while (iter != comment.end()) {
+    *sout_ << *iter;
+    if (*iter == '\n' &&
+       (iter != comment.end() && *(iter + 1) == '/'))
+      // writeIndent();  // would write extra newline
+      *sout_ << indentString_;
+    ++iter;
+  }
+  indented_ = false;
+}
+
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
+  if (cs_ == CommentStyle::None) return;
+  if (root.hasComment(commentAfterOnSameLine))
+    *sout_ << " " + root.getComment(commentAfterOnSameLine);
+
+  if (root.hasComment(commentAfter)) {
+    writeIndent();
+    *sout_ << root.getComment(commentAfter);
+  }
+}
+
+// static
+bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
+  return value.hasComment(commentBefore) ||
+         value.hasComment(commentAfterOnSameLine) ||
+         value.hasComment(commentAfter);
+}
+
+///////////////
+// StreamWriter
+
+StreamWriter::StreamWriter()
+    : sout_(NULL)
+{
+}
+StreamWriter::~StreamWriter()
+{
+}
+StreamWriter::Factory::~Factory()
+{}
+StreamWriterBuilder::StreamWriterBuilder()
+{
+  setDefaults(&settings_);
+}
+StreamWriterBuilder::~StreamWriterBuilder()
+{}
+StreamWriter* StreamWriterBuilder::newStreamWriter() const
+{
+  std::string indentation = settings_["indentation"].asString();
+  std::string cs_str = settings_["commentStyle"].asString();
+  bool eyc = settings_["enableYAMLCompatibility"].asBool();
+  bool dnp = settings_["dropNullPlaceholders"].asBool();
+  bool usf = settings_["useSpecialFloats"].asBool(); 
+  unsigned int pre = settings_["precision"].asUInt();
+  CommentStyle::Enum cs = CommentStyle::All;
+  if (cs_str == "All") {
+    cs = CommentStyle::All;
+  } else if (cs_str == "None") {
+    cs = CommentStyle::None;
+  } else {
+    throwRuntimeError("commentStyle must be 'All' or 'None'");
+  }
+  std::string colonSymbol = " : ";
+  if (eyc) {
+    colonSymbol = ": ";
+  } else if (indentation.empty()) {
+    colonSymbol = ":";
+  }
+  std::string nullSymbol = "null";
+  if (dnp) {
+    nullSymbol = "";
+  }
+  if (pre > 17) pre = 17;
+  std::string endingLineFeedSymbol = "";
+  return new BuiltStyledStreamWriter(
+      indentation, cs,
+      colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
+}
+static void getValidWriterKeys(std::set<std::string>* valid_keys)
+{
+  valid_keys->clear();
+  valid_keys->insert("indentation");
+  valid_keys->insert("commentStyle");
+  valid_keys->insert("enableYAMLCompatibility");
+  valid_keys->insert("dropNullPlaceholders");
+  valid_keys->insert("useSpecialFloats");
+  valid_keys->insert("precision");
+}
+bool StreamWriterBuilder::validate(Json::Value* invalid) const
+{
+  Json::Value my_invalid;
+  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
+  Json::Value& inv = *invalid;
+  std::set<std::string> valid_keys;
+  getValidWriterKeys(&valid_keys);
+  Value::Members keys = settings_.getMemberNames();
+  size_t n = keys.size();
+  for (size_t i = 0; i < n; ++i) {
+    std::string const& key = keys[i];
+    if (valid_keys.find(key) == valid_keys.end()) {
+      inv[key] = settings_[key];
+    }
+  }
+  return 0u == inv.size();
+}
+Value& StreamWriterBuilder::operator[](std::string key)
+{
+  return settings_[key];
+}
+// static
+void StreamWriterBuilder::setDefaults(Json::Value* settings)
+{
+  //! [StreamWriterBuilderDefaults]
+  (*settings)["commentStyle"] = "All";
+  (*settings)["indentation"] = "\t";
+  (*settings)["enableYAMLCompatibility"] = false;
+  (*settings)["dropNullPlaceholders"] = false;
+  (*settings)["useSpecialFloats"] = false;
+  (*settings)["precision"] = 17;
+  //! [StreamWriterBuilderDefaults]
+}
+
+std::string writeString(StreamWriter::Factory const& builder, Value const& root) {
+  std::ostringstream sout;
+  StreamWriterPtr const writer(builder.newStreamWriter());
+  writer->write(root, &sout);
+  return sout.str();
+}
+
+std::ostream& operator<<(std::ostream& sout, Value const& root) {
+  StreamWriterBuilder builder;
+  StreamWriterPtr const writer(builder.newStreamWriter());
+  writer->write(root, &sout);
+  return sout;
+}
+
+} // namespace Json
+
+// //////////////////////////////////////////////////////////////////////
+// End of content of file: src/lib_json/json_writer.cpp
+// //////////////////////////////////////////////////////////////////////
+
+
+
+
+
diff --git a/third_party/openvr/src/src/openvr_api_public.cpp b/third_party/openvr/src/src/openvr_api_public.cpp
new file mode 100644
index 0000000..3e303dd
--- /dev/null
+++ b/third_party/openvr/src/src/openvr_api_public.cpp
@@ -0,0 +1,284 @@
+//========= Copyright Valve Corporation ============//
+#define VR_API_EXPORT 1
+#include "openvr.h"
+#include "ivrclientcore.h"
+#include "pathtools_public.h"
+#include "sharedlibtools_public.h"
+#include "envvartools_public.h"
+#include "hmderrors_public.h"
+#include "vrpathregistry_public.h"
+
+using vr::EVRInitError;
+using vr::IVRSystem;
+using vr::IVRClientCore;
+using vr::VRInitError_None;
+
+namespace vr
+{
+
+static void *g_pVRModule = NULL;
+static IVRClientCore *g_pHmdSystem = NULL;
+
+
+typedef void* (*VRClientCoreFactoryFn)(const char *pInterfaceName, int *pReturnCode);
+
+static uint32_t g_nVRToken = 0;
+
+uint32_t VR_GetInitToken()
+{
+	return g_nVRToken;
+}
+
+EVRInitError VR_LoadHmdSystemInternal();
+void CleanupInternalInterfaces();
+
+
+uint32_t VR_InitInternal( EVRInitError *peError, vr::EVRApplicationType eApplicationType )
+{
+	EVRInitError err = VR_LoadHmdSystemInternal();
+	if (err != vr::VRInitError_None)
+	{
+		SharedLib_Unload(g_pVRModule);
+		g_pHmdSystem = NULL;
+		g_pVRModule = NULL;
+
+		if (peError)
+			*peError = err;
+
+		return 0;
+	}
+
+	err = g_pHmdSystem->Init(eApplicationType);
+	if (err != VRInitError_None)
+	{
+		SharedLib_Unload(g_pVRModule);
+		g_pHmdSystem = NULL;
+		g_pVRModule = NULL;
+
+		if (peError)
+			*peError = err;
+
+		return 0;
+	}
+
+	if (peError)
+		*peError = VRInitError_None;
+
+	return ++g_nVRToken;
+}
+
+void VR_ShutdownInternal()
+{
+	if (g_pHmdSystem)
+	{
+		g_pHmdSystem->Cleanup();
+		g_pHmdSystem = NULL;
+	}
+	if (g_pVRModule)
+	{
+		SharedLib_Unload(g_pVRModule);
+		g_pVRModule = NULL;
+	}
+
+#if !defined( VR_API_PUBLIC )
+	CleanupInternalInterfaces();
+#endif
+
+	++g_nVRToken;
+}
+
+EVRInitError VR_LoadHmdSystemInternal()
+{
+	std::string sRuntimePath, sConfigPath, sLogPath;
+
+	bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
+	if( !bReadPathRegistry )
+	{
+		return vr::VRInitError_Init_PathRegistryNotFound;
+	}
+
+	// figure out where we're going to look for vrclient.dll
+	// see if the specified path actually exists.
+	if( !Path_IsDirectory( sRuntimePath ) )
+	{
+		return vr::VRInitError_Init_InstallationNotFound;
+	}
+
+	// Because we don't have a way to select debug vs. release yet we'll just
+	// use debug if it's there
+#if defined( LINUX64 )
+	std::string sTestPath = Path_Join( sRuntimePath, "bin", PLATSUBDIR );
+#else
+	std::string sTestPath = Path_Join( sRuntimePath, "bin" );
+#endif
+	if( !Path_IsDirectory( sTestPath ) )
+	{
+		return vr::VRInitError_Init_InstallationCorrupt;
+	}
+
+#if defined( WIN64 )
+	std::string sDLLPath = Path_Join( sTestPath, "vrclient_x64" DYNAMIC_LIB_EXT );
+#else
+	std::string sDLLPath = Path_Join( sTestPath, "vrclient" DYNAMIC_LIB_EXT );
+#endif
+
+	// only look in the override
+	void *pMod = SharedLib_Load( sDLLPath.c_str() );
+	// nothing more to do if we can't load the DLL
+	if( !pMod )
+	{
+		return vr::VRInitError_Init_VRClientDLLNotFound;
+	}
+
+	VRClientCoreFactoryFn fnFactory = ( VRClientCoreFactoryFn )( SharedLib_GetFunction( pMod, "VRClientCoreFactory" ) );
+	if( !fnFactory )
+	{
+		SharedLib_Unload( pMod );
+		return vr::VRInitError_Init_FactoryNotFound;
+	}
+
+	int nReturnCode = 0;
+	g_pHmdSystem = static_cast< IVRClientCore * > ( fnFactory( vr::IVRClientCore_Version, &nReturnCode ) );
+	if( !g_pHmdSystem )
+	{
+		SharedLib_Unload( pMod );
+		return vr::VRInitError_Init_InterfaceNotFound;
+	}
+
+	g_pVRModule = pMod;
+	return VRInitError_None;
+}
+
+
+void *VR_GetGenericInterface(const char *pchInterfaceVersion, EVRInitError *peError)
+{
+	if (!g_pHmdSystem)
+	{
+		if (peError)
+			*peError = vr::VRInitError_Init_NotInitialized;
+		return NULL;
+	}
+
+	return g_pHmdSystem->GetGenericInterface(pchInterfaceVersion, peError);
+}
+
+bool VR_IsInterfaceVersionValid(const char *pchInterfaceVersion)
+{
+	if (!g_pHmdSystem)
+	{
+		return false;
+	}
+
+	return g_pHmdSystem->IsInterfaceVersionValid(pchInterfaceVersion) == VRInitError_None;
+}
+
+bool VR_IsHmdPresent()
+{
+	if( g_pHmdSystem )
+	{
+		// if we're already initialized, just call through
+		return g_pHmdSystem->BIsHmdPresent();
+	}
+	else
+	{
+		// otherwise we need to do a bit more work
+		EVRInitError err = VR_LoadHmdSystemInternal();
+		if( err != VRInitError_None )
+			return false;
+
+		bool bHasHmd = g_pHmdSystem->BIsHmdPresent();
+
+		g_pHmdSystem = NULL;
+		SharedLib_Unload( g_pVRModule );
+		g_pVRModule = NULL;
+
+		return bHasHmd;
+	}
+}
+
+/** Returns true if the OpenVR runtime is installed. */
+bool VR_IsRuntimeInstalled()
+{
+	if( g_pHmdSystem )
+	{
+		// if we're already initialized, OpenVR is obviously installed
+		return true;
+	}
+	else
+	{
+		// otherwise we need to do a bit more work
+		std::string sRuntimePath, sConfigPath, sLogPath;
+
+		bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
+		if( !bReadPathRegistry )
+		{
+			return false;
+		}
+
+		// figure out where we're going to look for vrclient.dll
+		// see if the specified path actually exists.
+		if( !Path_IsDirectory( sRuntimePath ) )
+		{
+			return false;
+		}
+
+		// the installation may be corrupt in some way, but it certainly looks installed
+		return true;
+	}
+}
+
+
+/** Returns where OpenVR runtime is installed. */
+const char *VR_RuntimePath()
+{
+	// otherwise we need to do a bit more work
+	static std::string sRuntimePath;
+	std::string sConfigPath, sLogPath;
+
+	bool bReadPathRegistry = CVRPathRegistry_Public::GetPaths( &sRuntimePath, &sConfigPath, &sLogPath, NULL, NULL );
+	if ( !bReadPathRegistry )
+	{
+		return nullptr;
+	}
+
+	// figure out where we're going to look for vrclient.dll
+	// see if the specified path actually exists.
+	if ( !Path_IsDirectory( sRuntimePath ) )
+	{
+		return nullptr;
+	}
+
+	return sRuntimePath.c_str();
+}
+
+
+/** Returns the symbol version of an HMD error. */
+const char *VR_GetVRInitErrorAsSymbol( EVRInitError error )
+{
+	if( g_pHmdSystem )
+		return g_pHmdSystem->GetIDForVRInitError( error );
+	else
+		return GetIDForVRInitError( error );
+}
+
+
+/** Returns the english string version of an HMD error. */
+const char *VR_GetVRInitErrorAsEnglishDescription( EVRInitError error )
+{
+	if ( g_pHmdSystem )
+		return g_pHmdSystem->GetEnglishStringForHmdError( error );
+	else
+		return GetEnglishStringForHmdError( error );
+}
+
+
+VR_INTERFACE const char *VR_CALLTYPE VR_GetStringForHmdError( vr::EVRInitError error );
+
+/** Returns the english string version of an HMD error. */
+const char *VR_GetStringForHmdError( EVRInitError error )
+{
+	return VR_GetVRInitErrorAsEnglishDescription( error );
+}
+
+}
+
diff --git a/third_party/openvr/src/src/vrcommon/dirtools_public.cpp b/third_party/openvr/src/src/vrcommon/dirtools_public.cpp
new file mode 100644
index 0000000..e5cfc02
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/dirtools_public.cpp
@@ -0,0 +1,101 @@
+//========= Copyright Valve Corporation ============//
+#include "dirtools_public.h"
+#include "strtools_public.h"
+#include "pathtools_public.h"
+
+#include <errno.h>
+#include <string.h>
+
+#ifdef _WIN32
+#include "windows.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#endif
+
+#if defined( OSX )
+#include <sys/syslimits.h>
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Purpose: utility function to create dirs & subdirs
+//-----------------------------------------------------------------------------
+bool BCreateDirectoryRecursive( const char *pchPath )
+{
+	// Does it already exist?
+	if ( Path_IsDirectory( pchPath ) )
+		return true;
+
+	// copy the path into something we can munge
+	int len = (int)strlen( pchPath );
+	char *path = (char *)malloc( len + 1 );
+	strcpy( path, pchPath );
+
+	// Walk backwards to first non-existing dir that we find
+	char *s = path + len - 1;
+
+	const char slash = Path_GetSlash();
+	while ( s > path )
+	{
+		if ( *s == slash )
+		{
+			*s = '\0';
+			bool bExists = Path_IsDirectory( path );
+			*s = slash;
+
+			if ( bExists )
+			{
+				++s;
+				break;
+			}
+		}
+		--s;
+	}
+
+	// and then move forwards from there
+
+	while ( *s )
+	{
+		if ( *s == slash )
+		{
+			*s = '\0';
+			BCreateDirectory( path );
+			*s = slash;
+		}
+		s++;
+	}
+
+	bool bRetVal = BCreateDirectory( path );
+	free( path );
+	return bRetVal;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Creates the directory, returning true if it is created, or if it already existed
+//-----------------------------------------------------------------------------
+bool BCreateDirectory( const char *pchPath )
+{
+#ifdef WIN32
+	std::wstring wPath = UTF8to16( pchPath );
+	if ( ::CreateDirectoryW( wPath.c_str(), NULL ) )
+		return true;
+
+	if ( ::GetLastError() == ERROR_ALREADY_EXISTS )
+		return true;
+
+	return false;
+#else
+	int i = mkdir( pchPath, S_IRWXU | S_IRWXG | S_IRWXO );
+	if ( i == 0 )
+		return true;
+	if ( errno == EEXIST )
+		return true;
+
+	return false;
+#endif
+}
+
diff --git a/third_party/openvr/src/src/vrcommon/dirtools_public.h b/third_party/openvr/src/src/vrcommon/dirtools_public.h
new file mode 100644
index 0000000..b048b41
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/dirtools_public.h
@@ -0,0 +1,17 @@
+//========= Copyright Valve Corporation ============//
+#pragma once
+
+#include <stdint.h>
+#include <string>
+
+
+#if !defined(_WIN32)
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+
+extern bool BCreateDirectoryRecursive( const char *pchPath );
+extern bool BCreateDirectory( const char *pchPath );
+
+
diff --git a/third_party/openvr/src/src/vrcommon/envvartools_public.cpp b/third_party/openvr/src/src/vrcommon/envvartools_public.cpp
new file mode 100644
index 0000000..bb050d6
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/envvartools_public.cpp
@@ -0,0 +1,46 @@
+//========= Copyright Valve Corporation ============//
+#include "envvartools_public.h"
+#include <stdlib.h>
+
+#if defined(_WIN32)
+#include <Windows.h>
+
+#undef GetEnvironmentVariable
+#undef SetEnvironmentVariable
+#endif
+
+
+std::string GetEnvironmentVariable( const char *pchVarName )
+{
+#if defined(_WIN32)
+	char rchValue[32767]; // max size for an env var on Windows
+	DWORD cChars = GetEnvironmentVariableA( pchVarName, rchValue, sizeof( rchValue ) );
+	if( cChars == 0 )
+		return "";
+	else
+		return rchValue;
+#elif defined(POSIX)
+	char *pchValue = getenv( pchVarName );
+	if( pchValue )
+		return pchValue;
+	else
+		return "";
+#else
+#error "Unsupported Platform"
+#endif
+}
+
+
+bool SetEnvironmentVariable( const char *pchVarName, const char *pchVarValue )
+{
+#if defined(_WIN32)
+	return 0 != SetEnvironmentVariableA( pchVarName, pchVarValue );
+#elif defined(POSIX)
+	if( pchVarValue == NULL )
+		return 0 == unsetenv( pchVarName );
+	else
+		return 0 == setenv( pchVarName, pchVarValue, 1 );
+#else
+#error "Unsupported Platform"
+#endif
+}
diff --git a/third_party/openvr/src/src/vrcommon/envvartools_public.h b/third_party/openvr/src/src/vrcommon/envvartools_public.h
new file mode 100644
index 0000000..7de981a
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/envvartools_public.h
@@ -0,0 +1,7 @@
+//========= Copyright Valve Corporation ============//
+#pragma once
+
+#include <string>
+
+std::string GetEnvironmentVariable( const char *pchVarName );
+bool SetEnvironmentVariable( const char *pchVarName, const char *pchVarValue );
diff --git a/third_party/openvr/src/src/vrcommon/hmderrors_public.cpp b/third_party/openvr/src/src/vrcommon/hmderrors_public.cpp
new file mode 100644
index 0000000..5d9ecbc
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/hmderrors_public.cpp
@@ -0,0 +1,205 @@
+//========= Copyright Valve Corporation ============//
+#include "openvr.h"
+#include "hmderrors_public.h"
+#include <stdio.h>
+#include <algorithm>
+
+using namespace vr;
+
+#define RETURN_ENUM_AS_STRING(enumValue) case enumValue: return #enumValue;
+
+
+const char *GetEnglishStringForHmdError( vr::EVRInitError eError )
+{
+	switch( eError )
+	{
+	case VRInitError_None:						return "No Error (0)";
+
+	case VRInitError_Init_InstallationNotFound:	return "Installation Not Found (100)";
+	case VRInitError_Init_InstallationCorrupt:	return "Installation Corrupt (101)";
+	case VRInitError_Init_VRClientDLLNotFound:	return "vrclient Shared Lib Not Found (102)";
+	case VRInitError_Init_FileNotFound:			return "File Not Found (103)";
+	case VRInitError_Init_FactoryNotFound:		return "Factory Function Not Found (104)";
+	case VRInitError_Init_InterfaceNotFound:	return "Interface Not Found (105)";
+	case VRInitError_Init_InvalidInterface:		return "Invalid Interface (106)";
+	case VRInitError_Init_UserConfigDirectoryInvalid: return "User Config Directory Invalid (107)";
+	case VRInitError_Init_HmdNotFound:			return "Hmd Not Found (108)";
+	case VRInitError_Init_NotInitialized:		return "Not Initialized (109)";
+	case VRInitError_Init_PathRegistryNotFound:	return "Installation path could not be located (110)";
+	case VRInitError_Init_NoConfigPath:			return "Config path could not be located (111)";
+	case VRInitError_Init_NoLogPath:			return "Log path could not be located (112)";
+	case VRInitError_Init_PathRegistryNotWritable: return "Unable to write path registry (113)";
+	case VRInitError_Init_AppInfoInitFailed:	return "App info manager init failed (114)";
+	case VRInitError_Init_Retry:				return "Internal Retry (115)";
+	case VRInitError_Init_InitCanceledByUser:	return "User Canceled Init (116)";
+	case VRInitError_Init_AnotherAppLaunching:	return "Another app was already launching (117)";
+	case VRInitError_Init_SettingsInitFailed:	return "Settings manager init failed (118)";
+	case VRInitError_Init_ShuttingDown:			return "VR system shutting down (119)";
+	case VRInitError_Init_TooManyObjects:		return "Too many tracked objects (120)";
+	case VRInitError_Init_NoServerForBackgroundApp: return "Not starting vrserver for background app (121)";
+	case VRInitError_Init_NotSupportedWithCompositor: return "The requested interface is incompatible with the compositor and the compositor is running (122)";
+	case VRInitError_Init_NotAvailableToUtilityApps: return "This interface is not available to utility applications (123)";
+	case VRInitError_Init_Internal:				return "vrserver internal error (124)";
+	case VRInitError_Init_HmdDriverIdIsNone:	return "Hmd DriverId is invalid (125)";
+	case VRInitError_Init_HmdNotFoundPresenceFailed:	return "Hmd Not Found Presence Failed (126)";
+
+	case VRInitError_Driver_Failed:				return "Driver Failed (200)";
+	case VRInitError_Driver_Unknown:			return "Driver Not Known (201)";
+	case VRInitError_Driver_HmdUnknown:			return "HMD Not Known (202)";
+	case VRInitError_Driver_NotLoaded:			return "Driver Not Loaded (203)";
+	case VRInitError_Driver_RuntimeOutOfDate:	return "Driver runtime is out of date (204)";
+	case VRInitError_Driver_HmdInUse:			return "HMD already in use by another application (205)";
+	case VRInitError_Driver_NotCalibrated:		return "Device is not calibrated (206)";
+	case VRInitError_Driver_CalibrationInvalid: return "Device Calibration is invalid (207)";
+	case VRInitError_Driver_HmdDisplayNotFound: return "HMD detected over USB, but Monitor not found (208)";
+	case VRInitError_Driver_TrackedDeviceInterfaceUnknown: return "Driver Tracked Device Interface unknown (209)";
+	// case VRInitError_Driver_HmdDisplayNotFoundAfterFix: return "HMD detected over USB, but Monitor not found after attempt to fix (210)"; // taken out upon Ben's request: He thinks that there is no need to separate that error from 208
+	case VRInitError_Driver_HmdDriverIdOutOfBounds: return "Hmd DriverId is our of bounds (211)";
+	case VRInitError_Driver_HmdDisplayMirrored: return "HMD detected over USB, but Monitor may be mirrored instead of extended (212)";
+
+	case VRInitError_IPC_ServerInitFailed:		return "VR Server Init Failed (300)";
+	case VRInitError_IPC_ConnectFailed:			return "Connect to VR Server Failed (301)";
+	case VRInitError_IPC_SharedStateInitFailed: return "Shared IPC State Init Failed (302)";
+	case VRInitError_IPC_CompositorInitFailed:	return "Shared IPC Compositor Init Failed (303)";
+	case VRInitError_IPC_MutexInitFailed:		return "Shared IPC Mutex Init Failed (304)";
+	case VRInitError_IPC_Failed:				return "Shared IPC Failed (305)";
+	case VRInitError_IPC_CompositorConnectFailed:				return "Shared IPC Compositor Connect Failed (306)";
+	case VRInitError_IPC_CompositorInvalidConnectResponse:		return "Shared IPC Compositor Invalid Connect Response (307)";
+	case VRInitError_IPC_ConnectFailedAfterMultipleAttempts:	return "Shared IPC Connect Failed After Multiple Attempts (308)";
+
+	case VRInitError_Compositor_Failed:						return "Compositor failed to initialize (400)";
+	case VRInitError_Compositor_D3D11HardwareRequired:		return "Compositor failed to find DX11 hardware (401)";
+	case VRInitError_Compositor_FirmwareRequiresUpdate:		return "Compositor requires mandatory firmware update (402)";
+	case VRInitError_Compositor_OverlayInitFailed:			return "Compositor initialization succeeded, but overlay init failed (403)";
+
+	// Oculus
+	case VRInitError_VendorSpecific_UnableToConnectToOculusRuntime:	return "Unable to connect to Oculus Runtime (1000)";
+
+	// Lighthouse
+	case VRInitError_VendorSpecific_HmdFound_CantOpenDevice:				return "HMD found, but can not open device (1101)";
+	case VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart:	return "HMD found, but unable to request config (1102)";
+	case VRInitError_VendorSpecific_HmdFound_NoStoredConfig:				return "HMD found, but no stored config (1103)";
+	case VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck:       return "HMD found, but failed configuration check (1113)";
+	case VRInitError_VendorSpecific_HmdFound_ConfigTooBig:					return "HMD found, but config too big (1104)";
+	case VRInitError_VendorSpecific_HmdFound_ConfigTooSmall:				return "HMD found, but config too small (1105)";
+	case VRInitError_VendorSpecific_HmdFound_UnableToInitZLib:				return "HMD found, but unable to init ZLib (1106)";
+	case VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion:		return "HMD found, but problems with the data (1107)";
+	case VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart:		return "HMD found, but problems with the data (1108)";
+	case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart:		return "HMD found, but problems with the data (1109)";
+	case VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext:		return "HMD found, but problems with the data (1110)";
+	case VRInitError_VendorSpecific_HmdFound_UserDataAddressRange:			return "HMD found, but problems with the data (1111)";
+	case VRInitError_VendorSpecific_HmdFound_UserDataError:					return "HMD found, but problems with the data (1112)";
+
+	case VRInitError_Steam_SteamInstallationNotFound: return "Unable to find Steam installation (2000)";
+
+	default:
+		{
+			static char buf[128];
+			sprintf( buf, "Unknown error (%d)", eError );
+			return buf;
+		}
+	}
+
+}
+
+
+const char *GetIDForVRInitError( vr::EVRInitError eError )
+{
+	switch( eError )
+	{
+		RETURN_ENUM_AS_STRING( VRInitError_None );
+		RETURN_ENUM_AS_STRING( VRInitError_Unknown );
+
+		RETURN_ENUM_AS_STRING( VRInitError_Init_InstallationNotFound );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_InstallationCorrupt );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_VRClientDLLNotFound );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_FileNotFound );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_FactoryNotFound );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_InterfaceNotFound );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidInterface );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_UserConfigDirectoryInvalid );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_HmdNotFound );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_NotInitialized );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_PathRegistryNotFound );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_NoConfigPath );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_NoLogPath );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_PathRegistryNotWritable );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_AppInfoInitFailed );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_Retry );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_InitCanceledByUser );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_AnotherAppLaunching );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_SettingsInitFailed );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_ShuttingDown );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_TooManyObjects );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_NoServerForBackgroundApp );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_NotSupportedWithCompositor );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_NotAvailableToUtilityApps );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_Internal );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_VRMonitorNotFound );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_VRMonitorStartupFailed );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_LowPowerWatchdogNotSupported );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_InvalidApplicationType );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_NotAvailableToWatchdogApps );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_WatchdogDisabledInSettings );
+
+		RETURN_ENUM_AS_STRING( VRInitError_Init_HmdDriverIdIsNone );
+		RETURN_ENUM_AS_STRING( VRInitError_Init_HmdNotFoundPresenceFailed );
+
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_Failed );
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_Unknown );
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdUnknown);
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_NotLoaded);
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_RuntimeOutOfDate);
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdInUse);
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_NotCalibrated);
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_CalibrationInvalid);
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFound);
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_TrackedDeviceInterfaceUnknown );
+		// RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayNotFoundAfterFix );
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDriverIdOutOfBounds );
+		RETURN_ENUM_AS_STRING( VRInitError_Driver_HmdDisplayMirrored );
+
+		RETURN_ENUM_AS_STRING( VRInitError_IPC_ServerInitFailed);
+		RETURN_ENUM_AS_STRING( VRInitError_IPC_ConnectFailed);
+		RETURN_ENUM_AS_STRING( VRInitError_IPC_SharedStateInitFailed);
+		RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorInitFailed);
+		RETURN_ENUM_AS_STRING( VRInitError_IPC_MutexInitFailed);
+		RETURN_ENUM_AS_STRING( VRInitError_IPC_Failed);
+		RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorConnectFailed);
+		RETURN_ENUM_AS_STRING( VRInitError_IPC_CompositorInvalidConnectResponse);
+		RETURN_ENUM_AS_STRING( VRInitError_IPC_ConnectFailedAfterMultipleAttempts);
+
+		RETURN_ENUM_AS_STRING( VRInitError_Compositor_Failed );
+		RETURN_ENUM_AS_STRING( VRInitError_Compositor_D3D11HardwareRequired );
+		RETURN_ENUM_AS_STRING( VRInitError_Compositor_FirmwareRequiresUpdate );
+		RETURN_ENUM_AS_STRING( VRInitError_Compositor_OverlayInitFailed );
+
+		// Oculus
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_UnableToConnectToOculusRuntime);
+
+		// Lighthouse
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_CantOpenDevice);
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToRequestConfigStart);
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_NoStoredConfig);
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigFailedSanityCheck );
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigTooBig );
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_ConfigTooSmall );
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToInitZLib );
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_CantReadFirmwareVersion );
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToSendUserDataStart );
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataStart );
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UnableToGetUserDataNext );
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UserDataAddressRange );
+		RETURN_ENUM_AS_STRING( VRInitError_VendorSpecific_HmdFound_UserDataError );
+
+		RETURN_ENUM_AS_STRING( VRInitError_Steam_SteamInstallationNotFound );
+
+	default:
+		{
+			static char buf[128];
+			sprintf( buf, "Unknown error (%d)", eError );
+			return buf;
+		}
+	}
+}
+
diff --git a/third_party/openvr/src/src/vrcommon/hmderrors_public.h b/third_party/openvr/src/src/vrcommon/hmderrors_public.h
new file mode 100644
index 0000000..ccd6c8a
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/hmderrors_public.h
@@ -0,0 +1,6 @@
+//========= Copyright Valve Corporation ============//
+#pragma once
+
+const char *GetEnglishStringForHmdError( vr::EVRInitError eError );
+const char *GetIDForVRInitError( vr::EVRInitError eError );
+
diff --git a/third_party/openvr/src/src/vrcommon/pathtools_public.cpp b/third_party/openvr/src/src/vrcommon/pathtools_public.cpp
new file mode 100644
index 0000000..6413c34
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/pathtools_public.cpp
@@ -0,0 +1,818 @@
+//========= Copyright Valve Corporation ============//
+#include "strtools_public.h"
+#include "pathtools_public.h"
+
+#if defined( _WIN32)
+#include <Windows.h>
+#include <direct.h>
+#include <Shobjidl.h>
+#include <KnownFolders.h>
+#include <Shlobj.h>
+
+#undef GetEnvironmentVariable
+#else
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#endif
+#if defined OSX
+#include <Foundation/Foundation.h>
+#include <AppKit/AppKit.h>
+#include <mach-o/dyld.h>
+#define _S_IFDIR S_IFDIR     // really from tier0/platform.h which we dont have yet
+#endif
+
+#include <sys/stat.h>
+
+#include <algorithm>
+
+/** Returns the path (including filename) to the current executable */
+std::string Path_GetExecutablePath()
+{
+#if defined( _WIN32 )
+	wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH];
+	char *pchPath = new char[MAX_UNICODE_PATH_IN_UTF8];
+	::GetModuleFileNameW( NULL, pwchPath, MAX_UNICODE_PATH );
+	WideCharToMultiByte( CP_UTF8, 0, pwchPath, -1, pchPath, MAX_UNICODE_PATH_IN_UTF8, NULL, NULL );
+	delete[] pwchPath;
+
+	std::string sPath = pchPath;
+	delete[] pchPath;
+	return sPath;
+#elif defined( OSX )
+	char rchPath[1024];
+	uint32_t nBuff = sizeof( rchPath );
+	bool bSuccess = _NSGetExecutablePath(rchPath, &nBuff) == 0;
+	rchPath[nBuff-1] = '\0';
+	if( bSuccess )
+		return rchPath;
+	else
+		return "";
+#elif defined LINUX
+	char rchPath[1024];
+	size_t nBuff = sizeof( rchPath );
+	ssize_t nRead = readlink("/proc/self/exe", rchPath, nBuff-1 );
+	if ( nRead != -1 )
+	{
+		rchPath[ nRead ] = 0;
+		return rchPath;
+	}
+	else
+	{
+		return "";
+	}
+#else
+	AssertMsg( false, "Implement Plat_GetExecutablePath" );
+	return "";
+#endif
+
+}
+
+/** Returns the path of the current working directory */
+std::string Path_GetWorkingDirectory()
+{
+	std::string sPath;
+#if defined( _WIN32 )
+	wchar_t buf[MAX_UNICODE_PATH];
+	sPath = UTF16to8( _wgetcwd( buf, MAX_UNICODE_PATH ) );
+#else
+	char buf[ 1024 ];
+	sPath = getcwd( buf, sizeof( buf ) );
+#endif
+	return sPath;
+}
+
+/** Sets the path of the current working directory. Returns true if this was successful. */
+bool Path_SetWorkingDirectory( const std::string & sPath )
+{
+	bool bSuccess;
+#if defined( _WIN32 )
+	std::wstring wsPath = UTF8to16( sPath.c_str() );
+	bSuccess = 0 == _wchdir( wsPath.c_str() );
+#else
+	bSuccess = 0 == chdir( sPath.c_str() );
+#endif
+	return bSuccess;
+}
+
+/** Returns the specified path without its filename */
+std::string Path_StripFilename( const std::string & sPath, char slash )
+{
+	if( slash == 0 )
+		slash = Path_GetSlash();
+
+	std::string::size_type n = sPath.find_last_of( slash );
+	if( n == std::string::npos )
+		return sPath;
+	else
+		return std::string( sPath.begin(), sPath.begin() + n );
+}
+
+/** returns just the filename from the provided full or relative path. */
+std::string Path_StripDirectory( const std::string & sPath, char slash )
+{
+	if( slash == 0 )
+		slash = Path_GetSlash();
+
+	std::string::size_type n = sPath.find_last_of( slash );
+	if( n == std::string::npos )
+		return sPath;
+	else
+		return std::string( sPath.begin() + n + 1, sPath.end() );
+}
+
+/** returns just the filename with no extension of the provided filename. 
+* If there is a path the path is left intact. */
+std::string Path_StripExtension( const std::string & sPath )
+{
+	for( std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++ )
+	{
+		if( *i == '.' )
+		{
+			return std::string( sPath.begin(), i.base() - 1 );
+		}
+
+		// if we find a slash there is no extension
+		if( *i == '\\' || *i == '/' )
+			break;
+	}
+
+	// we didn't find an extension
+	return sPath;
+}
+
+/** returns just extension of the provided filename (if any). */
+std::string Path_GetExtension( const std::string & sPath )
+{
+	for ( std::string::const_reverse_iterator i = sPath.rbegin(); i != sPath.rend(); i++ )
+	{
+		if ( *i == '.' )
+		{
+			return std::string( i.base(), sPath.end() );
+		}
+
+		// if we find a slash there is no extension
+		if ( *i == '\\' || *i == '/' )
+			break;
+	}
+
+	// we didn't find an extension
+	return "";
+}
+
+bool Path_IsAbsolute( const std::string & sPath )
+{
+	if( sPath.empty() )
+		return false;
+
+#if defined( WIN32 )
+	if ( sPath.size() < 3 ) // must be c:\x or \\x at least
+		return false;
+
+	if ( sPath[1] == ':' ) // drive letter plus slash, but must test both slash cases
+	{
+		if ( sPath[2] == '\\' || sPath[2] == '/' )
+			return true;
+	}
+	else if ( sPath[0] == '\\' && sPath[1] == '\\' ) // UNC path
+		return true;
+#else
+	if( sPath[0] == '\\' || sPath[0] == '/' ) // any leading slash
+		return true;
+#endif
+
+	return false;
+}
+
+
+/** Makes an absolute path from a relative path and a base path */
+std::string Path_MakeAbsolute( const std::string & sRelativePath, const std::string & sBasePath, char slash )
+{
+	if( slash == 0 )
+		slash = Path_GetSlash();
+
+	if( Path_IsAbsolute( sRelativePath ) )
+		return sRelativePath;
+	else
+	{
+		if( !Path_IsAbsolute( sBasePath ) )
+			return "";
+
+		std::string sCompacted = Path_Compact( Path_Join( sBasePath, sRelativePath, slash ), slash );
+		if( Path_IsAbsolute( sCompacted ) )
+			return sCompacted;
+		else
+			return "";
+	}
+}
+
+
+/** Fixes the directory separators for the current platform */
+std::string Path_FixSlashes( const std::string & sPath, char slash )
+{
+	if( slash == 0 )
+		slash = Path_GetSlash();
+
+	std::string sFixed = sPath;
+	for( std::string::iterator i = sFixed.begin(); i != sFixed.end(); i++ )
+	{
+		if( *i == '/' || *i == '\\' )
+			*i = slash;
+	}
+
+	return sFixed;
+}
+
+
+char Path_GetSlash()
+{
+#if defined(_WIN32)
+	return '\\';
+#else
+	return '/';
+#endif
+}
+
+/** Jams two paths together with the right kind of slash */
+std::string Path_Join( const std::string & first, const std::string & second, char slash )
+{
+	if( slash == 0 )
+		slash = Path_GetSlash();
+
+	// only insert a slash if we don't already have one
+	std::string::size_type nLen = first.length();
+	if( !nLen )
+		return second;
+#if defined(_WIN32)
+	if( first.back() == '\\' || first.back() == '/' )
+	    nLen--;
+#else
+	char last_char = first[first.length()-1];
+	if (last_char == '\\' || last_char == '/')
+	    nLen--;
+#endif
+
+	return first.substr( 0, nLen ) + std::string( 1, slash ) + second;
+}
+
+
+std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, char slash )
+{
+	return Path_Join( Path_Join( first, second, slash ), third, slash );
+}
+
+std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, const std::string &fourth, char slash )
+{
+	return Path_Join( Path_Join( Path_Join( first, second, slash ), third, slash ), fourth, slash );
+}
+
+std::string Path_Join( 
+	const std::string & first, 
+	const std::string & second, 
+	const std::string & third, 
+	const std::string & fourth, 
+	const std::string & fifth, 
+	char slash )
+{
+	return Path_Join( Path_Join( Path_Join( Path_Join( first, second, slash ), third, slash ), fourth, slash ), fifth, slash );
+}
+
+
+std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash )
+{
+	if ( slash == 0 )
+		slash = Path_GetSlash();
+
+	std::string sPath = sRawPath;
+	std::string::size_type nCurrent = sRawPath.length();
+	if ( nCurrent == 0 )
+		return sPath;
+
+	int nLastFound = -1;
+	nCurrent--;
+	while( nCurrent != 0 )
+	{
+		if ( sRawPath[ nCurrent ] == slash )
+		{
+			nLastFound = (int)nCurrent;
+			nCurrent--;
+		}
+		else
+		{
+			break;
+		}
+	}
+		
+	if ( nLastFound >= 0 )
+	{
+		sPath.erase( nLastFound, std::string::npos );
+	}
+	
+	return sPath;
+}
+
+
+/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the 
+* specified path has a broken number of directories for its number of ..s */
+std::string Path_Compact( const std::string & sRawPath, char slash )
+{
+	if( slash == 0 )
+		slash = Path_GetSlash();
+
+	std::string sPath = Path_FixSlashes( sRawPath, slash );
+	std::string sSlashString( 1, slash );
+
+	// strip out all /./
+	for( std::string::size_type i = 0; (i + 3) < sPath.length();  )
+	{
+		if( sPath[ i ] == slash && sPath[ i+1 ] == '.' && sPath[ i+2 ] == slash )
+		{
+			sPath.replace( i, 3, sSlashString );
+		}
+		else
+		{
+			++i;
+		}
+	}
+
+
+	// get rid of trailing /. but leave the path separator
+	if( sPath.length() > 2 )
+	{
+		std::string::size_type len = sPath.length();
+		if( sPath[ len-1 ] == '.'  && sPath[ len-2 ] == slash )
+		{
+		  // sPath.pop_back();
+		  sPath[len-1] = 0;  // for now, at least
+		}
+	}
+
+	// get rid of leading ./ 
+	if( sPath.length() > 2 )
+	{
+		if( sPath[ 0 ] == '.'  && sPath[ 1 ] == slash )
+		{
+			sPath.replace( 0, 2, "" );
+		}
+	}
+
+	// each time we encounter .. back up until we've found the previous directory name
+	// then get rid of both
+	std::string::size_type i = 0;
+	while( i < sPath.length() )
+	{
+		if( i > 0 && sPath.length() - i >= 2 
+			&& sPath[i] == '.'
+			&& sPath[i+1] == '.'
+			&& ( i + 2 == sPath.length() || sPath[ i+2 ] == slash )
+			&& sPath[ i-1 ] == slash )
+		{
+			// check if we've hit the start of the string and have a bogus path
+			if( i == 1 )
+				return "";
+			
+			// find the separator before i-1
+			std::string::size_type iDirStart = i-2;
+			while( iDirStart > 0 && sPath[ iDirStart - 1 ] != slash )
+				--iDirStart;
+
+			// remove everything from iDirStart to i+2
+			sPath.replace( iDirStart, (i - iDirStart) + 3, "" );
+
+			// start over
+			i = 0;
+		}
+		else
+		{
+			++i;
+		}
+	}
+
+	return sPath;
+}
+
+
+/** Returns the path to the current DLL or exe */
+std::string Path_GetThisModulePath()
+{
+	// gets the path of vrclient.dll itself
+#ifdef WIN32
+	HMODULE hmodule = NULL;
+
+	::GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, reinterpret_cast<LPCTSTR>(Path_GetThisModulePath), &hmodule );
+
+	wchar_t *pwchPath = new wchar_t[MAX_UNICODE_PATH];
+	char *pchPath = new char[ MAX_UNICODE_PATH_IN_UTF8 ];
+	::GetModuleFileNameW( hmodule, pwchPath, MAX_UNICODE_PATH );
+	WideCharToMultiByte( CP_UTF8, 0, pwchPath, -1, pchPath, MAX_UNICODE_PATH_IN_UTF8, NULL, NULL );
+	delete[] pwchPath;
+
+	std::string sPath = pchPath;
+	delete [] pchPath;
+	return sPath;
+
+#elif defined( OSX ) || defined( LINUX )
+	// get the addr of a function in vrclient.so and then ask the dlopen system about it
+	Dl_info info;
+	dladdr( (void *)Path_GetThisModulePath, &info );
+	return info.dli_fname;
+#endif
+
+}
+
+
+/** returns true if the specified path exists and is a directory */
+bool Path_IsDirectory( const std::string & sPath )
+{
+	std::string sFixedPath = Path_FixSlashes( sPath );
+	if( sFixedPath.empty() )
+		return false;
+	char cLast = sFixedPath[ sFixedPath.length() - 1 ];
+	if( cLast == '/' || cLast == '\\' )
+		sFixedPath.erase( sFixedPath.end() - 1, sFixedPath.end() );
+
+	// see if the specified path actually exists.
+
+#if defined(POSIX)
+	struct	stat	buf;
+	if ( stat( sFixedPath.c_str(), &buf ) == -1 )
+	{
+		return false;
+	}
+
+#if defined( LINUX ) || defined( OSX )
+	return S_ISDIR( buf.st_mode );
+#else
+	return (buf.st_mode & _S_IFDIR) != 0;
+#endif
+
+#else
+	struct	_stat	buf;
+	std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() );
+	if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 )
+	{
+		return false;
+	}
+
+	return (buf.st_mode & _S_IFDIR) != 0;
+#endif
+}
+
+/** returns true if the specified path represents an app bundle */
+bool Path_IsAppBundle( const std::string & sPath )
+{
+#if defined(OSX)
+	NSBundle *bundle = [ NSBundle bundleWithPath: [ NSString stringWithUTF8String:sPath.c_str() ] ];
+	bool bisAppBundle = ( nullptr != bundle );
+	[ bundle release ];
+	return bisAppBundle;
+#else
+	return false;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns true if the the path exists
+//-----------------------------------------------------------------------------
+bool Path_Exists( const std::string & sPath )
+{
+	std::string sFixedPath = Path_FixSlashes( sPath );
+	if( sFixedPath.empty() )
+		return false;
+
+#if defined( WIN32 )
+	struct	_stat	buf;
+	std::wstring wsFixedPath = UTF8to16( sFixedPath.c_str() );
+	if ( _wstat( wsFixedPath.c_str(), &buf ) == -1 )
+	{
+		return false;
+	}
+#else
+	struct stat buf;
+	if ( stat ( sFixedPath.c_str(), &buf ) == -1)
+	{
+		return false;
+	}
+#endif
+
+	return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: helper to find a directory upstream from a given path
+//-----------------------------------------------------------------------------
+std::string Path_FindParentDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName )
+{
+	std::string strFoundPath = "";
+	std::string strCurrentPath = Path_FixSlashes( strStartDirectory );
+	if ( strCurrentPath.length() == 0 )
+		return "";
+
+	bool bExists = Path_Exists( strCurrentPath );
+	std::string strCurrentDirectoryName = Path_StripDirectory( strCurrentPath );
+	if ( bExists && stricmp( strCurrentDirectoryName.c_str(), strDirectoryName.c_str() ) == 0 )
+		return strCurrentPath;
+
+	while( bExists && strCurrentPath.length() != 0 )
+	{
+		strCurrentPath = Path_StripFilename( strCurrentPath );
+		strCurrentDirectoryName = Path_StripDirectory( strCurrentPath );
+		bExists = Path_Exists( strCurrentPath );
+		if ( bExists && stricmp( strCurrentDirectoryName.c_str(), strDirectoryName.c_str() ) == 0 )
+			return strCurrentPath;
+	}
+
+	return "";
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: helper to find a subdirectory upstream from a given path
+//-----------------------------------------------------------------------------
+std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName )
+{
+	std::string strFoundPath = "";
+	std::string strCurrentPath = Path_FixSlashes( strStartDirectory );
+	if ( strCurrentPath.length() == 0 )
+		return "";
+
+	bool bExists = Path_Exists( strCurrentPath );
+	while( bExists && strCurrentPath.length() != 0 )
+	{
+		strCurrentPath = Path_StripFilename( strCurrentPath );
+		bExists = Path_Exists( strCurrentPath );
+
+		if( Path_Exists( Path_Join( strCurrentPath, strDirectoryName ) ) )
+		{
+			strFoundPath = Path_Join( strCurrentPath, strDirectoryName );
+			break;
+		}
+	}
+	return strFoundPath;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: reading and writing files in the vortex directory
+//-----------------------------------------------------------------------------
+unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize )
+{
+	FILE *f;
+#if defined( POSIX )
+	f = fopen( strFilename.c_str(), "rb" );
+#else
+	std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
+	// the open operation needs to be sharable, therefore use of _wfsopen instead of _wfopen_s
+	f = _wfsopen( wstrFilename.c_str(), L"rb", _SH_DENYNO );
+#endif
+	
+	unsigned char* buf = NULL;
+
+	if ( f != NULL )
+	{
+		fseek(f, 0, SEEK_END);
+		int size = ftell(f);
+		fseek(f, 0, SEEK_SET);
+
+		buf = new unsigned char[size];
+		if (buf && fread(buf, size, 1, f) == 1)
+		{
+			if (pSize)
+				*pSize = size;
+		}
+		else
+		{
+			delete[] buf;
+			buf = 0;
+		}
+
+		fclose(f);
+	}
+
+	return buf;
+}
+
+uint32_t  Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize )
+{
+	FILE *f;
+#if defined( POSIX )
+	f = fopen( strFilename.c_str(), "rb" );
+#else
+	std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
+	errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"rb" );
+	if ( err != 0 )
+	{
+		f = NULL;
+	}
+#endif
+
+	uint32_t unSizeToReturn = 0;
+
+	if ( f != NULL )
+	{
+		fseek( f, 0, SEEK_END );
+		uint32_t size = (uint32_t)ftell( f );
+		fseek( f, 0, SEEK_SET );
+
+		if ( size > unSize || !pBuffer )
+		{
+			unSizeToReturn = (uint32_t)size;
+		}
+		else
+		{
+			if ( fread( pBuffer, size, 1, f ) == 1 )
+			{
+				unSizeToReturn = (uint32_t)size;
+			}
+		}
+
+		fclose( f );
+	}
+
+	return unSizeToReturn;
+}
+
+bool Path_WriteBinaryFile(const std::string &strFilename, unsigned char *pData, unsigned nSize)
+{
+	FILE *f;
+#if defined( POSIX )
+	f = fopen(strFilename.c_str(), "wb");
+#else
+	std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
+	errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"wb" );
+	if (err != 0)
+	{
+		f = NULL;
+	}
+#endif
+
+	size_t written = 0;
+	if (f != NULL) {
+		written = fwrite(pData, sizeof(unsigned char), nSize, f);
+		fclose(f);
+	}
+
+	return written = nSize ? true : false;
+}
+
+std::string Path_ReadTextFile( const std::string &strFilename )
+{
+	// doing it this way seems backwards, but I don't
+	// see an easy way to do this with C/C++ style IO
+	// that isn't worse...
+	int size;
+	unsigned char* buf = Path_ReadBinaryFile( strFilename, &size );
+	if (!buf)
+		return "";
+
+	// convert CRLF -> LF
+	size_t outsize = 1;
+	for (int i=1; i < size; i++)
+	{
+		if (buf[i] == '\n' && buf[i-1] == '\r') // CRLF
+			buf[outsize-1] = '\n'; // ->LF
+		else
+			buf[outsize++] = buf[i]; // just copy
+	}
+
+	std::string ret((char *)buf, outsize);
+	delete[] buf;
+	return ret;
+}
+
+
+bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pchData )
+{
+	FILE *f;
+#if defined( POSIX )
+	f = fopen( strFilename.c_str(), "w" );
+#else
+	std::wstring wstrFilename = UTF8to16( strFilename.c_str() );
+	errno_t err = _wfopen_s( &f, wstrFilename.c_str(), L"w" );
+	if ( err != 0 )
+	{
+		f = NULL;
+	}
+#endif
+	
+	bool ok = false;
+
+	if ( f != NULL )
+	{
+		ok = fputs( pchData, f) >= 0;
+		fclose(f);
+	}
+
+	return ok;
+}
+
+bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData )
+{
+	std::string strTmpFilename = strFilename + ".tmp";
+
+	if ( !Path_WriteStringToTextFile( strTmpFilename, pchData ) )
+		return false;
+
+	// Platform specific atomic file replacement
+#if defined( _WIN32 )
+	std::wstring wsFilename = UTF8to16( strFilename.c_str() );
+	std::wstring wsTmpFilename = UTF8to16( strTmpFilename.c_str() );
+	if ( !::ReplaceFileW( wsFilename.c_str(), wsTmpFilename.c_str(), nullptr, 0, 0, 0 ) )
+	{
+		// if we couldn't ReplaceFile, try a non-atomic write as a fallback
+		if ( !Path_WriteStringToTextFile( strFilename, pchData ) )
+			return false;
+	}
+#elif defined( POSIX )
+	if ( rename( strTmpFilename.c_str(), strFilename.c_str() ) == -1 )
+		return false;
+#else
+#error Do not know how to write atomic file
+#endif
+
+	return true;
+}
+
+
+#if defined(WIN32)
+#define FILE_URL_PREFIX "file:///"
+#else
+#define FILE_URL_PREFIX "file://"
+#endif
+
+// ----------------------------------------------------------------------------------------------------------------------------
+// Purpose: Turns a path to a file on disk into a URL (or just returns the value if it's already a URL)
+// ----------------------------------------------------------------------------------------------------------------------------
+std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath )
+{
+	if ( !strnicmp( sRelativePath.c_str(), "http://", 7 )
+		|| !strnicmp( sRelativePath.c_str(), "https://", 8 )
+		|| !strnicmp( sRelativePath.c_str(), "file://", 7 ) )
+	{
+		return sRelativePath;
+	}
+	else
+	{
+		std::string sAbsolute = Path_MakeAbsolute( sRelativePath, sBasePath );
+		if ( sAbsolute.empty() )
+			return sAbsolute;
+		return std::string( FILE_URL_PREFIX ) + sAbsolute;
+	}
+}
+
+// -----------------------------------------------------------------------------------------------------
+// Purpose: Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned
+// -----------------------------------------------------------------------------------------------------
+std::string Path_UrlToFilePath( const std::string & sFileUrl )
+{
+	if ( !strnicmp( sFileUrl.c_str(), FILE_URL_PREFIX, strlen( FILE_URL_PREFIX ) ) )
+	{
+		return sFileUrl.c_str() + strlen( FILE_URL_PREFIX );
+	}
+	else
+	{
+		return "";
+	}
+}
+
+
+// -----------------------------------------------------------------------------------------------------
+// Purpose: Returns the root of the directory the system wants us to store user documents in
+// -----------------------------------------------------------------------------------------------------
+std::string GetUserDocumentsPath()
+{
+#if defined( WIN32 )
+	WCHAR rwchPath[MAX_PATH];
+
+	if ( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_MYDOCUMENTS | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) )
+	{
+		return "";
+	}
+
+	// Convert the path to UTF-8 and store in the output
+	std::string sUserPath = UTF16to8( rwchPath );
+
+	return sUserPath;
+#elif defined( OSX )
+	@autoreleasepool {
+		NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
+		if ( [paths count] == 0 )
+		{
+			return "";
+		}
+		
+		return [[paths objectAtIndex:0] UTF8String];
+	}
+#elif defined( LINUX )
+	// @todo: not solved/changed as part of OSX - still not real - just removed old class based steam cut and paste
+	const char *pchHome = getenv( "HOME" );
+	if ( pchHome == NULL )
+	{
+		return "";
+	}
+	return pchHome;
+#endif
+}
+
diff --git a/third_party/openvr/src/src/vrcommon/pathtools_public.h b/third_party/openvr/src/src/vrcommon/pathtools_public.h
new file mode 100644
index 0000000..7c34a71
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/pathtools_public.h
@@ -0,0 +1,129 @@
+//========= Copyright Valve Corporation ============//
+#pragma once
+
+#include <string>
+#include <stdint.h>
+
+/** Returns the path (including filename) to the current executable */
+std::string Path_GetExecutablePath();
+
+/** Returns the path of the current working directory */
+std::string Path_GetWorkingDirectory();
+
+/** Sets the path of the current working directory. Returns true if this was successful. */
+bool Path_SetWorkingDirectory( const std::string & sPath );
+
+/** returns the path (including filename) of the current shared lib or DLL */
+std::string Path_GetThisModulePath();
+
+/** Returns the specified path without its filename.
+* If slash is unspecified the native path separator of the current platform
+* will be used. */
+std::string Path_StripFilename( const std::string & sPath, char slash = 0 );
+
+/** returns just the filename from the provided full or relative path. */
+std::string Path_StripDirectory( const std::string & sPath, char slash = 0 );
+
+/** returns just the filename with no extension of the provided filename. 
+* If there is a path the path is left intact. */
+std::string Path_StripExtension( const std::string & sPath );
+
+/** returns just extension of the provided filename (if any). */
+std::string Path_GetExtension( const std::string & sPath );
+
+/** Returns true if the path is absolute */
+bool Path_IsAbsolute( const std::string & sPath );
+
+/** Makes an absolute path from a relative path and a base path */
+std::string Path_MakeAbsolute( const std::string & sRelativePath, const std::string & sBasePath, char slash = 0 );
+
+/** Fixes the directory separators for the current platform.
+* If slash is unspecified the native path separator of the current platform
+* will be used. */
+std::string Path_FixSlashes( const std::string & sPath, char slash = 0 );
+
+/** Returns the path separator for the current platform */
+char Path_GetSlash();
+
+/** Jams two paths together with the right kind of slash */
+std::string Path_Join( const std::string & first, const std::string & second, char slash = 0 );
+std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, char slash = 0 );
+std::string Path_Join( const std::string & first, const std::string & second, const std::string & third, const std::string &fourth, char slash = 0 );
+std::string Path_Join( 
+	const std::string & first, 
+	const std::string & second, 
+	const std::string & third, 
+	const std::string & fourth, 
+	const std::string & fifth, 
+	char slash = 0 );
+
+
+/** Removes redundant <dir>/.. elements in the path. Returns an empty path if the 
+* specified path has a broken number of directories for its number of ..s.
+* If slash is unspecified the native path separator of the current platform
+* will be used. */
+std::string Path_Compact( const std::string & sRawPath, char slash = 0 );
+
+//** Removed trailing slashes */
+std::string Path_RemoveTrailingSlash( const std::string & sRawPath, char slash = 0 );
+
+/** returns true if the specified path exists and is a directory */
+bool Path_IsDirectory( const std::string & sPath );
+
+/** returns true if the specified path represents an app bundle */
+bool Path_IsAppBundle( const std::string & sPath );
+
+/** returns true if the the path exists */
+bool Path_Exists( const std::string & sPath );
+
+/** Helper functions to find parent directories or subdirectories of parent directories */
+std::string Path_FindParentDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
+std::string Path_FindParentSubDirectoryRecursively( const std::string &strStartDirectory, const std::string &strDirectoryName );
+
+/** Path operations to read or write text/binary files */
+unsigned char * Path_ReadBinaryFile( const std::string &strFilename, int *pSize );
+uint32_t  Path_ReadBinaryFile( const std::string &strFilename, unsigned char *pBuffer, uint32_t unSize );
+bool Path_WriteBinaryFile( const std::string &strFilename, unsigned char *pData, unsigned nSize );
+std::string Path_ReadTextFile( const std::string &strFilename );
+bool Path_WriteStringToTextFile( const std::string &strFilename, const char *pchData );
+bool Path_WriteStringToTextFileAtomic( const std::string &strFilename, const char *pchData );
+
+/** Returns a file:// url for paths, or an http or https url if that's what was provided */
+std::string Path_FilePathToUrl( const std::string & sRelativePath, const std::string & sBasePath );
+
+/** Strips off file:// off a URL and returns the path. For other kinds of URLs an empty string is returned */
+std::string Path_UrlToFilePath( const std::string & sFileUrl );
+
+/** Returns the root of the directory the system wants us to store user documents in */
+std::string GetUserDocumentsPath();
+
+#ifndef MAX_UNICODE_PATH
+	#define MAX_UNICODE_PATH 32767
+#endif
+
+#ifndef MAX_UNICODE_PATH_IN_UTF8
+	#define MAX_UNICODE_PATH_IN_UTF8 (MAX_UNICODE_PATH * 4)
+#endif
+
+//-----------------------------------------------------------------------------
+#if defined(WIN32)
+#define DYNAMIC_LIB_EXT	".dll"
+#ifdef _WIN64
+#define PLATSUBDIR	"win64"
+#else
+#define PLATSUBDIR	"win32"
+#endif
+#elif defined(OSX)
+#define DYNAMIC_LIB_EXT	".dylib"
+#define PLATSUBDIR	"osx32"
+#elif defined(LINUX)
+#define DYNAMIC_LIB_EXT	".so"
+#if defined( LINUX32 )
+#define PLATSUBDIR	"linux32"
+#else
+#define PLATSUBDIR	"linux64"
+#endif
+#else
+#warning "Unknown platform for PLATSUBDIR"
+#define PLATSUBDIR	"unknown_platform"
+#endif
diff --git a/third_party/openvr/src/src/vrcommon/sharedlibtools_public.cpp b/third_party/openvr/src/src/vrcommon/sharedlibtools_public.cpp
new file mode 100644
index 0000000..9c0661e
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/sharedlibtools_public.cpp
@@ -0,0 +1,41 @@
+//========= Copyright Valve Corporation ============//
+#include "sharedlibtools_public.h"
+#include <string.h>
+
+#if defined(_WIN32)
+#include <Windows.h>
+#endif
+
+#if defined(POSIX)
+#include <dlfcn.h>
+#endif
+
+SharedLibHandle SharedLib_Load( const char *pchPath )
+{
+#if defined( _WIN32)
+	return (SharedLibHandle)LoadLibraryEx( pchPath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH );
+#elif defined(POSIX)
+	return (SharedLibHandle)dlopen(pchPath, RTLD_LOCAL|RTLD_NOW);
+#endif
+}
+
+void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName)
+{
+#if defined( _WIN32)
+	return GetProcAddress( (HMODULE)lib, pchFunctionName );
+#elif defined(POSIX)
+	return dlsym( lib, pchFunctionName );
+#endif
+}
+
+
+void SharedLib_Unload( SharedLibHandle lib )
+{
+#if defined( _WIN32)
+	FreeLibrary( (HMODULE)lib );
+#elif defined(POSIX)
+	dlclose( lib );
+#endif
+}
+
+
diff --git a/third_party/openvr/src/src/vrcommon/sharedlibtools_public.h b/third_party/openvr/src/src/vrcommon/sharedlibtools_public.h
new file mode 100644
index 0000000..10163db
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/sharedlibtools_public.h
@@ -0,0 +1,10 @@
+//========= Copyright Valve Corporation ============//
+#pragma once
+
+typedef void *SharedLibHandle;
+
+SharedLibHandle SharedLib_Load( const char *pchPath );
+void *SharedLib_GetFunction( SharedLibHandle lib, const char *pchFunctionName);
+void SharedLib_Unload( SharedLibHandle lib );
+
+
diff --git a/third_party/openvr/src/src/vrcommon/strtools_public.cpp b/third_party/openvr/src/src/vrcommon/strtools_public.cpp
new file mode 100644
index 0000000..9ab60d9
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/strtools_public.cpp
@@ -0,0 +1,437 @@
+//========= Copyright Valve Corporation ============//
+#include "strtools_public.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool StringHasPrefix( const std::string & sString, const std::string & sPrefix )
+{
+	return 0 == strnicmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
+}
+
+bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix )
+{
+	return 0 == strncmp( sString.c_str(), sPrefix.c_str(), sPrefix.length() );
+}
+
+
+bool StringHasSuffix( const std::string &sString, const std::string &sSuffix )
+{
+	size_t cStrLen = sString.length();
+	size_t cSuffixLen = sSuffix.length();
+
+	if ( cSuffixLen > cStrLen )
+		return false;
+
+	std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
+
+	return 0 == stricmp( sStringSuffix.c_str(), sSuffix.c_str() );
+}
+
+bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix )
+{
+	size_t cStrLen = sString.length();
+	size_t cSuffixLen = sSuffix.length();
+
+	if ( cSuffixLen > cStrLen )
+		return false;
+
+	std::string sStringSuffix = sString.substr( cStrLen - cSuffixLen, cSuffixLen );
+
+	return 0 == strncmp( sStringSuffix.c_str(), sSuffix.c_str(),cSuffixLen );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+std::string UTF16to8(const wchar_t * in)
+{
+	std::string out;
+	unsigned int codepoint = 0;
+	for ( ; in && *in != 0; ++in )
+	{
+		if (*in >= 0xd800 && *in <= 0xdbff)
+			codepoint = ((*in - 0xd800) << 10) + 0x10000;
+		else
+		{
+			if (*in >= 0xdc00 && *in <= 0xdfff)
+				codepoint |= *in - 0xdc00;
+			else
+				codepoint = *in;
+
+			if (codepoint <= 0x7f)
+				out.append(1, static_cast<char>(codepoint));
+			else if (codepoint <= 0x7ff)
+			{
+				out.append(1, static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)));
+				out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
+			}
+			else if (codepoint <= 0xffff)
+			{
+				out.append(1, static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)));
+				out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
+				out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
+			}
+			else
+			{
+				out.append(1, static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)));
+				out.append(1, static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)));
+				out.append(1, static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)));
+				out.append(1, static_cast<char>(0x80 | (codepoint & 0x3f)));
+			}
+			codepoint = 0;
+		}
+	}
+	return out;
+}
+
+std::wstring UTF8to16(const char * in)
+{
+	std::wstring out;
+	unsigned int codepoint = 0;
+	int following = 0;
+	for ( ; in && *in != 0; ++in )
+	{
+		unsigned char ch = *in;
+		if (ch <= 0x7f)
+		{
+			codepoint = ch;
+			following = 0;
+		}
+		else if (ch <= 0xbf)
+		{
+			if (following > 0)
+			{
+				codepoint = (codepoint << 6) | (ch & 0x3f);
+				--following;
+			}
+		}
+		else if (ch <= 0xdf)
+		{
+			codepoint = ch & 0x1f;
+			following = 1;
+		}
+		else if (ch <= 0xef)
+		{
+			codepoint = ch & 0x0f;
+			following = 2;
+		}
+		else
+		{
+			codepoint = ch & 0x07;
+			following = 3;
+		}
+		if (following == 0)
+		{
+			if (codepoint > 0xffff)
+			{
+				out.append(1, static_cast<wchar_t>(0xd800 + (codepoint >> 10)));
+				out.append(1, static_cast<wchar_t>(0xdc00 + (codepoint & 0x03ff)));
+			}
+			else
+				out.append(1, static_cast<wchar_t>(codepoint));
+			codepoint = 0;
+		}
+	}
+	return out;
+}
+
+
+void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource )
+{
+	pchBuffer[ unBufferSizeBytes - 1 ] = '\0';
+	strncpy( pchBuffer, pchSource, unBufferSizeBytes - 1 );
+}
+
+
+// --------------------------------------------------------------------
+// Purpose: converts a string to upper case
+// --------------------------------------------------------------------
+std::string StringToUpper( const std::string & sString )
+{
+	std::string sOut;
+	sOut.reserve( sString.size() + 1 );
+	for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
+	{
+		sOut.push_back( (char)toupper( *i ) );
+	}
+
+	return sOut;
+}
+
+
+// --------------------------------------------------------------------
+// Purpose: converts a string to lower case
+// --------------------------------------------------------------------
+std::string StringToLower( const std::string & sString )
+{
+	std::string sOut;
+	sOut.reserve( sString.size() + 1 );
+	for( std::string::const_iterator i = sString.begin(); i != sString.end(); i++ )
+	{
+		sOut.push_back( (char)tolower( *i ) );
+	}
+
+	return sOut;
+}
+
+
+uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen )
+{
+	uint32_t unLen = (uint32_t)sValue.length() + 1;
+	if( !pchBuffer || !unBufferLen )
+		return unLen;
+
+	if( unBufferLen < unLen )
+	{
+		pchBuffer[0] = '\0';
+	}
+	else
+	{
+		memcpy( pchBuffer, sValue.c_str(), unLen );
+	}
+
+	return unLen;
+}
+
+void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen )
+{
+	sDest.resize( unBufferLen + 1 );
+	memcpy( const_cast< char* >( sDest.c_str() ), pchBuffer, unBufferLen );
+	const_cast< char* >( sDest.c_str() )[ unBufferLen ] = '\0';
+}
+
+/** Returns a std::string from a uint64_t */
+std::string Uint64ToString( uint64_t ulValue )
+{
+	char buf[ 22 ];
+#if defined( _WIN32 )
+	sprintf_s( buf, "%llu", ulValue );
+#else
+    snprintf( buf, sizeof( buf ), "%llu", (long long unsigned int ) ulValue );
+#endif
+	return buf;
+}
+
+
+/** returns a uint64_t from a string */
+uint64_t StringToUint64( const std::string & sValue )
+{
+	return strtoull( sValue.c_str(), NULL, 0 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Helper for converting a numeric value to a hex digit, value should be 0-15.
+//-----------------------------------------------------------------------------
+char cIntToHexDigit( int nValue )
+{
+	//Assert( nValue >= 0 && nValue <= 15 );
+	return "0123456789ABCDEF"[ nValue & 15 ];
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Helper for converting a hex char value to numeric, return -1 if the char
+//          is not a valid hex digit.
+//-----------------------------------------------------------------------------
+int iHexCharToInt( char cValue )
+{
+	int32_t iValue = cValue;
+	if ( (uint32_t)( iValue - '0' ) < 10 )
+		return iValue - '0';
+
+	iValue |= 0x20;
+	if ( (uint32_t)( iValue - 'a' ) < 6 )
+		return iValue - 'a' + 10;
+
+	return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Internal implementation of encode, works in the strict RFC manner, or
+//          with spaces turned to + like HTML form encoding.
+//-----------------------------------------------------------------------------
+void V_URLEncodeInternal( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen, bool bUsePlusForSpace )
+{
+	//AssertMsg( nDestLen > 3*nSourceLen, "Target buffer for V_URLEncode should be 3x source length, plus one for terminating null\n" );
+	
+	int iDestPos = 0;
+	for ( int i=0; i < nSourceLen; ++i )
+	{
+		// worst case we need 3 additional chars
+		if( (iDestPos+3) > nDestLen  )
+		{
+			pchDest[0] = '\0';
+//			AssertMsg( false, "Target buffer too short\n" );
+			return;
+		}
+
+		// We allow only a-z, A-Z, 0-9, period, underscore, and hyphen to pass through unescaped.
+		// These are the characters allowed by both the original RFC 1738 and the latest RFC 3986.
+		// Current specs also allow '~', but that is forbidden under original RFC 1738.
+		if ( !( pchSource[i] >= 'a' && pchSource[i] <= 'z' ) && !( pchSource[i] >= 'A' && pchSource[i] <= 'Z' ) && !(pchSource[i] >= '0' && pchSource[i] <= '9' )
+			 && pchSource[i] != '-' && pchSource[i] != '_' && pchSource[i] != '.'	
+		)
+		{
+			if ( bUsePlusForSpace && pchSource[i] == ' ' )
+			{
+				pchDest[iDestPos++] = '+';
+			}
+			else
+			{
+				pchDest[iDestPos++] = '%';
+				uint8_t iValue = pchSource[i];
+				if ( iValue == 0 )
+				{
+					pchDest[iDestPos++] = '0';
+					pchDest[iDestPos++] = '0';
+				}
+				else
+				{
+					char cHexDigit1 = cIntToHexDigit( iValue % 16 );
+					iValue /= 16;
+					char cHexDigit2 = cIntToHexDigit( iValue );
+					pchDest[iDestPos++] = cHexDigit2;
+					pchDest[iDestPos++] = cHexDigit1;
+				}
+			}
+		}
+		else
+		{
+			pchDest[iDestPos++] = pchSource[i];
+		}
+	}
+
+	if( (iDestPos+1) > nDestLen )
+	{
+		pchDest[0] = '\0';
+		//AssertMsg( false, "Target buffer too short to terminate\n" );
+		return;
+	}
+
+	// Null terminate
+	pchDest[iDestPos++] = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Internal implementation of decode, works in the strict RFC manner, or
+//          with spaces turned to + like HTML form encoding.
+//
+//			Returns the amount of space used in the output buffer.
+//-----------------------------------------------------------------------------
+size_t V_URLDecodeInternal( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen, bool bUsePlusForSpace )
+{
+	if ( nDecodeDestLen < nEncodedSourceLen )
+	{
+		//AssertMsg( false, "V_URLDecode needs a dest buffer at least as large as the source" );
+		return 0;
+	}
+
+	int iDestPos = 0;
+	for( int i=0; i < nEncodedSourceLen; ++i )
+	{
+		if ( bUsePlusForSpace && pchEncodedSource[i] == '+' )
+		{
+			pchDecodeDest[ iDestPos++ ] = ' ';
+		}
+		else if ( pchEncodedSource[i] == '%' )
+		{
+			// Percent signifies an encoded value, look ahead for the hex code, convert to numeric, and use that
+
+			// First make sure we have 2 more chars
+			if ( i < nEncodedSourceLen - 2 )
+			{
+				char cHexDigit1 = pchEncodedSource[i+1];
+				char cHexDigit2 = pchEncodedSource[i+2];
+
+				// Turn the chars into a hex value, if they are not valid, then we'll
+				// just place the % and the following two chars direct into the string,
+				// even though this really shouldn't happen, who knows what bad clients
+				// may do with encoding.
+				bool bValid = false;
+				int iValue = iHexCharToInt( cHexDigit1 );
+				if ( iValue != -1 )
+				{
+					iValue *= 16;
+					int iValue2 = iHexCharToInt( cHexDigit2 );
+					if ( iValue2 != -1 )
+					{
+						iValue += iValue2;
+						pchDecodeDest[ iDestPos++ ] = (char)iValue;
+						bValid = true;
+					}
+				}
+
+				if ( !bValid )
+				{
+					pchDecodeDest[ iDestPos++ ] = '%';
+					pchDecodeDest[ iDestPos++ ] = cHexDigit1;
+					pchDecodeDest[ iDestPos++ ] = cHexDigit2;
+				}
+			}
+
+			// Skip ahead
+			i += 2;
+		}
+		else
+		{
+			pchDecodeDest[ iDestPos++ ] = pchEncodedSource[i];
+		}
+	}
+
+	// We may not have extra room to NULL terminate, since this can be used on raw data, but if we do
+	// go ahead and do it as this can avoid bugs.
+	if ( iDestPos < nDecodeDestLen )
+	{
+		pchDecodeDest[iDestPos] = 0;
+	}
+
+	return (size_t)iDestPos;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.  
+//          This version of the call isn't a strict RFC implementation, but uses + for space as is
+//          the standard in HTML form encoding, despite it not being part of the RFC.
+//
+//          Dest buffer should be at least as large as source buffer to guarantee room for decode.
+//-----------------------------------------------------------------------------
+void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen )
+{
+	return V_URLEncodeInternal( pchDest, nDestLen, pchSource, nSourceLen, true );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.  
+//          This version of the call isn't a strict RFC implementation, but uses + for space as is
+//          the standard in HTML form encoding, despite it not being part of the RFC.
+//
+//          Dest buffer should be at least as large as source buffer to guarantee room for decode.
+//			Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
+//-----------------------------------------------------------------------------
+size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen )
+{
+	return V_URLDecodeInternal( pchDecodeDest, nDecodeDestLen, pchEncodedSource, nEncodedSourceLen, true );
+}
+
+//-----------------------------------------------------------------------------
+void V_StripExtension( std::string &in )
+{
+	// Find the last dot. If it's followed by a dot or a slash, then it's part of a 
+	// directory specifier like ../../somedir/./blah.
+	std::string::size_type test = in.rfind( '.' );
+	if ( test != std::string::npos )
+	{
+		// This handles things like ".\blah" or "c:\my@email.com\abc\def\geh"
+		// Which would otherwise wind up with "" and "c:\my@email", respectively.
+		if ( in.rfind( '\\' ) < test && in.rfind( '/' ) < test )
+		{
+			in.resize( test );
+		}
+	}
+}
+
diff --git a/third_party/openvr/src/src/vrcommon/strtools_public.h b/third_party/openvr/src/src/vrcommon/strtools_public.h
new file mode 100644
index 0000000..4bab9b74
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/strtools_public.h
@@ -0,0 +1,126 @@
+//========= Copyright Valve Corporation ============//
+#pragma once
+
+#include <string>
+#include <stdint.h>
+#include <sys/types.h>
+
+/** returns true if the string has the prefix */
+bool StringHasPrefix( const std::string & sString, const std::string & sPrefix );
+bool StringHasPrefixCaseSensitive( const std::string & sString, const std::string & sPrefix );
+
+/** returns if the string has the suffix */
+bool StringHasSuffix( const std::string &sString, const std::string &sSuffix );
+bool StringHasSuffixCaseSensitive( const std::string &sString, const std::string &sSuffix );
+
+/** converts a UTF-16 string to a UTF-8 string */
+std::string UTF16to8(const wchar_t * in);
+
+/** converts a UTF-8 string to a UTF-16 string */
+std::wstring UTF8to16(const char * in);
+#define Utf16FromUtf8 UTF8to16
+
+/** safely copy a string into a buffer */
+void strcpy_safe( char *pchBuffer, size_t unBufferSizeBytes, const char *pchSource );
+template< size_t bufferSize >
+void strcpy_safe( char (& buffer) [ bufferSize ], const char *pchSource ) 
+{
+	strcpy_safe( buffer, bufferSize, pchSource );
+}
+
+
+/** converts a string to upper case */
+std::string StringToUpper( const std::string & sString );
+
+/** converts a string to lower case */
+std::string StringToLower( const std::string & sString );
+
+// we stricmp (from WIN) but it isn't POSIX - OSX/LINUX have strcasecmp so just inline bridge to it
+#if defined( OSX ) || defined( LINUX )
+#include <strings.h>
+inline int stricmp(const char *pStr1, const char *pStr2) { return strcasecmp(pStr1,pStr2); }
+#define _stricmp stricmp
+inline int strnicmp( const char *pStr1, const char *pStr2, size_t unBufferLen ) { return strncasecmp( pStr1,pStr2, unBufferLen ); }
+#define _strnicmp strnicmp
+
+#define _vsnprintf_s vsnprintf
+
+#define _TRUNCATE ((size_t)-1)
+
+#endif
+
+#if defined( OSX )
+// behaviors ensure NULL-termination at least as well as _TRUNCATE does, but
+// wcsncpy_s/strncpy_s can non-NULL-terminate, wcslcpy/strlcpy can not.
+inline errno_t wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
+{
+	return wcslcpy(strDest, strSource, numberOfElements);
+}
+
+inline errno_t strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
+{
+	return strlcpy(strDest, strSource, numberOfElements);
+}
+
+#endif
+
+#if defined( LINUX )
+// this implementation does not return whether or not the destination was 
+// truncated, but that is straightforward to fix if anybody actually needs the
+// return code. 
+#include "string.h"
+inline void wcsncpy_s(wchar_t *strDest, size_t numberOfElements, const wchar_t *strSource, size_t count)
+{
+	wcsncpy(strDest, strSource, numberOfElements);
+	strDest[numberOfElements-1] = '\0';
+}
+
+inline void strncpy_s(char *strDest, size_t numberOfElements, const char *strSource, size_t count)
+{
+	strncpy(strDest, strSource, numberOfElements);
+	strDest[numberOfElements-1] = '\0';
+}
+
+#endif
+
+#if defined( _WIN32 ) && _MSC_VER < 1800
+inline uint64_t strtoull(const char *str, char **endptr, int base) { return _strtoui64( str, endptr, base ); }
+#endif
+
+/* Handles copying a std::string into a buffer as would be provided in an API */
+uint32_t ReturnStdString( const std::string & sValue, char *pchBuffer, uint32_t unBufferLen );
+
+/* Handles copying a buffer into an std::string and auto adds null terminator */
+void BufferToStdString( std::string & sDest, const char *pchBuffer, uint32_t unBufferLen );
+
+/** Returns a std::string from a uint64_t */
+std::string Uint64ToString( uint64_t ulValue );
+
+/** returns a uint64_t from a string */
+uint64_t StringToUint64( const std::string & sValue );
+
+//-----------------------------------------------------------------------------
+// Purpose: Encodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.  
+//          This version of the call isn't a strict RFC implementation, but uses + for space as is
+//          the standard in HTML form encoding, despite it not being part of the RFC.
+//
+//          Dest buffer should be at least as large as source buffer to guarantee room for decode.
+//-----------------------------------------------------------------------------
+void V_URLEncode( char *pchDest, int nDestLen, const char *pchSource, int nSourceLen );
+
+//-----------------------------------------------------------------------------
+// Purpose: Decodes a string (or binary data) from URL encoding format, see rfc1738 section 2.2.  
+//          This version of the call isn't a strict RFC implementation, but uses + for space as is
+//          the standard in HTML form encoding, despite it not being part of the RFC.
+//
+//          Dest buffer should be at least as large as source buffer to guarantee room for decode.
+//			Dest buffer being the same as the source buffer (decode in-place) is explicitly allowed.
+//-----------------------------------------------------------------------------
+size_t V_URLDecode( char *pchDecodeDest, int nDecodeDestLen, const char *pchEncodedSource, int nEncodedSourceLen );
+
+//-----------------------------------------------------------------------------
+// Purpose: strip extension from a path
+//-----------------------------------------------------------------------------
+void V_StripExtension( std::string &in );
+
+
diff --git a/third_party/openvr/src/src/vrcommon/vrpathregistry_public.cpp b/third_party/openvr/src/src/vrcommon/vrpathregistry_public.cpp
new file mode 100644
index 0000000..cf61c866
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/vrpathregistry_public.cpp
@@ -0,0 +1,409 @@
+//========= Copyright Valve Corporation ============//
+
+#include "vrpathregistry_public.h"
+#include "json/json.h"
+#include "pathtools_public.h"
+#include "envvartools_public.h"
+#include "strtools_public.h"
+#include "dirtools_public.h"
+
+#if defined( WIN32 )
+#include <windows.h>
+#include <Shlobj.h>
+
+#undef GetEnvironmentVariable
+#elif defined OSX
+#include <Foundation/Foundation.h>
+#include <AppKit/AppKit.h>
+#elif defined(LINUX)
+#include <dlfcn.h>
+#include <stdio.h>
+#endif
+
+#include <algorithm>
+
+#ifndef VRLog
+	#if defined( WIN32 )
+		#define VRLog(fmt, ...)		fprintf(stderr, fmt, __VA_ARGS__)
+	#else
+		#define VRLog(args...)		fprintf(stderr, args)
+	#endif
+#endif
+
+/** Returns the root of the directory the system wants us to store user config data in */
+static std::string GetAppSettingsPath()
+{
+#if defined( WIN32 )
+	WCHAR rwchPath[MAX_PATH];
+
+	if( !SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, rwchPath ) ) )
+	{
+		return "";
+	}
+
+	// Convert the path to UTF-8 and store in the output
+	std::string sUserPath = UTF16to8( rwchPath );
+
+	return sUserPath;
+#elif defined( OSX )
+	std::string sSettingsDir;
+	@autoreleasepool {
+		// Search for the path
+		NSArray *paths = NSSearchPathForDirectoriesInDomains( NSApplicationSupportDirectory, NSUserDomainMask, YES );
+		if ( [paths count] == 0 )
+		{
+			return "";
+		}
+		
+		NSString *resolvedPath = [paths objectAtIndex:0];
+		resolvedPath = [resolvedPath stringByAppendingPathComponent: @"OpenVR"];
+		
+		if ( ![[NSFileManager new] createDirectoryAtPath: resolvedPath withIntermediateDirectories:YES attributes:nil error:nil] )
+		{
+			return "";
+		}
+		
+		sSettingsDir.assign( [resolvedPath UTF8String] );
+	}
+	return sSettingsDir;
+#elif defined( LINUX )
+
+	// As defined by XDG Base Directory Specification 
+	// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
+
+	const char *pchHome = getenv("XDG_CONFIG_HOME");
+	if ( ( pchHome != NULL) && ( pchHome[0] != '\0' ) )
+	{
+		return pchHome;
+	}
+
+	//
+	// XDG_CONFIG_HOME is not defined, use ~/.config instead
+	// 
+	pchHome = getenv( "HOME" );
+	if ( pchHome == NULL )
+	{
+		return "";
+	}
+
+	std::string sUserPath( pchHome );
+	sUserPath = Path_Join( sUserPath, ".config" );
+	return sUserPath;
+#else
+	#warning "Unsupported platform"
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Constructor
+// ---------------------------------------------------------------------------
+CVRPathRegistry_Public::CVRPathRegistry_Public()
+{
+
+}
+
+// ---------------------------------------------------------------------------
+// Purpose: Computes the registry filename
+// ---------------------------------------------------------------------------
+std::string CVRPathRegistry_Public::GetOpenVRConfigPath()
+{
+	std::string sConfigPath = GetAppSettingsPath();
+	if( sConfigPath.empty() )
+		return "";
+
+#if defined( _WIN32 ) || defined( LINUX )
+	sConfigPath = Path_Join( sConfigPath, "openvr" );
+#elif defined ( OSX ) 
+	sConfigPath = Path_Join( sConfigPath, ".openvr" );
+#else
+	#warning "Unsupported platform"
+#endif
+	sConfigPath = Path_FixSlashes( sConfigPath );
+	return sConfigPath;
+}
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+std::string CVRPathRegistry_Public::GetVRPathRegistryFilename()
+{
+	std::string sPath = GetOpenVRConfigPath();
+	if ( sPath.empty() )
+		return "";
+
+#if defined( _WIN32 )
+	sPath = Path_Join( sPath, "openvrpaths.vrpath" );
+#elif defined ( POSIX ) 
+	sPath = Path_Join( sPath, "openvrpaths.vrpath" );
+#else
+	#error "Unsupported platform"
+#endif
+	sPath = Path_FixSlashes( sPath );
+	return sPath;
+}
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Converts JSON to a history array
+// ---------------------------------------------------------------------------
+static void ParseStringListFromJson( std::vector< std::string > *pvecHistory, const Json::Value & root, const char *pchArrayName )
+{
+	if( !root.isMember( pchArrayName ) )
+		return;
+
+	const Json::Value & arrayNode = root[ pchArrayName ];
+	if( !arrayNode )
+	{
+		VRLog( "VR Path Registry node %s is not an array\n", pchArrayName );
+		return;
+	}
+
+	pvecHistory->clear();
+	pvecHistory->reserve( arrayNode.size() );
+	for( uint32_t unIndex = 0; unIndex < arrayNode.size(); unIndex++ )
+	{
+		std::string sPath( arrayNode[ unIndex ].asString() );
+		pvecHistory->push_back( sPath );
+	}
+}
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Converts a history array to JSON
+// ---------------------------------------------------------------------------
+static void StringListToJson( const std::vector< std::string > & vecHistory, Json::Value & root, const char *pchArrayName )
+{
+	Json::Value & arrayNode = root[ pchArrayName ];
+	for( auto i = vecHistory.begin(); i != vecHistory.end(); i++ )
+	{
+		arrayNode.append( *i );
+	}
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CVRPathRegistry_Public::ToJsonString( std::string &sJsonString )
+{
+	std::string sRegPath = GetVRPathRegistryFilename();
+	if( sRegPath.empty() )
+		return false;
+	
+	std::string sRegistryContents = Path_ReadTextFile( sRegPath );
+	if( sRegistryContents.empty() )
+		return false;
+
+	sJsonString = sRegistryContents;
+
+	return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Loads the config file from its well known location
+// ---------------------------------------------------------------------------
+bool CVRPathRegistry_Public::BLoadFromFile()
+{
+	std::string sRegPath = GetVRPathRegistryFilename();
+	if( sRegPath.empty() )
+	{
+		VRLog( "Unable to determine VR Path Registry filename\n" );
+		return false;
+	}
+
+	std::string sRegistryContents = Path_ReadTextFile( sRegPath );
+	if( sRegistryContents.empty() )
+	{
+		VRLog( "Unable to read VR Path Registry from %s\n", sRegPath.c_str() );
+		return false;
+	}
+
+	Json::Value root;
+	Json::Reader reader;
+
+	if( !reader.parse( sRegistryContents, root ) )
+	{
+		VRLog( "Unable to parse %s: %s\n", sRegPath.c_str(), reader.getFormattedErrorMessages().c_str() );
+		return false;
+	}
+
+	ParseStringListFromJson( &m_vecRuntimePath, root, "runtime" );
+	ParseStringListFromJson( &m_vecConfigPath, root, "config" );
+	ParseStringListFromJson( &m_vecLogPath, root, "log" );
+	if (root.isMember( "external_drivers" ) && root[ "external_drivers" ].isArray() )
+	{
+		ParseStringListFromJson( &m_vecExternalDrivers, root, "external_drivers" );
+	}
+
+	return true;
+}
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Saves the config file to its well known location
+// ---------------------------------------------------------------------------
+bool CVRPathRegistry_Public::BSaveToFile() const
+{
+#if defined( DASHBOARD_BUILD_MODE )
+	return false;
+#else
+	std::string sRegPath = GetVRPathRegistryFilename();
+	if( sRegPath.empty() )
+		return false;
+	
+	Json::Value root;
+	
+	root[ "version" ] = 1;
+	root[ "jsonid" ] = "vrpathreg";
+
+	StringListToJson( m_vecRuntimePath, root, "runtime" );
+	StringListToJson( m_vecConfigPath, root, "config" );
+	StringListToJson( m_vecLogPath, root, "log" );
+	StringListToJson( m_vecExternalDrivers, root, "external_drivers" );
+
+	Json::StyledWriter writer;
+	std::string sRegistryContents = writer.write( root );
+
+	// make sure the directory we're writing into actually exists
+	std::string sRegDirectory = Path_StripFilename( sRegPath );
+	if( !BCreateDirectoryRecursive( sRegDirectory.c_str() ) )
+	{
+		VRLog( "Unable to create path registry directory %s\n", sRegDirectory.c_str() );
+		return false;
+	}
+
+	if( !Path_WriteStringToTextFile( sRegPath, sRegistryContents.c_str() ) )
+	{
+		VRLog( "Unable to write VR path registry to %s\n", sRegPath.c_str() );
+		return false;
+	}
+
+	return true;
+#endif
+}
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Returns the current runtime path or NULL if no path is configured.
+// ---------------------------------------------------------------------------
+std::string CVRPathRegistry_Public::GetRuntimePath() const
+{
+	if( m_vecRuntimePath.empty() )
+		return "";
+	else
+		return m_vecRuntimePath.front().c_str();
+}
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Returns the current config path or NULL if no path is configured.
+// ---------------------------------------------------------------------------
+std::string CVRPathRegistry_Public::GetConfigPath() const
+{
+	if( m_vecConfigPath.empty() )
+		return "";
+	else
+		return m_vecConfigPath.front().c_str();
+}
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Returns the current log path or NULL if no path is configured.
+// ---------------------------------------------------------------------------
+std::string CVRPathRegistry_Public::GetLogPath() const
+{
+	if( m_vecLogPath.empty() )
+		return "";
+	else
+		return m_vecLogPath.front().c_str();
+}
+
+
+
+// ---------------------------------------------------------------------------
+// Purpose: Returns paths using the path registry and the provided override 
+//			values. Pass NULL for any paths you don't care about.
+// ---------------------------------------------------------------------------
+bool CVRPathRegistry_Public::GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers )
+{
+	CVRPathRegistry_Public pathReg;
+	bool bLoadedRegistry = pathReg.BLoadFromFile();
+	int nCountEnvironmentVariables = 0;
+
+	if( psRuntimePath )
+	{
+		if ( GetEnvironmentVariable( k_pchRuntimeOverrideVar ).length() != 0 )
+		{
+			*psRuntimePath = GetEnvironmentVariable( k_pchRuntimeOverrideVar );
+			nCountEnvironmentVariables++;
+		}
+		else if( !pathReg.GetRuntimePath().empty() )
+		{
+			*psRuntimePath = pathReg.GetRuntimePath();
+		}
+		else
+		{
+			*psRuntimePath = "";
+		}
+	}
+
+	if( psConfigPath )
+	{
+		if ( GetEnvironmentVariable( k_pchConfigOverrideVar ).length() != 0 )
+		{
+			*psConfigPath = GetEnvironmentVariable( k_pchConfigOverrideVar );
+			nCountEnvironmentVariables++;
+		}
+		else if( pchConfigPathOverride )
+		{
+			*psConfigPath = pchConfigPathOverride;
+		}
+		else if( !pathReg.GetConfigPath().empty() )
+		{
+			*psConfigPath = pathReg.GetConfigPath();
+		}
+		else
+		{
+			*psConfigPath = "";
+		}
+	}
+
+	if( psLogPath )
+	{
+		if ( GetEnvironmentVariable( k_pchLogOverrideVar ).length() != 0 )
+		{
+			*psLogPath = GetEnvironmentVariable( k_pchLogOverrideVar );
+			nCountEnvironmentVariables++;
+		}
+		else if( pchLogPathOverride )
+		{
+			*psLogPath = pchLogPathOverride;
+		}
+		else if( !pathReg.GetLogPath().empty() )
+		{
+			*psLogPath = pathReg.GetLogPath();
+		}
+		else
+		{
+			*psLogPath = "";
+		}
+	}
+
+	if ( pvecExternalDrivers )
+	{
+		*pvecExternalDrivers = pathReg.m_vecExternalDrivers;
+	}
+
+	if ( nCountEnvironmentVariables == 3 )
+	{
+		// all three environment variables where set, so we don't need the physical file
+		return true;
+	}
+
+	return bLoadedRegistry;
+}
+
diff --git a/third_party/openvr/src/src/vrcommon/vrpathregistry_public.h b/third_party/openvr/src/src/vrcommon/vrpathregistry_public.h
new file mode 100644
index 0000000..4838a107c
--- /dev/null
+++ b/third_party/openvr/src/src/vrcommon/vrpathregistry_public.h
@@ -0,0 +1,45 @@
+//========= Copyright Valve Corporation ============//
+#pragma once
+
+#include <string>
+#include <vector>
+#include <stdint.h>
+
+static const char *k_pchRuntimeOverrideVar = "VR_OVERRIDE";
+static const char *k_pchConfigOverrideVar = "VR_CONFIG_PATH";
+static const char *k_pchLogOverrideVar = "VR_LOG_PATH";
+
+class CVRPathRegistry_Public
+{
+public:
+	static std::string GetVRPathRegistryFilename();
+	static std::string GetOpenVRConfigPath();
+
+public:
+	CVRPathRegistry_Public();
+
+	/** Returns paths using the path registry and the provided override values. Pass NULL for any paths you don't care about. 
+	* Returns false if the path registry could not be read. Valid paths might still be returned based on environment variables. */
+	static bool GetPaths( std::string *psRuntimePath, std::string *psConfigPath, std::string *psLogPath, const char *pchConfigPathOverride, const char *pchLogPathOverride, std::vector<std::string> *pvecExternalDrivers = NULL );
+
+	bool BLoadFromFile();
+	bool BSaveToFile() const;
+
+	bool ToJsonString( std::string &sJsonString );
+
+	// methods to get the current values
+	std::string GetRuntimePath() const;
+	std::string GetConfigPath() const;
+	std::string GetLogPath() const;
+
+protected:
+	typedef std::vector< std::string > StringVector_t;
+
+	// index 0 is the current setting
+	StringVector_t m_vecRuntimePath;
+	StringVector_t m_vecLogPath;
+	StringVector_t m_vecConfigPath;
+
+	// full list of external drivers
+	StringVector_t m_vecExternalDrivers;
+};
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 210951c..16964cc 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -513,6 +513,7 @@
       'chromeos_daisy_chromium_compile_only_ng': 'cros_chrome_sdk',
       'chromeos_x86-generic_chromium_compile_only_ng': 'cros_chrome_sdk',
       'closure_compilation': 'closure_compilation',
+      'fuchsia': 'release_trybot_fuchsia',
       'linux_arm': 'release_trybot_arm',
       'linux_chromium_archive_rel_ng': 'release_bot',
       'linux_chromium_asan_rel_ng': 'asan_lsan_release_trybot',
@@ -1438,6 +1439,10 @@
       'release_trybot', 'arm',
     ],
 
+    'release_trybot_fuchsia': [
+      'release_trybot', 'fuchsia',
+    ],
+
     'release_trybot_x86': [
       'release_trybot', 'x86',
     ],
diff --git a/ui/app_list/folder_image.cc b/ui/app_list/folder_image.cc
index eff0712..47513c8 100644
--- a/ui/app_list/folder_image.cc
+++ b/ui/app_list/folder_image.cc
@@ -19,7 +19,6 @@
 #include "ui/gfx/image/canvas_image_source.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_operations.h"
-#include "ui/strings/grit/ui_strings.h"
 
 namespace app_list {
 
diff --git a/ui/app_list/views/all_apps_tile_item_view.cc b/ui/app_list/views/all_apps_tile_item_view.cc
index 1cc2690..a2bfb8a 100644
--- a/ui/app_list/views/all_apps_tile_item_view.cc
+++ b/ui/app_list/views/all_apps_tile_item_view.cc
@@ -12,7 +12,6 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/image/canvas_image_source.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/strings/grit/ui_strings.h"
 
 namespace app_list {
diff --git a/ui/app_list/views/folder_header_view.cc b/ui/app_list/views/folder_header_view.cc
index 706f7eab..47a196d 100644
--- a/ui/app_list/views/folder_header_view.cc
+++ b/ui/app_list/views/folder_header_view.cc
@@ -11,7 +11,6 @@
 #include "ui/app_list/app_list_constants.h"
 #include "ui/app_list/app_list_folder_item.h"
 #include "ui/app_list/app_list_switches.h"
-#include "ui/app_list/resources/grit/app_list_resources.h"
 #include "ui/app_list/views/app_list_folder_view.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/canvas.h"
diff --git a/ui/base/cocoa/three_part_image_unittest.mm b/ui/base/cocoa/three_part_image_unittest.mm
index a517ae33..2c9d0d07 100644
--- a/ui/base/cocoa/three_part_image_unittest.mm
+++ b/ui/base/cocoa/three_part_image_unittest.mm
@@ -14,7 +14,6 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_unittest_util.h"
 #import "ui/gfx/test/ui_cocoa_test_helper.h"
-#include "ui/resources/grit/ui_resources.h"
 
 namespace ui {
 namespace test {
diff --git a/ui/base/resource/resource_bundle_unittest.cc b/ui/base/resource/resource_bundle_unittest.cc
index f9156ac..df11f1a 100644
--- a/ui/base/resource/resource_bundle_unittest.cc
+++ b/ui/base/resource/resource_bundle_unittest.cc
@@ -26,8 +26,6 @@
 #include "ui/gfx/codec/png_codec.h"
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/image/image_skia.h"
-#include "ui/resources/grit/ui_resources.h"
-#include "ui/strings/grit/app_locale_settings.h"
 
 #if defined(OS_WIN)
 #include "ui/display/win/dpi.h"
diff --git a/ui/file_manager/file_manager/background/js/file_operation_util.js b/ui/file_manager/file_manager/background/js/file_operation_util.js
index 1a7b337..4b1ae2a 100644
--- a/ui/file_manager/file_manager/background/js/file_operation_util.js
+++ b/ui/file_manager/file_manager/background/js/file_operation_util.js
@@ -411,6 +411,9 @@
           break;
 
         case 'error':
+          console.error(
+              'copy failed. sourceUrl: ' + source.toURL() +
+              ' error: ' + status.error);
           chrome.fileManagerPrivate.onCopyProgress.removeListener(
               onCopyProgress);
           errorCallback(util.createDOMError(status.error));
diff --git a/ui/message_center/views/message_center_bubble.cc b/ui/message_center/views/message_center_bubble.cc
index 8ecf7a5..ad76cef 100644
--- a/ui/message_center/views/message_center_bubble.cc
+++ b/ui/message_center/views/message_center_bubble.cc
@@ -5,10 +5,8 @@
 #include "ui/message_center/views/message_center_bubble.h"
 
 #include "base/macros.h"
-#include "ui/base/l10n/l10n_util.h"
 #include "ui/message_center/message_center_style.h"
 #include "ui/message_center/views/message_center_view.h"
-#include "ui/strings/grit/ui_strings.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/widget/widget.h"
 
diff --git a/ui/message_center/views/message_center_view.cc b/ui/message_center/views/message_center_view.cc
index 89bd7a1..d760442 100644
--- a/ui/message_center/views/message_center_view.cc
+++ b/ui/message_center/views/message_center_view.cc
@@ -28,7 +28,6 @@
 #include "ui/message_center/views/message_view_context_menu_controller.h"
 #include "ui/message_center/views/message_view_factory.h"
 #include "ui/message_center/views/notifier_settings_view.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc
index 6559660..a951c10a 100644
--- a/ui/message_center/views/message_view.cc
+++ b/ui/message_center/views/message_view.cc
@@ -16,8 +16,6 @@
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/message_center_style.h"
 #include "ui/message_center/views/message_center_controller.h"
-#include "ui/resources/grit/ui_resources.h"
-#include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/button/image_button.h"
diff --git a/ui/message_center/views/notification_view.cc b/ui/message_center/views/notification_view.cc
index 5fdf772..89fec2e 100644
--- a/ui/message_center/views/notification_view.cc
+++ b/ui/message_center/views/notification_view.cc
@@ -31,7 +31,6 @@
 #include "ui/message_center/views/padded_button.h"
 #include "ui/message_center/views/proportional_image_view.h"
 #include "ui/native_theme/native_theme.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/border.h"
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc
index ddb2eb0..09216e0 100644
--- a/ui/native_theme/common_theme.cc
+++ b/ui/native_theme/common_theme.cc
@@ -15,7 +15,6 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/skia_util.h"
-#include "ui/resources/grit/ui_resources.h"
 
 namespace ui {
 
diff --git a/ui/native_theme/native_theme_base.cc b/ui/native_theme/native_theme_base.cc
index 4a2fb95..d36a2c3 100644
--- a/ui/native_theme/native_theme_base.cc
+++ b/ui/native_theme/native_theme_base.cc
@@ -25,7 +25,6 @@
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/skia_util.h"
 #include "ui/native_theme/common_theme.h"
-#include "ui/resources/grit/ui_resources.h"
 
 namespace {
 
diff --git a/ui/views/button_drag_utils.cc b/ui/views/button_drag_utils.cc
index 230fb8e..cb6b611 100644
--- a/ui/views/button_drag_utils.cc
+++ b/ui/views/button_drag_utils.cc
@@ -18,7 +18,6 @@
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/label_button_border.h"
 #include "ui/views/drag_utils.h"
-#include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/widget/widget.h"
 #include "url/gurl.h"
 
diff --git a/ui/views/controls/button/blue_button.cc b/ui/views/controls/button/blue_button.cc
index a81677f..fcebb90d 100644
--- a/ui/views/controls/button/blue_button.cc
+++ b/ui/views/controls/button/blue_button.cc
@@ -9,7 +9,6 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/geometry/vector2d.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/controls/button/label_button_border.h"
 #include "ui/views/resources/grit/views_resources.h"
 
diff --git a/ui/views/controls/button/checkbox.cc b/ui/views/controls/button/checkbox.cc
index 6e2dccd..1438fc4 100644
--- a/ui/views/controls/button/checkbox.cc
+++ b/ui/views/controls/button/checkbox.cc
@@ -14,7 +14,6 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/animation/ink_drop_highlight.h"
 #include "ui/views/animation/ink_drop_ripple.h"
 #include "ui/views/animation/square_ink_drop_ripple.h"
diff --git a/ui/views/controls/button/label_button_border.cc b/ui/views/controls/button/label_button_border.cc
index cc6e983..5cd89f4e 100644
--- a/ui/views/controls/button/label_button_border.cc
+++ b/ui/views/controls/button/label_button_border.cc
@@ -13,7 +13,6 @@
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/sys_color_change_listener.h"
 #include "ui/native_theme/native_theme.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/border.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/native_theme_delegate.h"
diff --git a/ui/views/controls/button/menu_button.cc b/ui/views/controls/button/menu_button.cc
index 83ad60f3..0e4194e 100644
--- a/ui/views/controls/button/menu_button.cc
+++ b/ui/views/controls/button/menu_button.cc
@@ -19,7 +19,6 @@
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/button/menu_button_listener.h"
 #include "ui/views/mouse_constants.h"
-#include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/widget/root_view.h"
 #include "ui/views/widget/widget.h"
 
diff --git a/ui/views/controls/button/radio_button.cc b/ui/views/controls/button/radio_button.cc
index ca85989..5786210 100644
--- a/ui/views/controls/button/radio_button.cc
+++ b/ui/views/controls/button/radio_button.cc
@@ -10,7 +10,6 @@
 #include "ui/events/event_utils.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/paint_vector_icon.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/vector_icons.h"
 #include "ui/views/widget/widget.h"
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index 5b15552..06be5f0 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -19,7 +19,6 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/text_utils.h"
 #include "ui/native_theme/common_theme.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/image_view.h"
@@ -29,7 +28,6 @@
 #include "ui/views/controls/menu/menu_scroll_view_container.h"
 #include "ui/views/controls/menu/menu_separator.h"
 #include "ui/views/controls/menu/submenu_view.h"
-#include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/widget/widget.h"
 
 namespace views {
diff --git a/ui/views/controls/slider.cc b/ui/views/controls/slider.cc
index 48f0732..eaa903c 100644
--- a/ui/views/controls/slider.cc
+++ b/ui/views/controls/slider.cc
@@ -21,8 +21,6 @@
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/native_theme/native_theme.h"
-#include "ui/resources/grit/ui_resources.h"
-#include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/widget/widget.h"
 
 namespace {
diff --git a/ui/views/controls/throbber.cc b/ui/views/controls/throbber.cc
index 7194bd3..cc92263 100644
--- a/ui/views/controls/throbber.cc
+++ b/ui/views/controls/throbber.cc
@@ -15,9 +15,7 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/native_theme/common_theme.h"
 #include "ui/native_theme/native_theme.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/vector_icons/vector_icons.h"
-#include "ui/views/resources/grit/views_resources.h"
 
 namespace views {
 
diff --git a/ui/views/examples/button_example.cc b/ui/views/examples/button_example.cc
index 8075f1a7..353718d 100644
--- a/ui/views/examples/button_example.cc
+++ b/ui/views/examples/button_example.cc
@@ -7,7 +7,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/image/image.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/button/blue_button.h"
 #include "ui/views/controls/button/image_button.h"
diff --git a/ui/views/style/platform_style.cc b/ui/views/style/platform_style.cc
index bf6d767..0b7ed2f4 100644
--- a/ui/views/style/platform_style.cc
+++ b/ui/views/style/platform_style.cc
@@ -10,7 +10,6 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/shadow_value.h"
 #include "ui/native_theme/native_theme.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/label_button_border.h"
diff --git a/ui/views/touchui/touch_selection_controller_impl.cc b/ui/views/touchui/touch_selection_controller_impl.cc
index d70efd74f..0597090 100644
--- a/ui/views/touchui/touch_selection_controller_impl.cc
+++ b/ui/views/touchui/touch_selection_controller_impl.cc
@@ -17,8 +17,6 @@
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/path.h"
 #include "ui/resources/grit/ui_resources.h"
-#include "ui/strings/grit/ui_strings.h"
-#include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/wm/core/coordinate_conversion.h"
diff --git a/ui/views/touchui/touch_selection_controller_impl_unittest.cc b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
index 4743062..27be28e 100644
--- a/ui/views/touchui/touch_selection_controller_impl_unittest.cc
+++ b/ui/views/touchui/touch_selection_controller_impl_unittest.cc
@@ -21,10 +21,8 @@
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/render_text.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/controls/textfield/textfield_test_api.h"
-#include "ui/views/resources/grit/views_resources.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/touchui/touch_selection_controller_impl.h"
 #include "ui/views/views_touch_selection_controller_factory.h"
diff --git a/ui/views/touchui/touch_selection_menu_runner_views_unittest.cc b/ui/views/touchui/touch_selection_menu_runner_views_unittest.cc
index 428a7c2..281ebd7 100644
--- a/ui/views/touchui/touch_selection_menu_runner_views_unittest.cc
+++ b/ui/views/touchui/touch_selection_menu_runner_views_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "base/macros.h"
 #include "ui/events/event_utils.h"
-#include "ui/strings/grit/ui_strings.h"
 #include "ui/touch_selection/touch_selection_menu_runner.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/test/views_test_base.h"
diff --git a/ui/views/window/custom_frame_view.cc b/ui/views/window/custom_frame_view.cc
index 27a5316..a2eaafc2 100644
--- a/ui/views/window/custom_frame_view.cc
+++ b/ui/views/window/custom_frame_view.cc
@@ -17,7 +17,6 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/path.h"
-#include "ui/resources/grit/ui_resources.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/resources/grit/views_resources.h"
diff --git a/ui/wm/BUILD.gn b/ui/wm/BUILD.gn
index bf2496b..caaa3db 100644
--- a/ui/wm/BUILD.gn
+++ b/ui/wm/BUILD.gn
@@ -54,15 +54,15 @@
     "core/window_modality_controller.h",
     "core/window_util.cc",
     "core/window_util.h",
+    "core/wm_core_export.h",
     "core/wm_core_switches.cc",
     "core/wm_core_switches.h",
     "core/wm_state.cc",
     "core/wm_state.h",
-    "wm_export.h",
   ]
 
   configs += [ "//build/config:precompiled_headers" ]
-  defines = [ "WM_IMPLEMENTATION" ]
+  defines = [ "WM_CORE_IMPLEMENTATION" ]
 
   deps = [
     "//base",
diff --git a/ui/wm/core/accelerator_filter.h b/ui/wm/core/accelerator_filter.h
index ed042a7..492ab6c 100644
--- a/ui/wm/core/accelerator_filter.h
+++ b/ui/wm/core/accelerator_filter.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "ui/events/event_handler.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace ui {
 class AcceleratorHistory;
@@ -20,7 +20,7 @@
 
 // AcceleratorFilter filters key events for AcceleratorControler handling global
 // keyboard accelerators.
-class WM_EXPORT AcceleratorFilter : public ui::EventHandler {
+class WM_CORE_EXPORT AcceleratorFilter : public ui::EventHandler {
  public:
   // AcceleratorFilter doesn't own |accelerator_history|, it's owned by
   // AcceleratorController.
diff --git a/ui/wm/core/base_focus_rules.h b/ui/wm/core/base_focus_rules.h
index 990a368..6adf8794 100644
--- a/ui/wm/core/base_focus_rules.h
+++ b/ui/wm/core/base_focus_rules.h
@@ -13,7 +13,7 @@
 
 // A set of basic focus and activation rules. Specializations should most likely
 // subclass this and call up to these methods rather than reimplementing them.
-class WM_EXPORT BaseFocusRules : public FocusRules {
+class WM_CORE_EXPORT BaseFocusRules : public FocusRules {
  protected:
   BaseFocusRules();
   ~BaseFocusRules() override;
diff --git a/ui/wm/core/capture_controller.h b/ui/wm/core/capture_controller.h
index 53481ab..d304bc4 100644
--- a/ui/wm/core/capture_controller.h
+++ b/ui/wm/core/capture_controller.h
@@ -11,7 +11,7 @@
 #include "base/observer_list.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/window_observer.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 namespace client {
@@ -22,7 +22,7 @@
 namespace wm {
 
 // Internal CaptureClient implementation. See ScopedCaptureClient for details.
-class WM_EXPORT CaptureController : public aura::client::CaptureClient {
+class WM_CORE_EXPORT CaptureController : public aura::client::CaptureClient {
  public:
   CaptureController();
   ~CaptureController() override;
@@ -72,9 +72,9 @@
 // ScopedCaptureClient is responsible for creating a CaptureClient for a
 // RootWindow. Specifically it creates a single CaptureController that is shared
 // among all ScopedCaptureClients and adds the RootWindow to it.
-class WM_EXPORT ScopedCaptureClient : public aura::WindowObserver {
+class WM_CORE_EXPORT ScopedCaptureClient : public aura::WindowObserver {
  public:
-  class WM_EXPORT TestApi {
+  class WM_CORE_EXPORT TestApi {
    public:
     explicit TestApi(ScopedCaptureClient* client) : client_(client) {}
     ~TestApi() {}
diff --git a/ui/wm/core/compound_event_filter.h b/ui/wm/core/compound_event_filter.h
index 34b78aa..0a39e1a 100644
--- a/ui/wm/core/compound_event_filter.h
+++ b/ui/wm/core/compound_event_filter.h
@@ -11,7 +11,7 @@
 #include "ui/events/event.h"
 #include "ui/events/event_handler.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace ui {
 class GestureEvent;
@@ -32,7 +32,7 @@
 // consumed by any of those filters. If an event is consumed by a filter, the
 // rest of the filter(s) and CompoundEventFilter will not see the consumed
 // event.
-class WM_EXPORT CompoundEventFilter : public ui::EventHandler {
+class WM_CORE_EXPORT CompoundEventFilter : public ui::EventHandler {
  public:
   CompoundEventFilter();
   ~CompoundEventFilter() override;
diff --git a/ui/wm/core/coordinate_conversion.h b/ui/wm/core/coordinate_conversion.h
index 4b987fcb..43bbe9c6 100644
--- a/ui/wm/core/coordinate_conversion.h
+++ b/ui/wm/core/coordinate_conversion.h
@@ -5,7 +5,7 @@
 #ifndef UI_WM_CORE_COORDINATE_CONVERSION_H_
 #define UI_WM_CORE_COORDINATE_CONVERSION_H_
 
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 class Window;
@@ -20,22 +20,23 @@
 
 // Converts the |point| from a given |window|'s coordinates into the screen
 // coordinates.
-WM_EXPORT void ConvertPointToScreen(const aura::Window* window,
-                                    gfx::Point* point);
+WM_CORE_EXPORT void ConvertPointToScreen(const aura::Window* window,
+                                         gfx::Point* point);
 
 // Converts the |point| from the screen coordinates to a given |window|'s
 // coordinates.
-WM_EXPORT void ConvertPointFromScreen(const aura::Window* window,
-                                      gfx::Point* point_in_screen);
+WM_CORE_EXPORT void ConvertPointFromScreen(const aura::Window* window,
+                                           gfx::Point* point_in_screen);
 
 // Converts |rect| from |window|'s coordinates to the virtual screen
 // coordinates.
-WM_EXPORT void ConvertRectToScreen(const aura::Window* window, gfx::Rect* rect);
+WM_CORE_EXPORT void ConvertRectToScreen(const aura::Window* window,
+                                        gfx::Rect* rect);
 
 // Converts |rect| from virtual screen coordinates to the |window|'s
 // coordinates.
-WM_EXPORT void ConvertRectFromScreen(const aura::Window* window,
-                                     gfx::Rect* rect_in_screen);
+WM_CORE_EXPORT void ConvertRectFromScreen(const aura::Window* window,
+                                          gfx::Rect* rect_in_screen);
 
 }  // namespace wm
 
diff --git a/ui/wm/core/cursor_manager.h b/ui/wm/core/cursor_manager.h
index 01e15a6..cce4f83 100644
--- a/ui/wm/core/cursor_manager.h
+++ b/ui/wm/core/cursor_manager.h
@@ -15,7 +15,7 @@
 #include "ui/gfx/geometry/point.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/wm/core/native_cursor_manager_delegate.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace ui {
 class KeyEvent;
@@ -33,8 +33,8 @@
 // requests to queue any further changes until a later time. It sends changes
 // to the NativeCursorManager, which communicates back to us when these changes
 // were made through the NativeCursorManagerDelegate interface.
-class WM_EXPORT CursorManager : public aura::client::CursorClient,
-                                public NativeCursorManagerDelegate {
+class WM_CORE_EXPORT CursorManager : public aura::client::CursorClient,
+                                     public NativeCursorManagerDelegate {
  public:
   explicit CursorManager(std::unique_ptr<NativeCursorManager> delegate);
   ~CursorManager() override;
diff --git a/ui/wm/core/default_activation_client.h b/ui/wm/core/default_activation_client.h
index cd776578..41e9e95 100644
--- a/ui/wm/core/default_activation_client.h
+++ b/ui/wm/core/default_activation_client.h
@@ -12,9 +12,9 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "ui/aura/window_observer.h"
+#include "ui/wm/core/wm_core_export.h"
 #include "ui/wm/public/activation_change_observer.h"
 #include "ui/wm/public/activation_client.h"
-#include "ui/wm/wm_export.h"
 
 namespace wm {
 
@@ -24,8 +24,8 @@
 // that just need basic behavior (e.g. activate windows whenever requested,
 // restack windows at the top when they're activated, etc.). This object deletes
 // itself when the root window it is associated with is destroyed.
-class WM_EXPORT DefaultActivationClient : public ActivationClient,
-                                          public aura::WindowObserver {
+class WM_CORE_EXPORT DefaultActivationClient : public ActivationClient,
+                                               public aura::WindowObserver {
  public:
   explicit DefaultActivationClient(aura::Window* root_window);
 
diff --git a/ui/wm/core/default_screen_position_client.h b/ui/wm/core/default_screen_position_client.h
index 3c7bfa3f..285620b 100644
--- a/ui/wm/core/default_screen_position_client.h
+++ b/ui/wm/core/default_screen_position_client.h
@@ -7,13 +7,13 @@
 
 #include "base/macros.h"
 #include "ui/aura/client/screen_position_client.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
 // Client that always offsets by the toplevel RootWindow of the passed
 // in child NativeWidgetAura.
-class WM_EXPORT DefaultScreenPositionClient
+class WM_CORE_EXPORT DefaultScreenPositionClient
     : public aura::client::ScreenPositionClient {
  public:
   DefaultScreenPositionClient();
diff --git a/ui/wm/core/easy_resize_window_targeter.h b/ui/wm/core/easy_resize_window_targeter.h
index 7ff604731..ea4df53 100644
--- a/ui/wm/core/easy_resize_window_targeter.h
+++ b/ui/wm/core/easy_resize_window_targeter.h
@@ -8,13 +8,13 @@
 #include "base/macros.h"
 #include "ui/aura/window_targeter.h"
 #include "ui/gfx/geometry/insets.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
 // An EventTargeter for a container window that uses a slightly larger
 // hit-target region for easier resize.
-class WM_EXPORT EasyResizeWindowTargeter : public aura::WindowTargeter {
+class WM_CORE_EXPORT EasyResizeWindowTargeter : public aura::WindowTargeter {
  public:
   // |container| window is the owner of this targeter.
   EasyResizeWindowTargeter(aura::Window* container,
diff --git a/ui/wm/core/focus_controller.h b/ui/wm/core/focus_controller.h
index 2da7173..702a4ee 100644
--- a/ui/wm/core/focus_controller.h
+++ b/ui/wm/core/focus_controller.h
@@ -14,9 +14,9 @@
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/window_observer.h"
 #include "ui/events/event_handler.h"
+#include "ui/wm/core/wm_core_export.h"
 #include "ui/wm/public/activation_change_observer.h"
 #include "ui/wm/public/activation_client.h"
-#include "ui/wm/wm_export.h"
 
 namespace wm {
 
@@ -40,10 +40,10 @@
 // . ActivationReason::WINDOW_DISPOSITION_CHANGED: Window disposition changes
 //   (implemented here in aura::WindowObserver). (The FocusController registers
 //   itself as an observer of the active and focused windows).
-class WM_EXPORT FocusController : public ActivationClient,
-                                  public aura::client::FocusClient,
-                                  public ui::EventHandler,
-                                  public aura::WindowObserver {
+class WM_CORE_EXPORT FocusController : public ActivationClient,
+                                       public aura::client::FocusClient,
+                                       public ui::EventHandler,
+                                       public aura::WindowObserver {
  public:
   // |rules| cannot be NULL.
   explicit FocusController(FocusRules* rules);
diff --git a/ui/wm/core/focus_rules.h b/ui/wm/core/focus_rules.h
index b8d0874..8a29541 100644
--- a/ui/wm/core/focus_rules.h
+++ b/ui/wm/core/focus_rules.h
@@ -5,7 +5,7 @@
 #ifndef UI_WM_CORE_FOCUS_RULES_H_
 #define UI_WM_CORE_FOCUS_RULES_H_
 
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 class Window;
@@ -19,7 +19,7 @@
 
 // Implemented by an object that establishes the rules about what can be
 // focused or activated.
-class WM_EXPORT FocusRules {
+class WM_CORE_EXPORT FocusRules {
  public:
   virtual ~FocusRules() {}
 
diff --git a/ui/wm/core/ime_util_chromeos.h b/ui/wm/core/ime_util_chromeos.h
index 39ed2228..4a50a65 100644
--- a/ui/wm/core/ime_util_chromeos.h
+++ b/ui/wm/core/ime_util_chromeos.h
@@ -6,7 +6,7 @@
 #define UI_WM_CORE_IME_UTIL_CHROMEOS_H_
 
 #include "ui/aura/window.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace gfx {
 class Rect;
@@ -16,16 +16,16 @@
 
 // A property key to store the restore bounds for a window when moved by the
 // virtual keyboard.
-WM_EXPORT extern const aura::WindowProperty<gfx::Rect*>* const
+WM_CORE_EXPORT extern const aura::WindowProperty<gfx::Rect*>* const
     kVirtualKeyboardRestoreBoundsKey;
 
 // Moves the window, if needed, to ensure it does not intersect with
 // |rect_in_screen|.
-WM_EXPORT void EnsureWindowNotInRect(aura::Window* window,
-                                     const gfx::Rect& rect_in_screen);
+WM_CORE_EXPORT void EnsureWindowNotInRect(aura::Window* window,
+                                          const gfx::Rect& rect_in_screen);
 
 // Restores the window bounds when input client loses the focus on the window.
-WM_EXPORT void RestoreWindowBoundsOnClientFocusLost(
+WM_CORE_EXPORT void RestoreWindowBoundsOnClientFocusLost(
     aura::Window* top_level_window);
 
 }  // namespace wm
diff --git a/ui/wm/core/masked_window_targeter.h b/ui/wm/core/masked_window_targeter.h
index 940aa66..272fde90 100644
--- a/ui/wm/core/masked_window_targeter.h
+++ b/ui/wm/core/masked_window_targeter.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "ui/aura/window_targeter.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace gfx {
 class Path;
@@ -15,7 +15,7 @@
 
 namespace wm {
 
-class WM_EXPORT MaskedWindowTargeter : public aura::WindowTargeter {
+class WM_CORE_EXPORT MaskedWindowTargeter : public aura::WindowTargeter {
  public:
   explicit MaskedWindowTargeter(aura::Window* masked_window);
   ~MaskedWindowTargeter() override;
diff --git a/ui/wm/core/native_cursor_manager.h b/ui/wm/core/native_cursor_manager.h
index 32afef71..c3be247 100644
--- a/ui/wm/core/native_cursor_manager.h
+++ b/ui/wm/core/native_cursor_manager.h
@@ -8,7 +8,7 @@
 #include "base/strings/string16.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/wm/core/native_cursor_manager_delegate.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace display {
 class Display;
@@ -20,7 +20,7 @@
 // requested changes to cursor state. When requested, implementer should tell
 // the CursorManager of any actual state changes performed through the
 // delegate.
-class WM_EXPORT NativeCursorManager {
+class WM_CORE_EXPORT NativeCursorManager {
  public:
   virtual ~NativeCursorManager() {}
 
diff --git a/ui/wm/core/native_cursor_manager_delegate.h b/ui/wm/core/native_cursor_manager_delegate.h
index 1393b2cd..aad9825 100644
--- a/ui/wm/core/native_cursor_manager_delegate.h
+++ b/ui/wm/core/native_cursor_manager_delegate.h
@@ -7,14 +7,14 @@
 
 #include "ui/base/cursor/cursor.h"
 #include "ui/gfx/native_widget_types.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
 // The non-public interface that CursorManager exposes to its users. This
 // gives accessors to all the current state, and mutators to all the current
 // state.
-class WM_EXPORT NativeCursorManagerDelegate {
+class WM_CORE_EXPORT NativeCursorManagerDelegate {
  public:
   virtual ~NativeCursorManagerDelegate() {}
 
diff --git a/ui/wm/core/shadow.h b/ui/wm/core/shadow.h
index 35c57f6..ad816cb2 100644
--- a/ui/wm/core/shadow.h
+++ b/ui/wm/core/shadow.h
@@ -10,7 +10,7 @@
 #include "base/macros.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/gfx/geometry/rect.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace ui {
 class Layer;
@@ -20,7 +20,7 @@
 enum class ShadowElevation;
 
 // Simple class that draws a drop shadow around content at given bounds.
-class WM_EXPORT Shadow : public ui::ImplicitAnimationObserver {
+class WM_CORE_EXPORT Shadow : public ui::ImplicitAnimationObserver {
  public:
   Shadow();
   ~Shadow() override;
diff --git a/ui/wm/core/shadow_controller.h b/ui/wm/core/shadow_controller.h
index c867ff0..34ac15a 100644
--- a/ui/wm/core/shadow_controller.h
+++ b/ui/wm/core/shadow_controller.h
@@ -11,8 +11,8 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "ui/wm/core/shadow_types.h"
+#include "ui/wm/core/wm_core_export.h"
 #include "ui/wm/public/activation_change_observer.h"
-#include "ui/wm/wm_export.h"
 
 namespace aura {
 class Window;
@@ -27,7 +27,7 @@
 // shadows as needed. ShadowController itself is light weight and per
 // ActivationClient. ShadowController delegates to its implementation class,
 // which observes all window creation.
-class WM_EXPORT ShadowController : public ActivationChangeObserver {
+class WM_CORE_EXPORT ShadowController : public ActivationChangeObserver {
  public:
   static constexpr ShadowElevation kActiveNormalShadowElevation =
       ShadowElevation::LARGE;
diff --git a/ui/wm/core/shadow_types.cc b/ui/wm/core/shadow_types.cc
index fc205e7..21163f5 100644
--- a/ui/wm/core/shadow_types.cc
+++ b/ui/wm/core/shadow_types.cc
@@ -6,7 +6,7 @@
 
 #include "ui/base/class_property.h"
 
-DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_EXPORT, ::wm::ShadowElevation);
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_CORE_EXPORT, ::wm::ShadowElevation);
 
 namespace wm {
 
diff --git a/ui/wm/core/shadow_types.h b/ui/wm/core/shadow_types.h
index f980188..578b04e 100644
--- a/ui/wm/core/shadow_types.h
+++ b/ui/wm/core/shadow_types.h
@@ -6,7 +6,7 @@
 #define UI_WM_CORE_SHADOW_TYPES_H_
 
 #include "ui/aura/window.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
@@ -24,15 +24,15 @@
   LARGE = 24,
 };
 
-WM_EXPORT void SetShadowElevation(aura::Window* window,
-                                  ShadowElevation elevation);
+WM_CORE_EXPORT void SetShadowElevation(aura::Window* window,
+                                       ShadowElevation elevation);
 
 // Returns true if |value| is a valid element of ShadowElevation elements.
-WM_EXPORT bool IsValidShadowElevation(int64_t value);
+WM_CORE_EXPORT bool IsValidShadowElevation(int64_t value);
 
 // A property key describing the drop shadow that should be displayed under the
 // window. A null value is interpreted as using the default.
-WM_EXPORT extern const aura::WindowProperty<ShadowElevation>* const
+WM_CORE_EXPORT extern const aura::WindowProperty<ShadowElevation>* const
     kShadowElevationKey;
 
 }  // namespace wm
diff --git a/ui/wm/core/transient_window_controller.h b/ui/wm/core/transient_window_controller.h
index 1f7a0c4..2794926 100644
--- a/ui/wm/core/transient_window_controller.h
+++ b/ui/wm/core/transient_window_controller.h
@@ -8,7 +8,7 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "ui/aura/client/transient_window_client.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
@@ -16,7 +16,7 @@
 
 // TransientWindowClient implementation. Uses TransientWindowManager to handle
 // tracking transient per window.
-class WM_EXPORT TransientWindowController
+class WM_CORE_EXPORT TransientWindowController
     : public aura::client::TransientWindowClient {
  public:
   TransientWindowController();
diff --git a/ui/wm/core/transient_window_manager.h b/ui/wm/core/transient_window_manager.h
index 9389954..ee6f3d9 100644
--- a/ui/wm/core/transient_window_manager.h
+++ b/ui/wm/core/transient_window_manager.h
@@ -10,7 +10,7 @@
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "ui/aura/window_observer.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
@@ -29,7 +29,7 @@
 // Transient windows are typically used for popups and menus.
 // TODO(sky): when we nuke TransientWindowClient rename this to
 // TransientWindowController.
-class WM_EXPORT TransientWindowManager : public aura::WindowObserver {
+class WM_CORE_EXPORT TransientWindowManager : public aura::WindowObserver {
  public:
   typedef std::vector<aura::Window*> Windows;
 
diff --git a/ui/wm/core/transient_window_observer.h b/ui/wm/core/transient_window_observer.h
index aff5af5..6a7a2e2 100644
--- a/ui/wm/core/transient_window_observer.h
+++ b/ui/wm/core/transient_window_observer.h
@@ -5,7 +5,7 @@
 #ifndef UI_WM_CORE_TRANSIENT_WINDOW_OBSERVER_H_
 #define UI_WM_CORE_TRANSIENT_WINDOW_OBSERVER_H_
 
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 class Window;
@@ -13,7 +13,7 @@
 
 namespace wm {
 
-class WM_EXPORT TransientWindowObserver {
+class WM_CORE_EXPORT TransientWindowObserver {
  public:
   // Called when a transient child is added to |window|.
   virtual void OnTransientChildAdded(aura::Window* window,
diff --git a/ui/wm/core/transient_window_stacking_client.h b/ui/wm/core/transient_window_stacking_client.h
index 2b3e04a..0f6840d 100644
--- a/ui/wm/core/transient_window_stacking_client.h
+++ b/ui/wm/core/transient_window_stacking_client.h
@@ -7,13 +7,13 @@
 
 #include "base/macros.h"
 #include "ui/aura/client/window_stacking_client.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
 class TransientWindowManager;
 
-class WM_EXPORT TransientWindowStackingClient
+class WM_CORE_EXPORT TransientWindowStackingClient
     : public aura::client::WindowStackingClient {
  public:
   TransientWindowStackingClient();
diff --git a/ui/wm/core/visibility_controller.h b/ui/wm/core/visibility_controller.h
index cb50673a..0f06bdc6 100644
--- a/ui/wm/core/visibility_controller.h
+++ b/ui/wm/core/visibility_controller.h
@@ -9,11 +9,11 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "ui/aura/client/visibility_client.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
-class WM_EXPORT VisibilityController
+class WM_CORE_EXPORT VisibilityController
     : public aura::client::VisibilityClient {
  public:
   VisibilityController();
@@ -47,7 +47,7 @@
 //   // previous state.
 // }
 //
-class WM_EXPORT SuspendChildWindowVisibilityAnimations {
+class WM_CORE_EXPORT SuspendChildWindowVisibilityAnimations {
  public:
   // Suspend visibility animations of child windows.
   explicit SuspendChildWindowVisibilityAnimations(aura::Window* window);
@@ -71,13 +71,13 @@
 // whose animation is already enabled either by this function, or
 // via SetChildWindowVisibilityChangesAnimatedbelow below is allowed and
 // the animation stays enabled.
-void WM_EXPORT SetWindowVisibilityChangesAnimated(aura::Window* window);
+void WM_CORE_EXPORT SetWindowVisibilityChangesAnimated(aura::Window* window);
 
 // Enable visibility change animation for all children of the |window|.
 // Typically applied to a container whose child windows should be animated
 // when their visibility changes.
-void WM_EXPORT SetChildWindowVisibilityChangesAnimated(
-    aura::Window* window);
+void WM_CORE_EXPORT
+SetChildWindowVisibilityChangesAnimated(aura::Window* window);
 
 }  // namespace wm
 
diff --git a/ui/wm/core/window_animations.h b/ui/wm/core/window_animations.h
index b2c1ad7..5986234 100644
--- a/ui/wm/core/window_animations.h
+++ b/ui/wm/core/window_animations.h
@@ -9,7 +9,7 @@
 
 #include "base/macros.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 class Window;
@@ -51,25 +51,26 @@
 
 // These two methods use int for type rather than WindowVisibilityAnimationType
 // since downstream libraries can extend the set of animations.
-WM_EXPORT void SetWindowVisibilityAnimationType(aura::Window* window, int type);
-WM_EXPORT int GetWindowVisibilityAnimationType(aura::Window* window);
+WM_CORE_EXPORT void SetWindowVisibilityAnimationType(aura::Window* window,
+                                                     int type);
+WM_CORE_EXPORT int GetWindowVisibilityAnimationType(aura::Window* window);
 
-WM_EXPORT void SetWindowVisibilityAnimationTransition(
+WM_CORE_EXPORT void SetWindowVisibilityAnimationTransition(
     aura::Window* window,
     WindowVisibilityAnimationTransition transition);
 
-WM_EXPORT bool HasWindowVisibilityAnimationTransition(
+WM_CORE_EXPORT bool HasWindowVisibilityAnimationTransition(
     aura::Window* window,
     WindowVisibilityAnimationTransition transition);
 
-WM_EXPORT void SetWindowVisibilityAnimationDuration(
+WM_CORE_EXPORT void SetWindowVisibilityAnimationDuration(
     aura::Window* window,
     const base::TimeDelta& duration);
 
-WM_EXPORT base::TimeDelta GetWindowVisibilityAnimationDuration(
+WM_CORE_EXPORT base::TimeDelta GetWindowVisibilityAnimationDuration(
     const aura::Window& window);
 
-WM_EXPORT void SetWindowVisibilityAnimationVerticalPosition(
+WM_CORE_EXPORT void SetWindowVisibilityAnimationVerticalPosition(
     aura::Window* window,
     float position);
 
@@ -78,7 +79,7 @@
 // Use this to ensure that the hiding animation is visible even after
 // the window is deleted or deactivated, instead of using
 // ui::ScopedLayerAnimationSettings directly.
-class WM_EXPORT ScopedHidingAnimationSettings {
+class WM_CORE_EXPORT ScopedHidingAnimationSettings {
  public:
   explicit ScopedHidingAnimationSettings(aura::Window* window);
   ~ScopedHidingAnimationSettings();
@@ -96,14 +97,15 @@
 };
 
 // Returns false if the |window| didn't animate.
-WM_EXPORT bool AnimateOnChildWindowVisibilityChanged(aura::Window* window,
-                                                     bool visible);
-WM_EXPORT bool AnimateWindow(aura::Window* window, WindowAnimationType type);
+WM_CORE_EXPORT bool AnimateOnChildWindowVisibilityChanged(aura::Window* window,
+                                                          bool visible);
+WM_CORE_EXPORT bool AnimateWindow(aura::Window* window,
+                                  WindowAnimationType type);
 
 // Returns true if window animations are disabled for |window|. Window
 // animations are enabled by default. If |window| is NULL, this just checks
 // if the global flag disabling window animations is present.
-WM_EXPORT bool WindowAnimationsDisabled(aura::Window* window);
+WM_CORE_EXPORT bool WindowAnimationsDisabled(aura::Window* window);
 
 }  // namespace wm
 
diff --git a/ui/wm/core/window_modality_controller.h b/ui/wm/core/window_modality_controller.h
index 106db131..c833f083 100644
--- a/ui/wm/core/window_modality_controller.h
+++ b/ui/wm/core/window_modality_controller.h
@@ -12,7 +12,7 @@
 #include "ui/aura/env_observer.h"
 #include "ui/aura/window_observer.h"
 #include "ui/events/event_handler.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace ui {
 class EventTarget;
@@ -22,18 +22,18 @@
 namespace wm {
 
 // Sets the modal parent for the child.
-WM_EXPORT void SetModalParent(aura::Window* child, aura::Window* parent);
+WM_CORE_EXPORT void SetModalParent(aura::Window* child, aura::Window* parent);
 
 // Returns the modal transient child of |window|, or NULL if |window| does not
 // have any modal transient children.
-WM_EXPORT aura::Window* GetModalTransient(aura::Window* window);
+WM_CORE_EXPORT aura::Window* GetModalTransient(aura::Window* window);
 
 // WindowModalityController is an event filter that consumes events sent to
 // windows that are the transient parents of window-modal windows. This filter
 // must be added to the CompoundEventFilter so that activation works properly.
-class WM_EXPORT WindowModalityController : public ui::EventHandler,
-                                           public aura::EnvObserver,
-                                           public aura::WindowObserver {
+class WM_CORE_EXPORT WindowModalityController : public ui::EventHandler,
+                                                public aura::EnvObserver,
+                                                public aura::WindowObserver {
  public:
   explicit WindowModalityController(ui::EventTarget* event_target);
   ~WindowModalityController() override;
diff --git a/ui/wm/core/window_util.h b/ui/wm/core/window_util.h
index 8c699c0..27c5400 100644
--- a/ui/wm/core/window_util.h
+++ b/ui/wm/core/window_util.h
@@ -11,7 +11,7 @@
 
 #include "base/callback_forward.h"
 #include "base/compiler_specific.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace aura {
 class Window;
@@ -25,19 +25,19 @@
 
 namespace wm {
 
-WM_EXPORT void ActivateWindow(aura::Window* window);
-WM_EXPORT void DeactivateWindow(aura::Window* window);
-WM_EXPORT bool IsActiveWindow(const aura::Window* window);
-WM_EXPORT bool CanActivateWindow(aura::Window* window);
-WM_EXPORT void SetWindowFullscreen(aura::Window* window, bool fullscreen);
+WM_CORE_EXPORT void ActivateWindow(aura::Window* window);
+WM_CORE_EXPORT void DeactivateWindow(aura::Window* window);
+WM_CORE_EXPORT bool IsActiveWindow(const aura::Window* window);
+WM_CORE_EXPORT bool CanActivateWindow(aura::Window* window);
+WM_CORE_EXPORT void SetWindowFullscreen(aura::Window* window, bool fullscreen);
 
 // Retrieves the activatable window for |window|. The ActivationClient makes
 // this determination.
-WM_EXPORT aura::Window* GetActivatableWindow(aura::Window* window);
+WM_CORE_EXPORT aura::Window* GetActivatableWindow(aura::Window* window);
 
 // Retrieves the toplevel window for |window|. The ActivationClient makes this
 // determination.
-WM_EXPORT aura::Window* GetToplevelWindow(aura::Window* window);
+WM_CORE_EXPORT aura::Window* GetToplevelWindow(aura::Window* window);
 
 // Returns the existing Layer for |root| (and all its descendants) and creates
 // a new layer for |root| and all its descendants. This is intended for
@@ -45,7 +45,7 @@
 //
 // As a result of this |root| has freshly created layers, meaning the layers
 // have not yet been painted to.
-WM_EXPORT std::unique_ptr<ui::LayerTreeOwner> RecreateLayers(
+WM_CORE_EXPORT std::unique_ptr<ui::LayerTreeOwner> RecreateLayers(
     ui::LayerOwner* root);
 
 using MapLayerFunc =
@@ -55,31 +55,34 @@
 // layer tree. The recursion stops at the level when |map_func| returns nullptr
 // on the owner's layer. MapLayers might return nullptr when |map_func| returns
 // nullptr on the root layer's owner.
-WM_EXPORT std::unique_ptr<ui::LayerTreeOwner> RecreateLayersWithClosure(
+WM_CORE_EXPORT std::unique_ptr<ui::LayerTreeOwner> RecreateLayersWithClosure(
     ui::LayerOwner* root,
     const MapLayerFunc& map_func);
 
 // Returns a layer tree that mirrors |root|. Used for live window previews. If
 // |sync_bounds| is true, the bounds of all mirror layers except the root are
 // synchronized. See |sync_bounds_| in ui::Layer.
-WM_EXPORT std::unique_ptr<ui::LayerTreeOwner> MirrorLayers(
-    ui::LayerOwner* root, bool sync_bounds);
+WM_CORE_EXPORT std::unique_ptr<ui::LayerTreeOwner> MirrorLayers(
+    ui::LayerOwner* root,
+    bool sync_bounds);
 
 // Convenience functions that get the TransientWindowManager for the window and
 // redirect appropriately. These are preferable to calling functions on
 // TransientWindowManager as they handle the appropriate NULL checks.
-WM_EXPORT aura::Window* GetTransientParent(aura::Window* window);
-WM_EXPORT const aura::Window* GetTransientParent(
+WM_CORE_EXPORT aura::Window* GetTransientParent(aura::Window* window);
+WM_CORE_EXPORT const aura::Window* GetTransientParent(
     const aura::Window* window);
-WM_EXPORT const std::vector<aura::Window*>& GetTransientChildren(
+WM_CORE_EXPORT const std::vector<aura::Window*>& GetTransientChildren(
     const aura::Window* window);
-WM_EXPORT void AddTransientChild(aura::Window* parent, aura::Window* child);
-WM_EXPORT void RemoveTransientChild(aura::Window* parent, aura::Window* child);
+WM_CORE_EXPORT void AddTransientChild(aura::Window* parent,
+                                      aura::Window* child);
+WM_CORE_EXPORT void RemoveTransientChild(aura::Window* parent,
+                                         aura::Window* child);
 
 // Returns true if |window| has |ancestor| as a transient ancestor. A transient
 // ancestor is found by following the transient parent chain of the window.
-WM_EXPORT bool HasTransientAncestor(const aura::Window* window,
-                                    const aura::Window* ancestor);
+WM_CORE_EXPORT bool HasTransientAncestor(const aura::Window* window,
+                                         const aura::Window* ancestor);
 
 }  // namespace wm
 
diff --git a/ui/wm/core/wm_core_export.h b/ui/wm/core/wm_core_export.h
new file mode 100644
index 0000000..c033ddc
--- /dev/null
+++ b/ui/wm/core/wm_core_export.h
@@ -0,0 +1,32 @@
+// 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 UI_WM_CORE_WM_CORE_EXPORT_H_
+#define UI_WM_CORE_WM_CORE_EXPORT_H_
+
+// Defines WM_CORE_EXPORT so that functionality implemented by the WM module
+// can be exported to consumers.
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(WM_CORE_IMPLEMENTATION)
+#define WM_CORE_EXPORT __declspec(dllexport)
+#else
+#define WM_CORE_EXPORT __declspec(dllimport)
+#endif  // defined(WM_CORE_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(WM_CORE_IMPLEMENTATION)
+#define WM_CORE_EXPORT __attribute__((visibility("default")))
+#else
+#define WM_CORE_EXPORT
+#endif
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define WM_CORE_EXPORT
+#endif
+
+#endif  // UI_WM_CORE_WM_CORE_EXPORT_H_
diff --git a/ui/wm/core/wm_core_switches.h b/ui/wm/core/wm_core_switches.h
index 05658d6a..dd48025 100644
--- a/ui/wm/core/wm_core_switches.h
+++ b/ui/wm/core/wm_core_switches.h
@@ -6,7 +6,7 @@
 #define UI_WM_CORE_WM_CORE_SWITCHES_H_
 
 #include "build/build_config.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 namespace switches {
@@ -16,7 +16,7 @@
 // see chromeos::LoginUtil::GetOffTheRecordCommandLine().)
 
 // Please keep alphabetized.
-WM_EXPORT extern const char kWindowAnimationsDisabled[];
+WM_CORE_EXPORT extern const char kWindowAnimationsDisabled[];
 
 }  // namespace switches
 }  // namespace wm
diff --git a/ui/wm/core/wm_state.h b/ui/wm/core/wm_state.h
index 5337ec4..d659509 100644
--- a/ui/wm/core/wm_state.h
+++ b/ui/wm/core/wm_state.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "ui/wm/wm_export.h"
+#include "ui/wm/core/wm_core_export.h"
 
 namespace wm {
 
@@ -17,7 +17,7 @@
 class TransientWindowStackingClient;
 
 // Installs state needed by the window manager.
-class WM_EXPORT WMState {
+class WM_CORE_EXPORT WMState {
  public:
   WMState();
   ~WMState();
diff --git a/ui/wm/wm_export.h b/ui/wm/wm_export.h
deleted file mode 100644
index 461d693..0000000
--- a/ui/wm/wm_export.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// 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 UI_WM_WM_EXPORT_H_
-#define UI_WM_WM_EXPORT_H_
-
-// Defines WM_EXPORT so that functionality implemented by the WM module
-// can be exported to consumers.
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(WM_IMPLEMENTATION)
-#define WM_EXPORT __declspec(dllexport)
-#else
-#define WM_EXPORT __declspec(dllimport)
-#endif  // defined(WM_IMPLEMENTATION)
-
-#else  // defined(WIN32)
-#if defined(WM_IMPLEMENTATION)
-#define WM_EXPORT __attribute__((visibility("default")))
-#else
-#define WM_EXPORT
-#endif
-#endif
-
-#else  // defined(COMPONENT_BUILD)
-#define WM_EXPORT
-#endif
-
-#endif  // UI_WM_WM_EXPORT_H_