From d9a584844a60542519d813b5dc1a62428f14a0ae Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Thu, 19 Jun 2014 17:03:28 +0200
Subject: Add OculusSDK 0.3.2 Linux Source Code w/o Samples, docs or binaries
 (libs or tools)

---
 LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp       |   73 +
 LibOVR/Src/CAPI/CAPI_DistortionRenderer.h         |  118 +
 LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp         |  675 ++++++
 LibOVR/Src/CAPI/CAPI_FrameTimeManager.h           |  264 +++
 LibOVR/Src/CAPI/CAPI_GlobalState.cpp              |  142 ++
 LibOVR/Src/CAPI/CAPI_GlobalState.h                |   84 +
 LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp           |  143 ++
 LibOVR/Src/CAPI/CAPI_HMDRenderState.h             |   93 +
 LibOVR/Src/CAPI/CAPI_HMDState.cpp                 |  804 +++++++
 LibOVR/Src/CAPI/CAPI_HMDState.h                   |  347 +++
 LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp |  784 +++++++
 LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h   |  178 ++
 LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h    |  326 +++
 LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp               |  530 +++++
 LibOVR/Src/CAPI/GL/CAPI_GL_Util.h                 |  537 +++++
 LibOVR/Src/Kernel/OVR_Alg.cpp                     |   57 +
 LibOVR/Src/Kernel/OVR_Alg.h                       | 1060 +++++++++
 LibOVR/Src/Kernel/OVR_Allocator.cpp               |   95 +
 LibOVR/Src/Kernel/OVR_Allocator.h                 |  347 +++
 LibOVR/Src/Kernel/OVR_Array.h                     |  833 +++++++
 LibOVR/Src/Kernel/OVR_Atomic.cpp                  |  162 ++
 LibOVR/Src/Kernel/OVR_Atomic.h                    |  890 ++++++++
 LibOVR/Src/Kernel/OVR_Color.h                     |   66 +
 LibOVR/Src/Kernel/OVR_ContainerAllocator.h        |  267 +++
 LibOVR/Src/Kernel/OVR_Deque.h                     |  296 +++
 LibOVR/Src/Kernel/OVR_File.cpp                    |  582 +++++
 LibOVR/Src/Kernel/OVR_File.h                      |  529 +++++
 LibOVR/Src/Kernel/OVR_FileFILE.cpp                |  595 +++++
 LibOVR/Src/Kernel/OVR_Hash.h                      | 1302 +++++++++++
 LibOVR/Src/Kernel/OVR_KeyCodes.h                  |  251 ++
 LibOVR/Src/Kernel/OVR_List.h                      |  336 +++
 LibOVR/Src/Kernel/OVR_Lockless.cpp                |  231 ++
 LibOVR/Src/Kernel/OVR_Lockless.h                  |  107 +
 LibOVR/Src/Kernel/OVR_Log.cpp                     |  184 ++
 LibOVR/Src/Kernel/OVR_Log.h                       |  204 ++
 LibOVR/Src/Kernel/OVR_Math.cpp                    |   91 +
 LibOVR/Src/Kernel/OVR_Math.h                      | 2526 +++++++++++++++++++++
 LibOVR/Src/Kernel/OVR_RefCount.cpp                |  111 +
 LibOVR/Src/Kernel/OVR_RefCount.h                  |  564 +++++
 LibOVR/Src/Kernel/OVR_Std.cpp                     | 1036 +++++++++
 LibOVR/Src/Kernel/OVR_Std.h                       |  514 +++++
 LibOVR/Src/Kernel/OVR_String.cpp                  |  768 +++++++
 LibOVR/Src/Kernel/OVR_String.h                    |  657 ++++++
 LibOVR/Src/Kernel/OVR_StringHash.h                |  100 +
 LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp       |   53 +
 LibOVR/Src/Kernel/OVR_String_PathUtil.cpp         |  211 ++
 LibOVR/Src/Kernel/OVR_SysFile.cpp                 |  138 ++
 LibOVR/Src/Kernel/OVR_SysFile.h                   |  104 +
 LibOVR/Src/Kernel/OVR_System.cpp                  |   81 +
 LibOVR/Src/Kernel/OVR_System.h                    |   78 +
 LibOVR/Src/Kernel/OVR_Threads.h                   |  407 ++++
 LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp          |  787 +++++++
 LibOVR/Src/Kernel/OVR_Timer.cpp                   |  287 +++
 LibOVR/Src/Kernel/OVR_Timer.h                     |   88 +
 LibOVR/Src/Kernel/OVR_Types.h                     |  474 ++++
 LibOVR/Src/Kernel/OVR_UTF8Util.cpp                |  556 +++++
 LibOVR/Src/Kernel/OVR_UTF8Util.h                  |   99 +
 LibOVR/Src/OVR_CAPI.cpp                           |  925 ++++++++
 LibOVR/Src/OVR_CAPI.h                             |  790 +++++++
 LibOVR/Src/OVR_CAPI_GL.h                          |   73 +
 LibOVR/Src/OVR_Common_HMDDevice.cpp               |  384 ++++
 LibOVR/Src/OVR_Device.h                           | 1135 +++++++++
 LibOVR/Src/OVR_DeviceConstants.h                  |  142 ++
 LibOVR/Src/OVR_DeviceHandle.cpp                   |  185 ++
 LibOVR/Src/OVR_DeviceHandle.h                     |  108 +
 LibOVR/Src/OVR_DeviceImpl.cpp                     |  794 +++++++
 LibOVR/Src/OVR_DeviceImpl.h                       |  428 ++++
 LibOVR/Src/OVR_DeviceMessages.h                   |  273 +++
 LibOVR/Src/OVR_HIDDevice.h                        |  154 ++
 LibOVR/Src/OVR_HIDDeviceBase.h                    |   51 +
 LibOVR/Src/OVR_HIDDeviceImpl.h                    |  201 ++
 LibOVR/Src/OVR_JSON.cpp                           | 1185 ++++++++++
 LibOVR/Src/OVR_JSON.h                             |  164 ++
 LibOVR/Src/OVR_LatencyTestImpl.cpp                |  773 +++++++
 LibOVR/Src/OVR_LatencyTestImpl.h                  |  144 ++
 LibOVR/Src/OVR_Linux_DeviceManager.cpp            |  331 +++
 LibOVR/Src/OVR_Linux_DeviceManager.h              |  122 +
 LibOVR/Src/OVR_Linux_HIDDevice.cpp                |  819 +++++++
 LibOVR/Src/OVR_Linux_HIDDevice.h                  |  135 ++
 LibOVR/Src/OVR_Linux_HMDDevice.cpp                |  291 +++
 LibOVR/Src/OVR_Linux_HMDDevice.h                  |  154 ++
 LibOVR/Src/OVR_Linux_SensorDevice.cpp             |   57 +
 LibOVR/Src/OVR_Profile.cpp                        | 1517 +++++++++++++
 LibOVR/Src/OVR_Profile.h                          |  203 ++
 LibOVR/Src/OVR_Recording.cpp                      |   38 +
 LibOVR/Src/OVR_Recording.h                        |   83 +
 LibOVR/Src/OVR_Sensor2Impl.cpp                    | 1124 +++++++++
 LibOVR/Src/OVR_Sensor2Impl.h                      |  153 ++
 LibOVR/Src/OVR_Sensor2ImplUtil.h                  |  676 ++++++
 LibOVR/Src/OVR_SensorCalibration.cpp              |  354 +++
 LibOVR/Src/OVR_SensorCalibration.h                |   82 +
 LibOVR/Src/OVR_SensorFilter.cpp                   |   99 +
 LibOVR/Src/OVR_SensorFilter.h                     |  307 +++
 LibOVR/Src/OVR_SensorFusion.cpp                   |  904 ++++++++
 LibOVR/Src/OVR_SensorFusion.h                     |  582 +++++
 LibOVR/Src/OVR_SensorFusionDebug.h                |   82 +
 LibOVR/Src/OVR_SensorImpl.cpp                     | 1165 ++++++++++
 LibOVR/Src/OVR_SensorImpl.h                       |  316 +++
 LibOVR/Src/OVR_SensorImpl_Common.cpp              |  245 ++
 LibOVR/Src/OVR_SensorImpl_Common.h                |  150 ++
 LibOVR/Src/OVR_SensorTimeFilter.cpp               |  385 ++++
 LibOVR/Src/OVR_SensorTimeFilter.h                 |  226 ++
 LibOVR/Src/OVR_Stereo.cpp                         | 1805 +++++++++++++++
 LibOVR/Src/OVR_Stereo.h                           |  460 ++++
 LibOVR/Src/OVR_ThreadCommandQueue.cpp             |  380 ++++
 LibOVR/Src/OVR_ThreadCommandQueue.h               |  319 +++
 LibOVR/Src/Util/Util_ImageWindow.cpp              |  511 +++++
 LibOVR/Src/Util/Util_ImageWindow.h                |  200 ++
 LibOVR/Src/Util/Util_Interface.cpp                |   34 +
 LibOVR/Src/Util/Util_Interface.h                  |   37 +
 LibOVR/Src/Util/Util_LatencyTest.cpp              |  570 +++++
 LibOVR/Src/Util/Util_LatencyTest.h                |  173 ++
 LibOVR/Src/Util/Util_LatencyTest2.cpp             |  191 ++
 LibOVR/Src/Util/Util_LatencyTest2.h               |  238 ++
 LibOVR/Src/Util/Util_Render_Stereo.cpp            | 1472 ++++++++++++
 LibOVR/Src/Util/Util_Render_Stereo.h              |  498 ++++
 116 files changed, 48619 insertions(+)
 create mode 100644 LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp
 create mode 100644 LibOVR/Src/CAPI/CAPI_DistortionRenderer.h
 create mode 100644 LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp
 create mode 100644 LibOVR/Src/CAPI/CAPI_FrameTimeManager.h
 create mode 100644 LibOVR/Src/CAPI/CAPI_GlobalState.cpp
 create mode 100644 LibOVR/Src/CAPI/CAPI_GlobalState.h
 create mode 100644 LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp
 create mode 100644 LibOVR/Src/CAPI/CAPI_HMDRenderState.h
 create mode 100644 LibOVR/Src/CAPI/CAPI_HMDState.cpp
 create mode 100644 LibOVR/Src/CAPI/CAPI_HMDState.h
 create mode 100644 LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp
 create mode 100644 LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h
 create mode 100644 LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h
 create mode 100644 LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp
 create mode 100644 LibOVR/Src/CAPI/GL/CAPI_GL_Util.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Alg.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Alg.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Allocator.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Allocator.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Array.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Atomic.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Atomic.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Color.h
 create mode 100644 LibOVR/Src/Kernel/OVR_ContainerAllocator.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Deque.h
 create mode 100644 LibOVR/Src/Kernel/OVR_File.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_File.h
 create mode 100644 LibOVR/Src/Kernel/OVR_FileFILE.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Hash.h
 create mode 100644 LibOVR/Src/Kernel/OVR_KeyCodes.h
 create mode 100644 LibOVR/Src/Kernel/OVR_List.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Lockless.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Lockless.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Log.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Log.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Math.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Math.h
 create mode 100644 LibOVR/Src/Kernel/OVR_RefCount.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_RefCount.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Std.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Std.h
 create mode 100644 LibOVR/Src/Kernel/OVR_String.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_String.h
 create mode 100644 LibOVR/Src/Kernel/OVR_StringHash.h
 create mode 100644 LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_String_PathUtil.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_SysFile.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_SysFile.h
 create mode 100644 LibOVR/Src/Kernel/OVR_System.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_System.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Threads.h
 create mode 100644 LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Timer.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_Timer.h
 create mode 100644 LibOVR/Src/Kernel/OVR_Types.h
 create mode 100644 LibOVR/Src/Kernel/OVR_UTF8Util.cpp
 create mode 100644 LibOVR/Src/Kernel/OVR_UTF8Util.h
 create mode 100644 LibOVR/Src/OVR_CAPI.cpp
 create mode 100644 LibOVR/Src/OVR_CAPI.h
 create mode 100644 LibOVR/Src/OVR_CAPI_GL.h
 create mode 100644 LibOVR/Src/OVR_Common_HMDDevice.cpp
 create mode 100644 LibOVR/Src/OVR_Device.h
 create mode 100644 LibOVR/Src/OVR_DeviceConstants.h
 create mode 100644 LibOVR/Src/OVR_DeviceHandle.cpp
 create mode 100644 LibOVR/Src/OVR_DeviceHandle.h
 create mode 100644 LibOVR/Src/OVR_DeviceImpl.cpp
 create mode 100644 LibOVR/Src/OVR_DeviceImpl.h
 create mode 100644 LibOVR/Src/OVR_DeviceMessages.h
 create mode 100644 LibOVR/Src/OVR_HIDDevice.h
 create mode 100644 LibOVR/Src/OVR_HIDDeviceBase.h
 create mode 100644 LibOVR/Src/OVR_HIDDeviceImpl.h
 create mode 100644 LibOVR/Src/OVR_JSON.cpp
 create mode 100644 LibOVR/Src/OVR_JSON.h
 create mode 100644 LibOVR/Src/OVR_LatencyTestImpl.cpp
 create mode 100644 LibOVR/Src/OVR_LatencyTestImpl.h
 create mode 100644 LibOVR/Src/OVR_Linux_DeviceManager.cpp
 create mode 100644 LibOVR/Src/OVR_Linux_DeviceManager.h
 create mode 100644 LibOVR/Src/OVR_Linux_HIDDevice.cpp
 create mode 100644 LibOVR/Src/OVR_Linux_HIDDevice.h
 create mode 100644 LibOVR/Src/OVR_Linux_HMDDevice.cpp
 create mode 100644 LibOVR/Src/OVR_Linux_HMDDevice.h
 create mode 100644 LibOVR/Src/OVR_Linux_SensorDevice.cpp
 create mode 100644 LibOVR/Src/OVR_Profile.cpp
 create mode 100644 LibOVR/Src/OVR_Profile.h
 create mode 100644 LibOVR/Src/OVR_Recording.cpp
 create mode 100644 LibOVR/Src/OVR_Recording.h
 create mode 100644 LibOVR/Src/OVR_Sensor2Impl.cpp
 create mode 100644 LibOVR/Src/OVR_Sensor2Impl.h
 create mode 100644 LibOVR/Src/OVR_Sensor2ImplUtil.h
 create mode 100644 LibOVR/Src/OVR_SensorCalibration.cpp
 create mode 100644 LibOVR/Src/OVR_SensorCalibration.h
 create mode 100644 LibOVR/Src/OVR_SensorFilter.cpp
 create mode 100644 LibOVR/Src/OVR_SensorFilter.h
 create mode 100644 LibOVR/Src/OVR_SensorFusion.cpp
 create mode 100644 LibOVR/Src/OVR_SensorFusion.h
 create mode 100644 LibOVR/Src/OVR_SensorFusionDebug.h
 create mode 100644 LibOVR/Src/OVR_SensorImpl.cpp
 create mode 100644 LibOVR/Src/OVR_SensorImpl.h
 create mode 100644 LibOVR/Src/OVR_SensorImpl_Common.cpp
 create mode 100644 LibOVR/Src/OVR_SensorImpl_Common.h
 create mode 100644 LibOVR/Src/OVR_SensorTimeFilter.cpp
 create mode 100644 LibOVR/Src/OVR_SensorTimeFilter.h
 create mode 100644 LibOVR/Src/OVR_Stereo.cpp
 create mode 100644 LibOVR/Src/OVR_Stereo.h
 create mode 100644 LibOVR/Src/OVR_ThreadCommandQueue.cpp
 create mode 100644 LibOVR/Src/OVR_ThreadCommandQueue.h
 create mode 100644 LibOVR/Src/Util/Util_ImageWindow.cpp
 create mode 100644 LibOVR/Src/Util/Util_ImageWindow.h
 create mode 100644 LibOVR/Src/Util/Util_Interface.cpp
 create mode 100644 LibOVR/Src/Util/Util_Interface.h
 create mode 100644 LibOVR/Src/Util/Util_LatencyTest.cpp
 create mode 100644 LibOVR/Src/Util/Util_LatencyTest.h
 create mode 100644 LibOVR/Src/Util/Util_LatencyTest2.cpp
 create mode 100644 LibOVR/Src/Util/Util_LatencyTest2.h
 create mode 100644 LibOVR/Src/Util/Util_Render_Stereo.cpp
 create mode 100644 LibOVR/Src/Util/Util_Render_Stereo.h

(limited to 'LibOVR/Src')

diff --git a/LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp
new file mode 100644
index 0000000..613d8fb
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp
@@ -0,0 +1,73 @@
+/************************************************************************************
+
+Filename    :   CAPI_DistortionRenderer.cpp
+Content     :   Combines all of the rendering state associated with the HMD
+Created     :   February 2, 2014
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "CAPI_DistortionRenderer.h"
+
+#if defined (OVR_OS_WIN32)
+
+// TBD: Move to separate config file that handles back-ends.
+#define OVR_D3D_VERSION 11
+#include "D3D1X/CAPI_D3D1X_DistortionRenderer.h"
+#undef OVR_D3D_VERSION
+
+#define OVR_D3D_VERSION 10
+#include "D3D1X/CAPI_D3D1X_DistortionRenderer.h"
+#undef OVR_D3D_VERSION
+
+#define OVR_D3D_VERSION 9
+#include "D3D1X/CAPI_D3D9_DistortionRenderer.h"
+#undef OVR_D3D_VERSION
+
+#endif
+
+#include "GL/CAPI_GL_DistortionRenderer.h"
+
+namespace OVR { namespace CAPI {
+
+//-------------------------------------------------------------------------------------
+// ***** DistortionRenderer
+
+// TBD: Move to separate config file that handles back-ends.
+
+DistortionRenderer::CreateFunc DistortionRenderer::APICreateRegistry[ovrRenderAPI_Count] =
+{
+    0, // None
+    &GL::DistortionRenderer::Create,
+    0, // Android_GLES
+#if defined (OVR_OS_WIN32)
+    &D3D9::DistortionRenderer::Create,
+    &D3D10::DistortionRenderer::Create,
+    &D3D11::DistortionRenderer::Create
+#else
+    0,
+    0,
+    0
+#endif
+};
+
+
+}} // namespace OVR::CAPI
+
diff --git a/LibOVR/Src/CAPI/CAPI_DistortionRenderer.h b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.h
new file mode 100644
index 0000000..a256bc6
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.h
@@ -0,0 +1,118 @@
+/************************************************************************************
+
+Filename    :   CAPI_DistortionRenderer.h
+Content     :   Abstract interface for platform-specific rendering of distortion
+Created     :   February 2, 2014
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_CAPI_DistortionRenderer_h
+#define OVR_CAPI_DistortionRenderer_h
+
+#include "CAPI_HMDRenderState.h"
+#include "CAPI_FrameTimeManager.h"
+
+
+namespace OVR { namespace CAPI {
+
+//-------------------------------------------------------------------------------------
+// ***** CAPI::DistortionRenderer
+
+// DistortionRenderer implements rendering of distortion and other overlay elements
+// in platform-independent way.
+// Platform-specific renderer back ends for CAPI are derived from this class.
+
+class  DistortionRenderer : public RefCountBase<DistortionRenderer>
+{
+    // Quiet assignment compiler warning.
+    void operator = (const DistortionRenderer&) { }
+public:
+    
+    DistortionRenderer(ovrRenderAPIType api, ovrHmd hmd,
+                       FrameTimeManager& timeManager,              
+                       const HMDRenderState& renderState)
+        : RenderAPI(api), HMD(hmd), TimeManager(timeManager), RState(renderState)
+    { }
+    virtual ~DistortionRenderer()
+    { }
+    
+
+    // Configures the Renderer based on externally passed API settings. Must be
+    // called before use.
+    // Under D3D, apiConfig includes D3D Device pointer, back buffer and other
+    // needed structures.
+    virtual bool Initialize(const ovrRenderAPIConfig* apiConfig,
+                            unsigned distortionCaps) = 0;
+
+    // Submits one eye texture for rendering. This is in the separate method to
+    // allow "submit as you render" scenarios on horizontal screens where one
+    // eye can be scanned out before the other.
+    virtual void SubmitEye(int eyeId, ovrTexture* eyeTexture) = 0;
+
+    // Finish the frame, optionally swapping buffers.
+    // Many implementations may actually apply the distortion here.
+    virtual void EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor,
+                                            unsigned char* latencyTester2DrawColor) = 0;
+    
+	// Stores the current graphics pipeline state so it can be restored later.
+	void SaveGraphicsState() { if (!(RState.EnabledHmdCaps & ovrHmdCap_NoRestore)) GfxState->Save(); }
+
+	// Restores the saved graphics pipeline state.
+	void RestoreGraphicsState() { if (!(RState.EnabledHmdCaps & ovrHmdCap_NoRestore)) GfxState->Restore(); }
+
+    // *** Creation Factory logic
+    
+    ovrRenderAPIType GetRenderAPI() const { return RenderAPI; }
+
+    // Creation function for this interface, registered for API.
+    typedef DistortionRenderer* (*CreateFunc)(ovrHmd hmd,
+                                              FrameTimeManager &timeManager,
+                                              const HMDRenderState& renderState);
+
+    static CreateFunc APICreateRegistry[ovrRenderAPI_Count];
+
+protected:
+    
+    class GraphicsState : public RefCountBase<GraphicsState>
+    {
+    public:
+        GraphicsState() : IsValid(false) {}
+        virtual ~GraphicsState() {}
+        virtual void Save() = 0;
+        virtual void Restore() = 0;
+        
+    protected:
+        bool IsValid;
+    };
+    
+    const ovrRenderAPIType  RenderAPI;
+    const ovrHmd            HMD;
+    FrameTimeManager&       TimeManager;
+    const HMDRenderState&   RState;
+    Ptr<GraphicsState>      GfxState;
+};
+
+}} // namespace OVR::CAPI
+
+
+#endif // OVR_CAPI_DistortionRenderer_h
+
+
diff --git a/LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp
new file mode 100644
index 0000000..3e776c3
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp
@@ -0,0 +1,675 @@
+/************************************************************************************
+
+Filename    :   CAPI_FrameTimeManager.cpp
+Content     :   Manage frame timing and pose prediction for rendering
+Created     :   November 30, 2013
+Authors     :   Volga Aksoy, Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "CAPI_FrameTimeManager.h"
+
+
+namespace OVR { namespace CAPI {
+
+
+//-------------------------------------------------------------------------------------
+// ***** FrameLatencyTracker
+    
+
+FrameLatencyTracker::FrameLatencyTracker()
+{
+   Reset();
+}
+
+void FrameLatencyTracker::Reset()
+{
+    TrackerEnabled         = true;
+    WaitMode               = SampleWait_Zeroes;
+    FrameIndex             = 0;    
+    MatchCount             = 0;
+    RenderLatencySeconds   = 0.0;
+    TimewarpLatencySeconds = 0.0;
+    
+    FrameDeltas.Clear();
+}
+
+
+unsigned char FrameLatencyTracker::GetNextDrawColor()
+{   
+    if (!TrackerEnabled || (WaitMode == SampleWait_Zeroes) ||
+        (FrameIndex >= FramesTracked))
+    {        
+        return (unsigned char)Util::FrameTimeRecord::ReadbackIndexToColor(0);
+    }
+
+    OVR_ASSERT(FrameIndex < FramesTracked);    
+    return (unsigned char)Util::FrameTimeRecord::ReadbackIndexToColor(FrameIndex+1);
+}
+
+
+void FrameLatencyTracker::SaveDrawColor(unsigned char drawColor, double endFrameTime,
+                                        double renderIMUTime, double timewarpIMUTime )
+{
+    if (!TrackerEnabled || (WaitMode == SampleWait_Zeroes))
+        return;
+
+    if (FrameIndex < FramesTracked)
+    {
+        OVR_ASSERT(Util::FrameTimeRecord::ReadbackIndexToColor(FrameIndex+1) == drawColor);
+        OVR_UNUSED(drawColor);
+
+        // saves {color, endFrame time}
+        FrameEndTimes[FrameIndex].ReadbackIndex         = FrameIndex + 1;
+        FrameEndTimes[FrameIndex].TimeSeconds           = endFrameTime;
+        FrameEndTimes[FrameIndex].RenderIMUTimeSeconds  = renderIMUTime;
+        FrameEndTimes[FrameIndex].TimewarpIMUTimeSeconds= timewarpIMUTime;
+        FrameEndTimes[FrameIndex].MatchedRecord         = false;
+        FrameIndex++;
+    }
+    else
+    {
+        // If the request was outstanding for too long, switch to zero mode to restart.
+        if (endFrameTime > (FrameEndTimes[FrameIndex-1].TimeSeconds + 0.15))
+        {
+            if (MatchCount == 0)
+            {
+                // If nothing was matched, we have no latency reading.
+                RenderLatencySeconds   = 0.0;
+                TimewarpLatencySeconds = 0.0;
+            }
+
+            WaitMode   =  SampleWait_Zeroes;
+            MatchCount = 0;
+            FrameIndex = 0;
+        }
+    }
+}
+
+
+void FrameLatencyTracker::MatchRecord(const Util::FrameTimeRecordSet &r)
+{
+    if (!TrackerEnabled)
+        return;
+
+    if (WaitMode == SampleWait_Zeroes)
+    {
+        // Do we have all zeros?
+        if (r.IsAllZeroes())
+        {
+            OVR_ASSERT(FrameIndex == 0);
+            WaitMode = SampleWait_Match;
+            MatchCount = 0;
+        }
+        return;
+    }
+
+    // We are in Match Mode. Wait until all colors are matched or timeout,
+    // at which point we go back to zeros.
+
+    for (int i = 0; i < FrameIndex; i++)
+    {
+        int recordIndex = 0;
+        int consecutiveMatch  = 0;
+
+        OVR_ASSERT(FrameEndTimes[i].ReadbackIndex != 0);
+
+        if (r.FindReadbackIndex(&recordIndex, FrameEndTimes[i].ReadbackIndex))
+        {
+            // Advance forward to see that we have several more matches.
+            int  ri = recordIndex + 1;
+            int  j  = i + 1;
+
+            consecutiveMatch++;
+
+            for (; (j < FrameIndex) && (ri < Util::FrameTimeRecordSet::RecordCount); j++, ri++)
+            {
+                if (r[ri].ReadbackIndex != FrameEndTimes[j].ReadbackIndex)
+                    break;
+                consecutiveMatch++;
+            }
+
+            // Match at least 2 items in the row, to avoid accidentally matching color.
+            if (consecutiveMatch > 1)
+            {
+                // Record latency values for all but last samples. Keep last 2 samples
+                // for the future to simplify matching.
+                for (int q = 0; q < consecutiveMatch; q++)
+                {
+                    const Util::FrameTimeRecord &scanoutFrame = r[recordIndex+q];
+                    FrameTimeRecordEx           &renderFrame  = FrameEndTimes[i+q];
+                    
+                    if (!renderFrame.MatchedRecord)
+                    {
+                        double deltaSeconds = scanoutFrame.TimeSeconds - renderFrame.TimeSeconds;
+                        if (deltaSeconds > 0.0)
+                        {
+                            FrameDeltas.AddTimeDelta(deltaSeconds);
+                            LatencyRecordTime      = scanoutFrame.TimeSeconds;
+                            RenderLatencySeconds   = scanoutFrame.TimeSeconds - renderFrame.RenderIMUTimeSeconds;
+                            TimewarpLatencySeconds = (renderFrame.TimewarpIMUTimeSeconds == 0.0)  ?  0.0 :
+                                                     (scanoutFrame.TimeSeconds - renderFrame.TimewarpIMUTimeSeconds);
+                        }
+
+                        renderFrame.MatchedRecord = true;
+                        MatchCount++;
+                    }
+                }
+
+                // Exit for.
+                break;
+            }
+        }
+    } // for ( i => FrameIndex )
+
+
+    // If we matched all frames, start over.
+    if (MatchCount == FramesTracked)
+    {
+        WaitMode   =  SampleWait_Zeroes;
+        MatchCount = 0;
+        FrameIndex = 0;
+    }
+}
+
+
+void FrameLatencyTracker::GetLatencyTimings(float latencies[3])
+{
+    if (ovr_GetTimeInSeconds() > (LatencyRecordTime + 2.0))
+    {
+        latencies[0] = 0.0f;
+        latencies[1] = 0.0f;
+        latencies[2] = 0.0f;
+    }
+    else
+    {
+        latencies[0] = (float)RenderLatencySeconds;
+        latencies[1] = (float)TimewarpLatencySeconds;
+        latencies[2] = (float)FrameDeltas.GetMedianTimeDelta();
+    }    
+}
+    
+    
+//-------------------------------------------------------------------------------------
+
+FrameTimeManager::FrameTimeManager(bool vsyncEnabled)
+    : VsyncEnabled(vsyncEnabled), DynamicPrediction(true), SdkRender(false),
+      FrameTiming()
+{    
+    RenderIMUTimeSeconds = 0.0;
+    TimewarpIMUTimeSeconds = 0.0;
+    
+    // HACK: SyncToScanoutDelay observed close to 1 frame in video cards.
+    //       Overwritten by dynamic latency measurement on DK2.
+    VSyncToScanoutDelay   = 0.013f;
+    NoVSyncToScanoutDelay = 0.004f;
+}
+
+void FrameTimeManager::Init(HmdRenderInfo& renderInfo)
+{
+    // Set up prediction distances.
+    // With-Vsync timings.
+    RenderInfo = renderInfo;
+
+    ScreenSwitchingDelay = RenderInfo.Shutter.PixelSettleTime * 0.5f + 
+                           RenderInfo.Shutter.PixelPersistence * 0.5f;
+}
+
+void FrameTimeManager::ResetFrameTiming(unsigned frameIndex,
+                                        bool dynamicPrediction,
+                                        bool sdkRender)
+{    
+    DynamicPrediction   = dynamicPrediction;
+    SdkRender           = sdkRender;
+
+    FrameTimeDeltas.Clear();
+    DistortionRenderTimes.Clear();
+    ScreenLatencyTracker.Reset();
+
+    FrameTiming.FrameIndex               = frameIndex;
+    FrameTiming.NextFrameTime            = 0.0;
+    FrameTiming.ThisFrameTime            = 0.0;
+    FrameTiming.Inputs.FrameDelta        = calcFrameDelta();
+    FrameTiming.Inputs.ScreenDelay       = calcScreenDelay();
+    FrameTiming.Inputs.TimewarpWaitDelta = 0.0f;
+
+    LocklessTiming.SetState(FrameTiming);
+}
+
+
+double  FrameTimeManager::calcFrameDelta() const
+{
+    // Timing difference between frame is tracked by FrameTimeDeltas, or
+    // is a hard-coded value of 1/FrameRate.
+    double  frameDelta;    
+
+    if (!VsyncEnabled)
+    {
+        frameDelta = 0.0;
+    }
+    else if (FrameTimeDeltas.GetCount() > 3)
+    {
+        frameDelta = FrameTimeDeltas.GetMedianTimeDelta();
+        if (frameDelta > (RenderInfo.Shutter.VsyncToNextVsync + 0.001))
+            frameDelta = RenderInfo.Shutter.VsyncToNextVsync;
+    }
+    else
+    {
+        frameDelta = RenderInfo.Shutter.VsyncToNextVsync;
+    }
+
+    return frameDelta;
+}
+
+
+double  FrameTimeManager::calcScreenDelay() const
+{
+    double  screenDelay = ScreenSwitchingDelay;
+    double  measuredVSyncToScanout;
+
+    // Use real-time DK2 latency tester HW for prediction if its is working.
+    // Do sanity check under 60 ms
+    if (!VsyncEnabled)
+    {
+        screenDelay += NoVSyncToScanoutDelay;
+    }
+    else if ( DynamicPrediction &&
+              (ScreenLatencyTracker.FrameDeltas.GetCount() > 3) &&
+              (measuredVSyncToScanout = ScreenLatencyTracker.FrameDeltas.GetMedianTimeDelta(),
+               (measuredVSyncToScanout > 0.0001) && (measuredVSyncToScanout < 0.06)) ) 
+    {
+        screenDelay += measuredVSyncToScanout;
+    }
+    else
+    {
+        screenDelay += VSyncToScanoutDelay;
+    }
+
+    return screenDelay;
+}
+
+
+double  FrameTimeManager::calcTimewarpWaitDelta() const
+{
+    // If timewarp timing hasn't been calculated, we should wait.
+    if (!VsyncEnabled)
+        return 0.0;
+
+    if (SdkRender)
+    {
+        if (NeedDistortionTimeMeasurement())
+            return 0.0;
+        return -(DistortionRenderTimes.GetMedianTimeDelta() + 0.002);
+    }
+   
+    // Just a hard-coded "high" value for game-drawn code.
+    // TBD: Just return 0 and let users calculate this themselves?
+    return -0.003;   
+}
+
+
+
+void FrameTimeManager::Timing::InitTimingFromInputs(const FrameTimeManager::TimingInputs& inputs,
+                                                    HmdShutterTypeEnum shutterType,
+                                                    double thisFrameTime, unsigned int frameIndex)
+{    
+    // ThisFrameTime comes from the end of last frame, unless it it changed.  
+    double  nextFrameBase;
+    double  frameDelta = inputs.FrameDelta;
+
+    FrameIndex        = frameIndex;
+
+    ThisFrameTime     = thisFrameTime;
+    NextFrameTime     = ThisFrameTime + frameDelta;
+    nextFrameBase     = NextFrameTime + inputs.ScreenDelay;
+    MidpointTime      = nextFrameBase + frameDelta * 0.5;
+    TimewarpPointTime = (inputs.TimewarpWaitDelta == 0.0) ?
+                        0.0 : (NextFrameTime + inputs.TimewarpWaitDelta);
+
+    // Calculate absolute points in time when eye rendering or corresponding time-warp
+    // screen edges will become visible.
+    // This only matters with VSync.
+    switch(shutterType)
+    {            
+    case HmdShutter_RollingTopToBottom:
+        EyeRenderTimes[0]               = MidpointTime;
+        EyeRenderTimes[1]               = MidpointTime;
+        TimeWarpStartEndTimes[0][0]     = nextFrameBase;
+        TimeWarpStartEndTimes[0][1]     = nextFrameBase + frameDelta;
+        TimeWarpStartEndTimes[1][0]     = nextFrameBase;
+        TimeWarpStartEndTimes[1][1]     = nextFrameBase + frameDelta;
+        break;
+    case HmdShutter_RollingLeftToRight:
+        EyeRenderTimes[0]               = nextFrameBase + frameDelta * 0.25;
+        EyeRenderTimes[1]               = nextFrameBase + frameDelta * 0.75;
+
+        /*
+        // TBD: MA: It is probably better if mesh sets it up per-eye.
+        // Would apply if screen is 0 -> 1 for each eye mesh
+        TimeWarpStartEndTimes[0][0]     = nextFrameBase;
+        TimeWarpStartEndTimes[0][1]     = MidpointTime;
+        TimeWarpStartEndTimes[1][0]     = MidpointTime;
+        TimeWarpStartEndTimes[1][1]     = nextFrameBase + frameDelta;
+        */
+
+        // Mesh is set up to vary from Edge of scree 0 -> 1 across both eyes
+        TimeWarpStartEndTimes[0][0]     = nextFrameBase;
+        TimeWarpStartEndTimes[0][1]     = nextFrameBase + frameDelta;
+        TimeWarpStartEndTimes[1][0]     = nextFrameBase;
+        TimeWarpStartEndTimes[1][1]     = nextFrameBase + frameDelta;
+
+        break;
+    case HmdShutter_RollingRightToLeft:
+
+        EyeRenderTimes[0]               = nextFrameBase + frameDelta * 0.75;
+        EyeRenderTimes[1]               = nextFrameBase + frameDelta * 0.25;
+        
+        // This is *Correct* with Tom's distortion mesh organization.
+        TimeWarpStartEndTimes[0][0]     = nextFrameBase ;
+        TimeWarpStartEndTimes[0][1]     = nextFrameBase + frameDelta;
+        TimeWarpStartEndTimes[1][0]     = nextFrameBase ;
+        TimeWarpStartEndTimes[1][1]     = nextFrameBase + frameDelta;
+        break;
+    case HmdShutter_Global:
+        // TBD
+        EyeRenderTimes[0]               = MidpointTime;
+        EyeRenderTimes[1]               = MidpointTime;
+        TimeWarpStartEndTimes[0][0]     = MidpointTime;
+        TimeWarpStartEndTimes[0][1]     = MidpointTime;
+        TimeWarpStartEndTimes[1][0]     = MidpointTime;
+        TimeWarpStartEndTimes[1][1]     = MidpointTime;
+        break;
+    default:
+        break;
+    }
+}
+
+  
+double FrameTimeManager::BeginFrame(unsigned frameIndex)
+{    
+    RenderIMUTimeSeconds = 0.0;
+    TimewarpIMUTimeSeconds = 0.0;
+
+    // ThisFrameTime comes from the end of last frame, unless it it changed.
+    double thisFrameTime = (FrameTiming.NextFrameTime != 0.0) ?
+                           FrameTiming.NextFrameTime : ovr_GetTimeInSeconds();
+    
+    // We are starting to process a new frame...
+    FrameTiming.InitTimingFromInputs(FrameTiming.Inputs, RenderInfo.Shutter.Type,
+                                     thisFrameTime, frameIndex);
+
+    return FrameTiming.ThisFrameTime;
+}
+
+
+void FrameTimeManager::EndFrame()
+{
+    // Record timing since last frame; must be called after Present & sync.
+    FrameTiming.NextFrameTime = ovr_GetTimeInSeconds();    
+    if (FrameTiming.ThisFrameTime > 0.0)
+    {
+        FrameTimeDeltas.AddTimeDelta(FrameTiming.NextFrameTime - FrameTiming.ThisFrameTime);
+        FrameTiming.Inputs.FrameDelta = calcFrameDelta();
+    }
+
+    // Write to Lock-less
+    LocklessTiming.SetState(FrameTiming);
+}
+
+
+
+// Thread-safe function to query timing for a future frame
+
+FrameTimeManager::Timing FrameTimeManager::GetFrameTiming(unsigned frameIndex)
+{
+    Timing frameTiming = LocklessTiming.GetState();
+
+    if (frameTiming.ThisFrameTime != 0.0)
+    {
+        // If timing hasn't been initialized, starting based on "now" is the best guess.
+        frameTiming.InitTimingFromInputs(frameTiming.Inputs, RenderInfo.Shutter.Type,
+                                         ovr_GetTimeInSeconds(), frameIndex);
+    }
+    
+    else if (frameIndex > frameTiming.FrameIndex)
+    {
+        unsigned frameDelta    = frameIndex - frameTiming.FrameIndex;
+        double   thisFrameTime = frameTiming.NextFrameTime +
+                                 double(frameDelta-1) * frameTiming.Inputs.FrameDelta;
+        // Don't run away too far into the future beyond rendering.
+        OVR_ASSERT(frameDelta < 6);
+
+        frameTiming.InitTimingFromInputs(frameTiming.Inputs, RenderInfo.Shutter.Type,
+                                         thisFrameTime, frameIndex);
+    }    
+     
+    return frameTiming;
+}
+
+
+double FrameTimeManager::GetEyePredictionTime(ovrEyeType eye)
+{
+    if (VsyncEnabled)
+    {
+        return FrameTiming.EyeRenderTimes[eye];
+    }
+
+    // No VSync: Best guess for the near future
+    return ovr_GetTimeInSeconds() + ScreenSwitchingDelay + NoVSyncToScanoutDelay;
+}
+
+Transformf FrameTimeManager::GetEyePredictionPose(ovrHmd hmd, ovrEyeType eye)
+{
+    double         eyeRenderTime = GetEyePredictionTime(eye);
+    ovrSensorState eyeState      = ovrHmd_GetSensorState(hmd, eyeRenderTime);
+
+//    EyeRenderPoses[eye] = eyeState.Predicted.Pose;
+
+    // Record view pose sampling time for Latency reporting.
+    if (RenderIMUTimeSeconds == 0.0)
+        RenderIMUTimeSeconds = eyeState.Recorded.TimeInSeconds;
+
+    return eyeState.Predicted.Pose;
+}
+
+
+void FrameTimeManager::GetTimewarpPredictions(ovrEyeType eye, double timewarpStartEnd[2])
+{
+    if (VsyncEnabled)
+    {
+        timewarpStartEnd[0] = FrameTiming.TimeWarpStartEndTimes[eye][0];
+        timewarpStartEnd[1] = FrameTiming.TimeWarpStartEndTimes[eye][1];
+        return;
+    }    
+
+    // Free-running, so this will be displayed immediately.
+    // Unfortunately we have no idea which bit of the screen is actually going to be displayed.
+    // TODO: guess which bit of the screen is being displayed!
+    // (e.g. use DONOTWAIT on present and see when the return isn't WASSTILLWAITING?)
+
+    // We have no idea where scan-out is currently, so we can't usefully warp the screen spatially.
+    timewarpStartEnd[0] = ovr_GetTimeInSeconds() + ScreenSwitchingDelay + NoVSyncToScanoutDelay;
+    timewarpStartEnd[1] = timewarpStartEnd[0];
+}
+
+
+void FrameTimeManager::GetTimewarpMatrices(ovrHmd hmd, ovrEyeType eyeId,
+                                           ovrPosef renderPose, ovrMatrix4f twmOut[2])
+{
+    if (!hmd)
+    {
+        return;
+    }
+
+    double timewarpStartEnd[2] = { 0.0, 0.0 };    
+    GetTimewarpPredictions(eyeId, timewarpStartEnd);
+      
+    ovrSensorState startState = ovrHmd_GetSensorState(hmd, timewarpStartEnd[0]);
+    ovrSensorState endState   = ovrHmd_GetSensorState(hmd, timewarpStartEnd[1]);
+
+    if (TimewarpIMUTimeSeconds == 0.0)
+        TimewarpIMUTimeSeconds = startState.Recorded.TimeInSeconds;
+
+    Quatf quatFromStart = startState.Predicted.Pose.Orientation;
+    Quatf quatFromEnd   = endState.Predicted.Pose.Orientation;
+    Quatf quatFromEye   = renderPose.Orientation; //EyeRenderPoses[eyeId].Orientation;
+    quatFromEye.Invert();
+    
+    Quatf timewarpStartQuat = quatFromEye * quatFromStart;
+    Quatf timewarpEndQuat   = quatFromEye * quatFromEnd;
+
+    Matrix4f timewarpStart(timewarpStartQuat);
+    Matrix4f timewarpEnd(timewarpEndQuat);
+    
+
+    // The real-world orientations have:                                  X=right, Y=up,   Z=backwards.
+    // The vectors inside the mesh are in NDC to keep the shader simple: X=right, Y=down, Z=forwards.
+    // So we need to perform a similarity transform on this delta matrix.
+    // The verbose code would look like this:
+    /*
+    Matrix4f matBasisChange;
+    matBasisChange.SetIdentity();
+    matBasisChange.M[0][0] =  1.0f;
+    matBasisChange.M[1][1] = -1.0f;
+    matBasisChange.M[2][2] = -1.0f;
+    Matrix4f matBasisChangeInv = matBasisChange.Inverted();
+    matRenderFromNow = matBasisChangeInv * matRenderFromNow * matBasisChange;
+    */
+    // ...but of course all the above is a constant transform and much more easily done.
+    // We flip the signs of the Y&Z row, then flip the signs of the Y&Z column,
+    // and of course most of the flips cancel:
+    // +++                        +--                     +--
+    // +++ -> flip Y&Z columns -> +-- -> flip Y&Z rows -> -++
+    // +++                        +--                     -++
+    timewarpStart.M[0][1] = -timewarpStart.M[0][1];
+    timewarpStart.M[0][2] = -timewarpStart.M[0][2];
+    timewarpStart.M[1][0] = -timewarpStart.M[1][0];
+    timewarpStart.M[2][0] = -timewarpStart.M[2][0];
+
+    timewarpEnd  .M[0][1] = -timewarpEnd  .M[0][1];
+    timewarpEnd  .M[0][2] = -timewarpEnd  .M[0][2];
+    timewarpEnd  .M[1][0] = -timewarpEnd  .M[1][0];
+    timewarpEnd  .M[2][0] = -timewarpEnd  .M[2][0];
+
+    twmOut[0] = timewarpStart;
+    twmOut[1] = timewarpEnd;
+}
+
+
+// Used by renderer to determine if it should time distortion rendering.
+bool  FrameTimeManager::NeedDistortionTimeMeasurement() const
+{
+    if (!VsyncEnabled)
+        return false;
+    return DistortionRenderTimes.GetCount() < 10;
+}
+
+
+void  FrameTimeManager::AddDistortionTimeMeasurement(double distortionTimeSeconds)
+{
+    DistortionRenderTimes.AddTimeDelta(distortionTimeSeconds);
+
+    // If timewarp timing changes based on this sample, update it.
+    double newTimewarpWaitDelta = calcTimewarpWaitDelta();
+    if (newTimewarpWaitDelta != FrameTiming.Inputs.TimewarpWaitDelta)
+    {
+        FrameTiming.Inputs.TimewarpWaitDelta = newTimewarpWaitDelta;
+        LocklessTiming.SetState(FrameTiming);
+    }
+}
+
+
+void FrameTimeManager::UpdateFrameLatencyTrackingAfterEndFrame(
+                                    unsigned char frameLatencyTestColor,
+                                    const Util::FrameTimeRecordSet& rs)
+{    
+    // FrameTiming.NextFrameTime in this context (after EndFrame) is the end frame time.
+    ScreenLatencyTracker.SaveDrawColor(frameLatencyTestColor,
+                                       FrameTiming.NextFrameTime,
+                                       RenderIMUTimeSeconds,
+                                       TimewarpIMUTimeSeconds);
+
+    ScreenLatencyTracker.MatchRecord(rs);
+
+    // If screen delay changed, update timing.
+    double newScreenDelay = calcScreenDelay();
+    if (newScreenDelay != FrameTiming.Inputs.ScreenDelay)
+    {
+        FrameTiming.Inputs.ScreenDelay = newScreenDelay;
+        LocklessTiming.SetState(FrameTiming);
+    }
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** TimeDeltaCollector
+
+void TimeDeltaCollector::AddTimeDelta(double timeSeconds)
+{
+    // avoid adding invalid timing values
+    if(timeSeconds < 0.0f)
+        return;
+
+    if (Count == Capacity)
+    {
+        for(int i=0; i< Count-1; i++)
+            TimeBufferSeconds[i] = TimeBufferSeconds[i+1];
+        Count--;
+    }
+    TimeBufferSeconds[Count++] = timeSeconds;
+}
+
+double TimeDeltaCollector::GetMedianTimeDelta() const
+{
+    double  SortedList[Capacity];
+    bool    used[Capacity];
+
+    memset(used, 0, sizeof(used));
+    SortedList[0] = 0.0; // In case Count was 0...
+
+    // Probably the slowest way to find median...
+    for (int i=0; i<Count; i++)
+    {
+        double smallestDelta = 1000000.0;
+        int    index = 0;
+
+        for (int j = 0; j < Count; j++)
+        {
+            if (!used[j])
+            {                
+                if (TimeBufferSeconds[j] < smallestDelta)
+                {
+                    smallestDelta = TimeBufferSeconds[j];
+                    index = j;
+                }
+            }
+        }
+
+        // Mark as used
+        used[index]   = true;
+        SortedList[i] = smallestDelta;
+    }
+
+    return SortedList[Count/2];
+}
+      
+
+}} // namespace OVR::CAPI
+
diff --git a/LibOVR/Src/CAPI/CAPI_FrameTimeManager.h b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.h
new file mode 100644
index 0000000..4693697
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.h
@@ -0,0 +1,264 @@
+/************************************************************************************
+
+Filename    :   CAPI_FrameTimeManager.h
+Content     :   Manage frame timing and pose prediction for rendering
+Created     :   November 30, 2013
+Authors     :   Volga Aksoy, Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_CAPI_FrameTimeManager_h
+#define OVR_CAPI_FrameTimeManager_h
+
+#include "../OVR_CAPI.h"
+#include "../Kernel/OVR_Timer.h"
+#include "../Kernel/OVR_Math.h"
+#include "../Util/Util_Render_Stereo.h"
+#include "../Util/Util_LatencyTest2.h"
+
+namespace OVR { namespace CAPI {
+
+//-------------------------------------------------------------------------------------
+
+// Helper class to collect median times between frames, so that we know
+// how long to wait. 
+struct TimeDeltaCollector
+{
+    TimeDeltaCollector() : Count(0) { }
+
+    void    AddTimeDelta(double timeSeconds);    
+    void    Clear() { Count = 0; }    
+
+    double  GetMedianTimeDelta() const;
+
+    double  GetCount() const { return Count; }
+
+    enum { Capacity = 12 };
+private:    
+    int     Count;
+    double  TimeBufferSeconds[Capacity];
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** FrameLatencyTracker
+
+// FrameLatencyTracker tracks frame Present to display Scan-out timing, as reported by
+// the DK2 internal latency tester pixel read-back. The computed value is used in
+// FrameTimeManager for prediction. View Render and TimeWarp to scan-out latencies are
+// also reported for debugging.
+//
+// The class operates by generating color values from GetNextDrawColor() that must
+// be rendered on the back end and then looking for matching values in FrameTimeRecordSet
+// structure as reported by HW.
+
+class FrameLatencyTracker
+{
+public:
+
+    enum { FramesTracked = Util::LT2_IncrementCount-1 };
+
+    FrameLatencyTracker();
+
+    // DrawColor == 0 is special in that it doesn't need saving of timestamp
+    unsigned char GetNextDrawColor();
+
+    void SaveDrawColor(unsigned char drawColor, double endFrameTime,
+                       double renderIMUTime, double timewarpIMUTime );
+
+    void MatchRecord(const Util::FrameTimeRecordSet &r);   
+
+    void GetLatencyTimings(float latencies[3]);
+
+    void Reset();
+
+public:
+
+    struct FrameTimeRecordEx : public Util::FrameTimeRecord
+    {
+        bool    MatchedRecord;
+        double  RenderIMUTimeSeconds;
+        double  TimewarpIMUTimeSeconds;
+    };
+
+    // True if rendering read-back is enabled.
+    bool                  TrackerEnabled;
+
+    enum SampleWaitType {
+        SampleWait_Zeroes, // We are waiting for a record with all zeros.
+        SampleWait_Match   // We are issuing & matching colors.
+    };
+    
+    SampleWaitType        WaitMode;
+    int                   MatchCount;
+    // Records of frame timings that we are trying to measure.
+    FrameTimeRecordEx     FrameEndTimes[FramesTracked];
+    int                   FrameIndex;
+    // Median filter for (ScanoutTimeSeconds - PostPresent frame time)
+    TimeDeltaCollector    FrameDeltas;
+    // Latency reporting results
+    double                RenderLatencySeconds;
+    double                TimewarpLatencySeconds;
+    double                LatencyRecordTime;
+};
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** FrameTimeManager
+
+// FrameTimeManager keeps track of rendered frame timing and handles predictions for
+// orientations and time-warp.
+
+class FrameTimeManager
+{
+public:
+    FrameTimeManager(bool vsyncEnabled = true);
+
+    // Data that affects frame timing computation.
+    struct TimingInputs
+    {
+        // Hard-coded value or dynamic as reported by FrameTimeDeltas.GetMedianTimeDelta().
+        double              FrameDelta;
+        // Screen delay from present to scan-out, as potentially reported by ScreenLatencyTracker.
+        double              ScreenDelay;
+        // Negative value of how many seconds before EndFrame we start timewarp. 0.0 if not used.
+        double              TimewarpWaitDelta;
+        
+        TimingInputs()
+            : FrameDelta(0), ScreenDelay(0), TimewarpWaitDelta(0)
+        { }
+    };
+
+    // Timing values for a specific frame.
+    struct Timing
+    {
+        TimingInputs        Inputs;
+        
+        // Index of a frame that started at ThisFrameTime.
+        unsigned int        FrameIndex;
+        // Predicted absolute times for when this frame will show up on screen.
+        // Generally, all values will be >= NextFrameTime, since that's the time we expect next
+        // vsync to succeed.
+        double              ThisFrameTime;
+        double              TimewarpPointTime;
+        double              NextFrameTime;        
+        double              MidpointTime;
+        double              EyeRenderTimes[2];
+        double              TimeWarpStartEndTimes[2][2];
+
+        Timing()
+        {
+            memset(this, 0, sizeof(Timing));
+        }
+
+        void InitTimingFromInputs(const TimingInputs& inputs, HmdShutterTypeEnum shutterType,
+                                  double thisFrameTime, unsigned int frameIndex);
+    };
+
+   
+    // Called on startup to provided data on HMD timing.
+    void    Init(HmdRenderInfo& renderInfo);
+
+    // Called with each new ConfigureRendering.
+    void    ResetFrameTiming(unsigned frameIndex,
+                             bool dynamicPrediction, bool sdkRender);
+
+    void    SetVsync(bool enabled) { VsyncEnabled = enabled; }
+
+    // BeginFrame returns time of the call
+    // TBD: Should this be a predicted time value instead ?
+    double  BeginFrame(unsigned frameIndex);
+    void    EndFrame();    
+
+    // Thread-safe function to query timing for a future frame
+    Timing  GetFrameTiming(unsigned frameIndex);
+ 
+    double  GetEyePredictionTime(ovrEyeType eye);
+    Transformf GetEyePredictionPose(ovrHmd hmd, ovrEyeType eye);
+
+    void    GetTimewarpPredictions(ovrEyeType eye, double timewarpStartEnd[2]); 
+    void    GetTimewarpMatrices(ovrHmd hmd, ovrEyeType eye, ovrPosef renderPose, ovrMatrix4f twmOut[2]);
+
+    // Used by renderer to determine if it should time distortion rendering.
+    bool    NeedDistortionTimeMeasurement() const;
+    void    AddDistortionTimeMeasurement(double distortionTimeSeconds);
+
+    
+    // DK2 Lateny test interface
+
+    // Get next draw color for DK2 latency tester
+    unsigned char GetFrameLatencyTestDrawColor()
+    { return ScreenLatencyTracker.GetNextDrawColor(); }
+
+    // Must be called after EndFrame() to update latency tester timings.
+    // Must pass color reported by NextFrameColor for this frame.
+    void    UpdateFrameLatencyTrackingAfterEndFrame(unsigned char frameLatencyTestColor,
+                                                    const Util::FrameTimeRecordSet& rs);
+
+    void    GetLatencyTimings(float latencies[3])
+    { return ScreenLatencyTracker.GetLatencyTimings(latencies); }
+
+
+    const Timing& GetFrameTiming() const { return FrameTiming; }
+
+private:
+
+    double  calcFrameDelta() const;
+    double  calcScreenDelay() const;
+    double  calcTimewarpWaitDelta() const;    
+    
+    
+    HmdRenderInfo       RenderInfo;
+    // Timings are collected through a median filter, to avoid outliers.
+    TimeDeltaCollector  FrameTimeDeltas;
+    TimeDeltaCollector  DistortionRenderTimes;
+    FrameLatencyTracker ScreenLatencyTracker;
+
+    // Timing changes if we have no Vsync (all prediction is reduced to fixed interval).
+    bool                VsyncEnabled;
+    // Set if we are rendering via the SDK, so DistortionRenderTimes is valid.
+    bool                DynamicPrediction;
+    // Set if SDk is doing teh rendering.
+    bool                SdkRender;
+
+    // Total frame delay due to VsyncToFirstScanline, persistence and settle time.
+    // Computed from RenderInfor.Shutter.
+    double              VSyncToScanoutDelay;
+    double              NoVSyncToScanoutDelay;
+    double              ScreenSwitchingDelay;
+
+    // Current (or last) frame timing info. Used as a source for LocklessTiming.
+    Timing                  FrameTiming;
+    // TBD: Don't we need NextFrame here as well?
+    LocklessUpdater<Timing> LocklessTiming;
+
+
+    // IMU Read timings
+    double              RenderIMUTimeSeconds;
+    double              TimewarpIMUTimeSeconds;
+};
+
+
+}} // namespace OVR::CAPI
+
+#endif // OVR_CAPI_FrameTimeManager_h
+
+
diff --git a/LibOVR/Src/CAPI/CAPI_GlobalState.cpp b/LibOVR/Src/CAPI/CAPI_GlobalState.cpp
new file mode 100644
index 0000000..2ed1794
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_GlobalState.cpp
@@ -0,0 +1,142 @@
+/************************************************************************************
+
+Filename    :   CAPI_GlobalState.cpp
+Content     :   Maintains global state of the CAPI
+Created     :   January 24, 2014
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "CAPI_GlobalState.h"
+
+namespace OVR { namespace CAPI {
+
+
+//-------------------------------------------------------------------------------------
+// Open Questions / Notes
+
+// 2. Detect HMDs.
+// Challenge: If we do everything through polling, it would imply we want all the devices
+//            initialized. However, there may be multiple rifts, extra sensors, etc,
+//            which shouldn't be allocated.
+// 
+
+// How do you reset orientation Quaternion?
+// Can you change IPD?
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** OVRGlobalState
+
+// Global instance
+GlobalState* GlobalState::pInstance = 0;
+
+
+GlobalState::GlobalState()
+{
+    pManager = *DeviceManager::Create();
+    // Handle the DeviceManager's messages
+    pManager->AddMessageHandler( this );
+    EnumerateDevices();
+
+    // PhoneSensors::Init();
+}
+
+GlobalState::~GlobalState()
+{
+    RemoveHandlerFromDevices();
+    OVR_ASSERT(HMDs.IsEmpty());
+}
+
+int GlobalState::EnumerateDevices()
+{
+    // Need to use separate lock for device enumeration, as pManager->GetHandlerLock()
+    // would produce deadlocks here.
+    Lock::Locker lock(&EnumerationLock);
+    
+    EnumeratedDevices.Clear();        
+
+    DeviceEnumerator<HMDDevice> e = pManager->EnumerateDevices<HMDDevice>();
+    while(e.IsAvailable())
+    {
+        EnumeratedDevices.PushBack(DeviceHandle(e));       
+        e.Next();
+    }
+
+    return (int)EnumeratedDevices.GetSize();
+}
+
+
+HMDDevice* GlobalState::CreateDevice(int index)
+{
+    Lock::Locker lock(&EnumerationLock);
+
+    if (index >= (int)EnumeratedDevices.GetSize())
+        return 0;
+    return EnumeratedDevices[index].CreateDeviceTyped<HMDDevice>();
+}
+
+
+void GlobalState::AddHMD(HMDState* hmd)
+{
+    Lock::Locker lock(pManager->GetHandlerLock());
+    HMDs.PushBack(hmd);
+}
+void GlobalState::RemoveHMD(HMDState* hmd)
+{
+    Lock::Locker lock(pManager->GetHandlerLock());
+    hmd->RemoveNode();
+}
+
+void GlobalState::NotifyHMDs_AddDevice(DeviceType deviceType)
+{
+    Lock::Locker lock(pManager->GetHandlerLock());
+    for(HMDState* hmd = HMDs.GetFirst(); !HMDs.IsNull(hmd); hmd = hmd->pNext)        
+        hmd->NotifyAddDevice(deviceType);
+}
+
+void GlobalState::OnMessage(const Message& msg)
+{
+    if (msg.Type == Message_DeviceAdded || msg.Type == Message_DeviceRemoved)
+    {       
+        if (msg.pDevice == pManager)
+        {   
+            const MessageDeviceStatus& statusMsg =
+                static_cast<const MessageDeviceStatus&>(msg);
+
+            if (msg.Type == Message_DeviceAdded)
+            {
+                //LogText("OnMessage DeviceAdded.\n");
+
+                // We may have added a sensor/other device; notify any HMDs that might
+                // need it to check for it later.
+                NotifyHMDs_AddDevice(statusMsg.Handle.GetType());
+            }
+            else
+            {
+                //LogText("OnMessage DeviceRemoved.\n");
+            }
+        }
+    }
+}
+
+
+}} // namespace OVR::CAPI
diff --git a/LibOVR/Src/CAPI/CAPI_GlobalState.h b/LibOVR/Src/CAPI/CAPI_GlobalState.h
new file mode 100644
index 0000000..54ab8cc
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_GlobalState.h
@@ -0,0 +1,84 @@
+/************************************************************************************
+
+Filename    :   CAPI_GlobalState.h
+Content     :   Maintains global state of the CAPI
+Created     :   January 24, 2013
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_CAPI_GlobalState_h
+#define OVR_CAPI_GlobalState_h
+
+#include "../OVR_CAPI.h"
+#include "../OVR_Device.h"
+#include "../Kernel/OVR_Timer.h"
+#include "../Kernel/OVR_Math.h"
+
+#include "CAPI_HMDState.h"
+
+namespace OVR { namespace CAPI {
+
+//-------------------------------------------------------------------------------------
+// ***** OVRGlobalState
+
+// Global DeviceManager state - singleton instance of this is created
+// by ovr_Initialize().
+class GlobalState  : public MessageHandler,  public NewOverrideBase
+{  
+public:
+    GlobalState();
+    ~GlobalState();
+
+    static GlobalState *pInstance;
+    
+    int         EnumerateDevices();
+    HMDDevice*  CreateDevice(int index);
+
+    // MessageHandler implementation
+    void        OnMessage(const Message& msg);
+
+    // Helpers used to keep track of HMDs and notify them of sensor changes.
+    void        AddHMD(HMDState* hmd);
+    void        RemoveHMD(HMDState* hmd);
+    void        NotifyHMDs_AddDevice(DeviceType deviceType);
+
+    const char* GetLastError()
+    {
+        return 0;
+    }
+
+    DeviceManager* GetManager() { return pManager; }
+
+protected:
+
+    Ptr<DeviceManager>  pManager;
+    Lock                EnumerationLock;
+    Array<DeviceHandle> EnumeratedDevices;
+    
+    // Currently created hmds; protected by Manager lock.
+    List<HMDState>      HMDs;
+};
+
+}} // namespace OVR::CAPI
+
+#endif
+
+
diff --git a/LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp b/LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp
new file mode 100644
index 0000000..00bdea2
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp
@@ -0,0 +1,143 @@
+/************************************************************************************
+
+Filename    :   OVR_CAPI_HMDRenderState.cpp
+Content     :   Combines all of the rendering state associated with the HMD
+Created     :   February 2, 2014
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "CAPI_HMDRenderState.h"
+
+namespace OVR { namespace CAPI {
+
+
+//-------------------------------------------------------------------------------------
+// ***** HMDRenderState
+
+
+HMDRenderState::HMDRenderState(ovrHmd hmd, Profile* userProfile, const OVR::HMDInfo& hmdInfo)
+    : HMD(hmd), HMDInfo(hmdInfo)
+{
+	RenderInfo = GenerateHmdRenderInfoFromHmdInfo( HMDInfo, userProfile );
+
+    Distortion[0] = CalculateDistortionRenderDesc(StereoEye_Left,  RenderInfo, 0);
+    Distortion[1] = CalculateDistortionRenderDesc(StereoEye_Right, RenderInfo, 0);
+
+    ClearColor[0] = ClearColor[1] = ClearColor[2] = ClearColor[3] =0.0f;
+
+    EnabledHmdCaps = 0;
+}
+
+HMDRenderState::~HMDRenderState()
+{
+}
+
+ovrHmdDesc HMDRenderState::GetDesc()
+{
+    ovrHmdDesc d;
+    memset(&d, 0, sizeof(d));
+    
+    d.Type = ovrHmd_Other;
+     
+    d.ProductName       = HMDInfo.ProductName;    
+    d.Manufacturer      = HMDInfo.Manufacturer;
+    d.Resolution.w      = HMDInfo.ResolutionInPixels.w;
+    d.Resolution.h      = HMDInfo.ResolutionInPixels.h;
+    d.WindowsPos.x      = HMDInfo.DesktopX;
+    d.WindowsPos.y      = HMDInfo.DesktopY;
+    d.DisplayDeviceName = HMDInfo.DisplayDeviceName;
+    d.DisplayId         = HMDInfo.DisplayId;
+
+    d.HmdCaps           = ovrHmdCap_Present | ovrHmdCap_NoVSync;
+    d.SensorCaps        = ovrSensorCap_YawCorrection | ovrSensorCap_Orientation;
+    d.DistortionCaps    = ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp | ovrDistortionCap_Vignette;
+
+    if (strstr(HMDInfo.ProductName, "DK1"))
+    {
+        d.Type = ovrHmd_DK1;        
+    }
+    else if (strstr(HMDInfo.ProductName, "DK2"))
+    {
+        d.Type        = ovrHmd_DK2;
+        d.HmdCaps    |= ovrHmdCap_LowPersistence |
+                        ovrHmdCap_LatencyTest | ovrHmdCap_DynamicPrediction;
+        d.SensorCaps |= ovrSensorCap_Position;
+    }
+        
+    DistortionRenderDesc& leftDistortion  = Distortion[0];
+    DistortionRenderDesc& rightDistortion = Distortion[1];
+  
+    // The suggested FOV (assuming eye rotation)
+    d.DefaultEyeFov[0] = CalculateFovFromHmdInfo(StereoEye_Left, leftDistortion, RenderInfo, OVR_DEFAULT_EXTRA_EYE_ROTATION);
+    d.DefaultEyeFov[1] = CalculateFovFromHmdInfo(StereoEye_Right, rightDistortion, RenderInfo, OVR_DEFAULT_EXTRA_EYE_ROTATION);
+
+    // FOV extended across the entire screen
+    d.MaxEyeFov[0] = GetPhysicalScreenFov(StereoEye_Left, leftDistortion);
+    d.MaxEyeFov[1] = GetPhysicalScreenFov(StereoEye_Right, rightDistortion);
+
+    if (HMDInfo.Shutter.Type == HmdShutter_RollingRightToLeft)
+    {
+        d.EyeRenderOrder[0] = ovrEye_Right;
+        d.EyeRenderOrder[1] = ovrEye_Left;
+    }
+    else
+    {
+        d.EyeRenderOrder[0] = ovrEye_Left;
+        d.EyeRenderOrder[1] = ovrEye_Right;
+    }    
+
+    return d;
+}
+
+
+ovrSizei HMDRenderState::GetFOVTextureSize(int eye, ovrFovPort fov, float pixelsPerDisplayPixel)
+{
+    OVR_ASSERT((unsigned)eye < 2);
+    StereoEye seye = (eye == ovrEye_Left) ? StereoEye_Left : StereoEye_Right;
+    return CalculateIdealPixelSize(seye, Distortion[eye], fov, pixelsPerDisplayPixel);
+}
+
+ovrEyeRenderDesc HMDRenderState::calcRenderDesc(ovrEyeType eyeType, const ovrFovPort& fov)
+{    
+    HmdRenderInfo&   hmdri = RenderInfo;
+    StereoEye        eye   = (eyeType == ovrEye_Left) ? StereoEye_Left : StereoEye_Right;
+    ovrEyeRenderDesc e0;
+    
+    e0.Eye                       = eyeType;
+    e0.Fov                       = fov;
+    e0.ViewAdjust                = CalculateEyeVirtualCameraOffset(hmdri, eye, false);
+    e0.DistortedViewport         = GetFramebufferViewport(eye, hmdri);
+    e0.PixelsPerTanAngleAtCenter = Distortion[0].PixelsPerTanAngleAtCenter;
+
+    return e0;
+}
+
+
+void HMDRenderState::setupRenderDesc( ovrEyeRenderDesc eyeRenderDescOut[2],
+                                      const ovrFovPort eyeFovIn[2] )
+{
+    eyeRenderDescOut[0] = EyeRenderDesc[0] = calcRenderDesc(ovrEye_Left,  eyeFovIn[0]);
+    eyeRenderDescOut[1] = EyeRenderDesc[1] = calcRenderDesc(ovrEye_Right, eyeFovIn[1]);   
+}
+
+
+}} // namespace OVR::CAPI
+
diff --git a/LibOVR/Src/CAPI/CAPI_HMDRenderState.h b/LibOVR/Src/CAPI/CAPI_HMDRenderState.h
new file mode 100644
index 0000000..a4e8d21
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_HMDRenderState.h
@@ -0,0 +1,93 @@
+/************************************************************************************
+
+Filename    :   CAPI_HMDRenderState.h
+Content     :   Combines all of the rendering state associated with the HMD
+Created     :   February 2, 2014
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_CAPI_HMDRenderState_h
+#define OVR_CAPI_HMDRenderState_h
+
+#include "../OVR_CAPI.h"
+#include "../Kernel/OVR_Math.h"
+#include "../Util/Util_Render_Stereo.h"
+
+
+namespace OVR { namespace CAPI {
+
+using namespace OVR::Util::Render;
+
+//-------------------------------------------------------------------------------------
+// ***** HMDRenderState
+
+// Combines all of the rendering setup information about one HMD.
+
+class HMDRenderState : public NewOverrideBase 
+{
+    // Quiet assignment compiler warning.
+    void operator = (const HMDRenderState&) { }
+public:   
+
+    HMDRenderState(ovrHmd hmd, Profile* userProfile, const OVR::HMDInfo& hmdInfo);
+    virtual ~HMDRenderState();
+
+
+    // *** Rendering Setup
+
+    // Delegated access APIs
+    ovrHmdDesc GetDesc();
+    ovrSizei   GetFOVTextureSize(int eye, ovrFovPort fov, float pixelsPerDisplayPixel);
+
+    ovrEyeRenderDesc calcRenderDesc(ovrEyeType eyeType, const ovrFovPort& fov);
+
+    void       setupRenderDesc(ovrEyeRenderDesc eyeRenderDescOut[2],
+                               const ovrFovPort eyeFovIn[2]);
+public:
+    
+    // HMDInfo shouldn't change, as its string pointers are passed out.    
+    ovrHmd                  HMD;
+    const OVR::HMDInfo&     HMDInfo;
+
+    //const char*             pLastError;
+
+    HmdRenderInfo            RenderInfo;    
+    DistortionRenderDesc     Distortion[2];
+    ovrEyeRenderDesc         EyeRenderDesc[2]; 
+
+    // Clear color used for distortion
+    float                    ClearColor[4];
+
+    // Pose at which last time the eye was rendered, as submitted by EndEyeRender.
+    ovrPosef                 EyeRenderPoses[2];
+
+    // Capabilities passed to Configure.
+    unsigned                 EnabledHmdCaps;
+    unsigned                 DistortionCaps;
+};
+
+
+}} // namespace OVR::CAPI
+
+
+#endif // OVR_CAPI_HMDState_h
+
+
diff --git a/LibOVR/Src/CAPI/CAPI_HMDState.cpp b/LibOVR/Src/CAPI/CAPI_HMDState.cpp
new file mode 100644
index 0000000..fd98225
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_HMDState.cpp
@@ -0,0 +1,804 @@
+/************************************************************************************
+
+Filename    :   CAPI_HMDState.cpp
+Content     :   State associated with a single HMD
+Created     :   January 24, 2014
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "CAPI_HMDState.h"
+#include "CAPI_GlobalState.h"
+#include "../OVR_Profile.h"
+
+namespace OVR { namespace CAPI {
+
+//-------------------------------------------------------------------------------------
+// ***** HMDState
+
+
+HMDState::HMDState(HMDDevice* device)
+    : pHMD(device), HMDInfoW(device), HMDInfo(HMDInfoW.h),    
+      EnabledHmdCaps(0), HmdCapsAppliedToSensor(0),
+      SensorStarted(0), SensorCreated(0), SensorCaps(0),
+      AddSensorCount(0), AddLatencyTestCount(0), AddLatencyTestDisplayCount(0),
+      RenderState(getThis(), pHMD->GetProfile(), HMDInfoW.h),
+      LastFrameTimeSeconds(0.0f), LastGetFrameTimeSeconds(0.0),
+      LatencyTestActive(false),
+      LatencyTest2Active(false)
+{
+    pLastError = 0;
+    GlobalState::pInstance->AddHMD(this);
+    
+    // Should be in renderer?
+    TimeManager.Init(RenderState.RenderInfo);
+
+    EyeRenderActive[0] = false;
+    EyeRenderActive[1] = false;
+
+    LatencyTestDrawColor[0] = 0;
+    LatencyTestDrawColor[1] = 0;
+    LatencyTestDrawColor[2] = 0;
+
+    OVR_CAPI_VISION_CODE( pPoseTracker = 0; )
+
+    RenderingConfigured = false;
+    BeginFrameCalled    = false;
+    BeginFrameThreadId  = 0;
+    BeginFrameTimingCalled = false;
+}
+
+HMDState::HMDState(ovrHmdType hmdType)
+  : pHMD(0), HMDInfoW(hmdType), HMDInfo(HMDInfoW.h),
+    EnabledHmdCaps(0),
+    SensorStarted(0), SensorCreated(0), SensorCaps(0),
+    AddSensorCount(0), AddLatencyTestCount(0), AddLatencyTestDisplayCount(0),
+    RenderState(getThis(), 0, HMDInfoW.h), // No profile. 
+    LastFrameTimeSeconds(0.0), LastGetFrameTimeSeconds(0.0)
+{
+    // TBD: We should probably be looking up the default profile for the given
+    // device type + user.
+
+    pLastError = 0;
+    GlobalState::pInstance->AddHMD(this);
+
+    // Should be in renderer?
+    TimeManager.Init(RenderState.RenderInfo);
+
+    EyeRenderActive[0] = false;
+    EyeRenderActive[1] = false;
+
+    OVR_CAPI_VISION_CODE( pPoseTracker = 0; )
+
+    RenderingConfigured = false;
+    BeginFrameCalled   = false;
+    BeginFrameThreadId = 0;
+    BeginFrameTimingCalled = false;
+}
+
+
+HMDState::~HMDState()
+{
+    OVR_ASSERT(GlobalState::pInstance);
+   
+    StopSensor();
+    ConfigureRendering(0,0,0,0);
+
+    OVR_CAPI_VISION_CODE( OVR_ASSERT(pPoseTracker == 0); )
+
+    GlobalState::pInstance->RemoveHMD(this);
+}
+
+
+
+//-------------------------------------------------------------------------------------
+// *** Sensor 
+
+bool HMDState::StartSensor(unsigned supportedCaps, unsigned requiredCaps)
+{
+    Lock::Locker lockScope(&DevicesLock);
+
+    bool crystalCoveOrBetter = (HMDInfo.HmdType == HmdType_CrystalCoveProto) ||
+                               (HMDInfo.HmdType == HmdType_DK2);
+    bool sensorCreatedJustNow = false;
+
+    // TBD: In case of sensor not being immediately available, it would be good to check
+    //      yaw config availability to match it with ovrHmdCap_YawCorrection requirement.
+    // 
+
+    if (!crystalCoveOrBetter)
+    {
+        if (requiredCaps & ovrSensorCap_Position)
+        {
+            pLastError = "ovrSensorCap_Position not supported on this HMD.";
+            return false;            
+        }
+    }
+
+    supportedCaps |= requiredCaps;
+
+    if (pHMD && !pSensor)
+    {
+        // Zero AddSensorCount before creation, in case it fails (or succeeds but then
+        // immediately gets disconnected) followed by another Add notification.        
+        AddSensorCount      = 0;
+        pSensor             = *pHMD->GetSensor();
+        sensorCreatedJustNow= true;
+
+        if (pSensor)
+        {
+            pSensor->SetReportRate(500);
+            SFusion.AttachToSensor(pSensor);
+            applyProfileToSensorFusion();
+        }
+        else
+        {
+            if (requiredCaps & ovrSensorCap_Orientation)
+            {
+                pLastError = "Failed to create sensor.";
+                return false;
+            }
+        }
+    }
+
+
+    if ((requiredCaps & ovrSensorCap_YawCorrection) && !pSensor->IsMagCalibrated())
+    {
+        pLastError = "ovrHmdCap_YawCorrection not available.";
+        if (sensorCreatedJustNow)
+        {
+            SFusion.AttachToSensor(0);
+            SFusion.Reset();
+            pSensor.Clear();
+        }
+        return false;
+    }        
+
+    SFusion.SetYawCorrectionEnabled((supportedCaps & ovrSensorCap_YawCorrection) != 0);
+
+    if (pSensor && sensorCreatedJustNow)
+    {
+        LogText("Sensor created.\n");
+        SensorCreated = true;
+    }
+
+    updateDK2FeaturesTiedToSensor(sensorCreatedJustNow);    
+    
+
+#ifdef OVR_CAPI_VISIONSUPPORT
+
+    if (crystalCoveOrBetter && (supportedCaps & ovrSensorCap_Position))
+    {
+        if (!pPoseTracker)
+        {
+            pPoseTracker = new Vision::PoseTracker(SFusion);
+            if (pPoseTracker)
+            {
+                pPoseTracker->AssociateHMD(pSensor);
+                LogText("Sensor Pose tracker created.\n");
+            }
+        }
+
+        // TBD: How do we verify that position tracking is actually available
+        //      i.e. camera is plugged in?
+    }
+    else if (pPoseTracker)
+    {
+        // TBD: Internals not thread safe - must fix!!
+        delete pPoseTracker;
+        pPoseTracker = 0;
+        LogText("Sensor Pose tracker destroyed.\n");
+    }
+
+#endif // OVR_CAPI_VISIONSUPPORT
+
+    SensorCaps    = supportedCaps;
+    SensorStarted = true;
+
+    return true;
+}
+
+
+// Stops sensor sampling, shutting down internal resources.
+void HMDState::StopSensor()
+{
+    Lock::Locker lockScope(&DevicesLock);
+
+    if (SensorStarted)
+    {
+#ifdef OVR_CAPI_VISIONSUPPORT
+        if (pPoseTracker)
+        {
+            // TBD: Internals not thread safe - must fix!!
+            delete pPoseTracker;
+            pPoseTracker = 0;
+            LogText("Sensor Pose tracker destroyed.\n");
+        }        
+#endif // OVR_CAPI_VISION_CODE
+
+        SFusion.AttachToSensor(0);
+        SFusion.Reset();
+        pSensor.Clear();
+        HmdCapsAppliedToSensor = 0;
+        AddSensorCount = 0;
+        SensorCaps     = 0;
+        SensorCreated  = false;
+        SensorStarted  = false;
+
+        LogText("StopSensor succeeded.\n");
+    }
+}
+
+// Resets sensor orientation.
+void HMDState::ResetSensor()
+{
+    SFusion.Reset();
+}
+
+
+// Returns prediction for time.
+ovrSensorState HMDState::PredictedSensorState(double absTime)
+{    
+    SensorState ss;
+
+    // We are trying to keep this path lockless unless we are notified of new device
+    // creation while not having a sensor yet. It's ok to check SensorCreated volatile
+    // flag here, since GetSensorStateAtTime() is internally lockless and safe.
+
+    if (SensorCreated || checkCreateSensor())
+    {   
+        ss = SFusion.GetSensorStateAtTime(absTime);
+
+        if (!(ss.StatusFlags & ovrStatus_OrientationTracked))
+        {
+            Lock::Locker lockScope(&DevicesLock);
+
+#ifdef OVR_CAPI_VISIONSUPPORT
+            if (pPoseTracker)
+            {
+                // TBD: Internals not thread safe - must fix!!
+                delete pPoseTracker;
+                pPoseTracker = 0;
+                LogText("Sensor Pose tracker destroyed.\n");
+            }        
+#endif // OVR_CAPI_VISION_CODE
+            // Not needed yet; SFusion.AttachToSensor(0);
+            // This seems to reset orientation anyway...
+            pSensor.Clear();
+            SensorCreated = false;         
+            HmdCapsAppliedToSensor = 0;
+        }
+    }
+    else
+    {
+        // SensorState() defaults to 0s.
+        // ss.Pose.Orientation       = Quatf();
+        // ..
+
+        // John:
+        // We still want valid times so frames will get a delta-time
+        // and allow operation with a joypad when the sensor isn't
+        // connected.
+        ss.Recorded.TimeInSeconds  = absTime;
+        ss.Predicted.TimeInSeconds = absTime;
+    }
+
+    ss.StatusFlags |= ovrStatus_HmdConnected;
+    return ss;
+}
+
+
+bool  HMDState::checkCreateSensor()
+{
+    if (!(SensorStarted && !SensorCreated && AddSensorCount))
+        return false;
+
+    Lock::Locker lockScope(&DevicesLock);
+
+    // Re-check condition once in the lock, in case the state changed.
+    if (SensorStarted && !SensorCreated && AddSensorCount)
+    {        
+        if (pHMD)
+        {
+            AddSensorCount = 0;
+            pSensor        = *pHMD->GetSensor();
+        }
+
+        if (pSensor)
+        {
+            pSensor->SetReportRate(500);
+            SFusion.AttachToSensor(pSensor);
+            SFusion.SetYawCorrectionEnabled((SensorCaps & ovrSensorCap_YawCorrection) != 0);
+            applyProfileToSensorFusion();
+
+#ifdef OVR_CAPI_VISIONSUPPORT
+            if (SensorCaps & ovrSensorCap_Position)
+            {
+                pPoseTracker = new Vision::PoseTracker(SFusion);
+                if (pPoseTracker)
+                {
+                    pPoseTracker->AssociateHMD(pSensor);
+                }
+                LogText("Sensor Pose tracker created.\n");
+            }
+#endif // OVR_CAPI_VISION_CODE
+
+            LogText("Sensor created.\n");
+
+            SensorCreated = true;
+            return true;
+        }
+    }
+
+    return SensorCreated;
+}
+
+bool HMDState::GetSensorDesc(ovrSensorDesc* descOut)
+{
+    Lock::Locker lockScope(&DevicesLock);
+
+    if (SensorCreated)
+    {
+        OVR_ASSERT(pSensor);
+        OVR::SensorInfo si;
+        pSensor->GetDeviceInfo(&si);
+        descOut->VendorId  = si.VendorId;
+        descOut->ProductId = si.ProductId;
+        OVR_ASSERT(si.SerialNumber.GetSize() <= sizeof(descOut->SerialNumber));
+        OVR_strcpy(descOut->SerialNumber, sizeof(descOut->SerialNumber), si.SerialNumber.ToCStr());
+        return true;
+    }
+    return false;
+}
+
+
+void HMDState::applyProfileToSensorFusion()
+{
+    if (!pHMD)
+        return;
+    Profile* profile = pHMD->GetProfile();
+    if (!profile)
+    {
+        OVR_ASSERT(false);
+        return;
+    }
+    SFusion.SetUserHeadDimensions ( *profile, RenderState.RenderInfo );
+}
+
+void HMDState::updateLowPersistenceMode(bool lowPersistence) const
+{
+	OVR_ASSERT(pSensor);
+	DisplayReport dr;
+    
+    if (pSensor.GetPtr())
+    {
+	    pSensor->GetDisplayReport(&dr);
+
+	    dr.Persistence = (UInt16) (dr.TotalRows * (lowPersistence ? 0.18f : 1.0f));
+	    dr.Brightness = lowPersistence ? 255 : 0;
+    
+	    pSensor->SetDisplayReport(dr);
+    }
+}
+
+void HMDState::updateLatencyTestForHmd(bool latencyTesting)
+{
+    if (pSensor.GetPtr())
+    {
+        DisplayReport dr;
+        pSensor->GetDisplayReport(&dr);
+
+        dr.ReadPixel = latencyTesting;
+
+        pSensor->SetDisplayReport(dr);
+    }
+
+    if (latencyTesting)
+    {
+        LatencyUtil2.SetSensorDevice(pSensor.GetPtr());
+    }
+    else
+    {
+        LatencyUtil2.SetSensorDevice(NULL);
+    }
+}
+
+
+void HMDState::updateDK2FeaturesTiedToSensor(bool sensorCreatedJustNow)
+{
+    Lock::Locker lockScope(&DevicesLock);
+
+    if (!SensorCreated || (HMDInfo.HmdType != HmdType_DK2))
+        return;
+
+    // Only send display reports if state changed or sensor initializing first time.
+    if (sensorCreatedJustNow ||
+         ((HmdCapsAppliedToSensor ^ EnabledHmdCaps) & ovrHmdCap_LowPersistence))
+    {
+        updateLowPersistenceMode((EnabledHmdCaps & ovrHmdCap_LowPersistence) ? true : false);         
+    }
+
+    if (sensorCreatedJustNow || ((HmdCapsAppliedToSensor ^ EnabledHmdCaps) & ovrHmdCap_LatencyTest))
+    {
+        updateLatencyTestForHmd((EnabledHmdCaps & ovrHmdCap_LatencyTest) != 0);
+    }
+
+    HmdCapsAppliedToSensor = EnabledHmdCaps & (ovrHmdCap_LowPersistence|ovrHmdCap_LatencyTest);
+}
+
+
+
+void HMDState::SetEnabledHmdCaps(unsigned hmdCaps)
+{
+    
+    if (HMDInfo.HmdType == HmdType_DK2)
+    {
+        if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_DynamicPrediction)
+        {
+            // DynamicPrediction change
+            TimeManager.ResetFrameTiming(TimeManager.GetFrameTiming().FrameIndex,
+                                         (hmdCaps & ovrHmdCap_DynamicPrediction) ? true : false,
+                                         RenderingConfigured);
+        }
+    }
+
+    if ((EnabledHmdCaps ^ hmdCaps) & ovrHmdCap_NoVSync)
+    {
+        TimeManager.SetVsync((hmdCaps & ovrHmdCap_NoVSync) ? false : true);
+    }
+
+
+    EnabledHmdCaps             = hmdCaps & ovrHmdCap_Writable_Mask;
+    RenderState.EnabledHmdCaps = EnabledHmdCaps;
+
+    // Unfortunately, LowPersistance and other flags are tied to sensor.
+    // This flag will apply the state of sensor is created; otherwise this will be delayed
+    // till StartSensor.
+    // Such behavior is less then ideal, but should be resolved with the service model.
+
+    updateDK2FeaturesTiedToSensor(false);
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** Property Access
+
+// TBD: This all needs to be cleaned up and organized into namespaces.
+
+float HMDState::getFloatValue(const char* propertyName, float defaultVal)
+{
+	if (OVR_strcmp(propertyName, "LensSeparation") == 0)
+	{
+		return HMDInfo.LensSeparationInMeters;
+	}
+    else if (OVR_strcmp(propertyName, "CenterPupilDepth") == 0)
+    {        
+        return SFusion.GetCenterPupilDepth();
+    }
+	else if (pHMD)
+	{
+		Profile* p = pHMD->GetProfile();
+		if (p)
+		{
+			return p->GetFloatValue(propertyName, defaultVal);
+		}
+	}
+	return defaultVal;
+}
+
+bool HMDState::setFloatValue(const char* propertyName, float value)
+{
+    if (OVR_strcmp(propertyName, "CenterPupilDepth") == 0)
+    {
+        SFusion.SetCenterPupilDepth(value);
+        return true;
+    }
+    return false;
+}
+
+
+static unsigned CopyFloatArrayWithLimit(float dest[], unsigned destSize,
+                                        float source[], unsigned sourceSize)
+{
+    unsigned count = Alg::Min(destSize, sourceSize);
+    for (unsigned i = 0; i < count; i++)
+        dest[i] = source[i];
+    return count;
+}
+
+
+unsigned HMDState::getFloatArray(const char* propertyName, float values[], unsigned arraySize)
+{
+	if (arraySize)
+	{
+		if (OVR_strcmp(propertyName, "ScreenSize") == 0)
+		{
+            float data[2] = { HMDInfo.ScreenSizeInMeters.w, HMDInfo.ScreenSizeInMeters.h };
+
+            return CopyFloatArrayWithLimit(values, arraySize, data, 2);
+		}
+        else if (OVR_strcmp(propertyName, "DistortionClearColor") == 0)
+        {
+            return CopyFloatArrayWithLimit(values, arraySize, RenderState.ClearColor, 4);
+        }
+        else if (OVR_strcmp(propertyName, "DK2Latency") == 0)
+        {
+            if (HMDInfo.HmdType != HmdType_DK2)
+                return 0;
+
+            float data[3];            
+            TimeManager.GetLatencyTimings(data);
+            
+            return CopyFloatArrayWithLimit(values, arraySize, data, 3);
+        }
+
+        /*
+        else if (OVR_strcmp(propertyName, "CenterPupilDepth") == 0)
+        {
+            if (arraySize >= 1)
+            {
+                values[0] = SFusion.GetCenterPupilDepth();
+                return 1;
+            }
+            return 0;
+        } */
+		else if (pHMD)
+		{        
+			Profile* p = pHMD->GetProfile();
+
+			// TBD: Not quite right. Should update profile interface, so that
+			//      we can return 0 in all conditions if property doesn't exist.
+			if (p)
+			{
+				unsigned count = p->GetFloatValues(propertyName, values, arraySize);
+				return count;
+			}
+		}
+	}
+
+	return 0;
+}
+
+bool HMDState::setFloatArray(const char* propertyName, float values[], unsigned arraySize)
+{
+    if (!arraySize)
+        return false;
+    
+    if (OVR_strcmp(propertyName, "DistortionClearColor") == 0)
+    {
+        CopyFloatArrayWithLimit(RenderState.ClearColor, 4, values, arraySize);
+        return true;
+    }
+    return false;
+}
+
+
+const char* HMDState::getString(const char* propertyName, const char* defaultVal)
+{
+	if (pHMD)
+	{
+		// For now, just access the profile.
+		Profile* p = pHMD->GetProfile();
+
+		LastGetStringValue[0] = 0;
+		if (p && p->GetValue(propertyName, LastGetStringValue, sizeof(LastGetStringValue)))
+		{
+			return LastGetStringValue;
+		}
+	}
+
+	return defaultVal;
+}
+
+//-------------------------------------------------------------------------------------
+// *** Latency Test
+
+bool HMDState::ProcessLatencyTest(unsigned char rgbColorOut[3])
+{
+    bool result = false;
+
+    // Check create.
+    if (pLatencyTester)
+    {
+        if (pLatencyTester->IsConnected())
+        {
+            Color colorToDisplay;
+
+            LatencyUtil.ProcessInputs();
+            result = LatencyUtil.DisplayScreenColor(colorToDisplay);
+            rgbColorOut[0] = colorToDisplay.R;
+            rgbColorOut[1] = colorToDisplay.G;
+            rgbColorOut[2] = colorToDisplay.B;
+        }
+        else
+        {
+            // Disconnect.
+            LatencyUtil.SetDevice(NULL);
+            pLatencyTester = 0;
+            LogText("LATENCY SENSOR disconnected.\n");
+        }
+    }
+    else if (AddLatencyTestCount > 0)
+    {
+        // This might have some unlikely race condition issue which could cause us to miss a device...
+        AddLatencyTestCount = 0;
+
+        pLatencyTester = *GlobalState::pInstance->GetManager()->
+                            EnumerateDevices<LatencyTestDevice>().CreateDevice();
+        if (pLatencyTester)
+        {
+            LatencyUtil.SetDevice(pLatencyTester);
+            LogText("LATENCY TESTER connected\n");
+        }        
+    }
+    
+    return result;
+}
+
+void HMDState::ProcessLatencyTest2(unsigned char rgbColorOut[3], double startTime)
+{
+    // Check create.
+    if (!(EnabledHmdCaps & ovrHmdCap_LatencyTest))
+        return;
+
+    if (pLatencyTesterDisplay && !LatencyUtil2.HasDisplayDevice())
+    {
+        if (!pLatencyTesterDisplay->IsConnected())
+        {
+            LatencyUtil2.SetDisplayDevice(NULL);
+        }
+    }
+    else if (AddLatencyTestDisplayCount > 0)
+    {
+        // This might have some unlikely race condition issue
+        // which could cause us to miss a device...
+        AddLatencyTestDisplayCount = 0;
+
+        pLatencyTesterDisplay = *GlobalState::pInstance->GetManager()->
+                                 EnumerateDevices<LatencyTestDevice>().CreateDevice();
+        if (pLatencyTesterDisplay)
+        {
+            LatencyUtil2.SetDisplayDevice(pLatencyTesterDisplay);
+        }
+    }
+
+    if (LatencyUtil2.HasDevice() && pSensor && pSensor->IsConnected())
+    {
+        LatencyUtil2.BeginTest(startTime);
+
+        Color colorToDisplay;
+        LatencyTest2Active = LatencyUtil2.DisplayScreenColor(colorToDisplay);
+        rgbColorOut[0] = colorToDisplay.R;
+        rgbColorOut[1] = colorToDisplay.G;
+        rgbColorOut[2] = colorToDisplay.B;
+    }
+    else
+    {
+        LatencyTest2Active = false;
+    }
+}
+
+//-------------------------------------------------------------------------------------
+// *** Rendering
+
+bool HMDState::ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
+                                  const ovrFovPort eyeFovIn[2],
+                                  const ovrRenderAPIConfig* apiConfig,                                  
+                                  unsigned distortionCaps)
+{
+    ThreadChecker::Scope checkScope(&RenderAPIThreadChecker, "ovrHmd_ConfigureRendering");
+
+    // null -> shut down.
+    if (!apiConfig)
+    {
+        if (pRenderer)
+            pRenderer.Clear();        
+        RenderingConfigured = false; 
+        return true;
+    }
+
+    if (pRenderer &&
+        (apiConfig->Header.API != pRenderer->GetRenderAPI()))
+    {
+        // Shutdown old renderer.
+        if (pRenderer)
+            pRenderer.Clear();
+    }
+
+
+    // Step 1: do basic setup configuration
+    RenderState.setupRenderDesc(eyeRenderDescOut, eyeFovIn);
+    RenderState.EnabledHmdCaps = EnabledHmdCaps;     // This is a copy... Any cleaner way?
+    RenderState.DistortionCaps = distortionCaps;
+
+    TimeManager.ResetFrameTiming(0,
+                                 (EnabledHmdCaps & ovrHmdCap_DynamicPrediction) ? true : false,
+                                 true);
+
+    LastFrameTimeSeconds = 0.0f;
+
+    // Set RenderingConfigured early to avoid ASSERTs in renderer initialization.
+    RenderingConfigured = true;
+
+    if (!pRenderer)
+    {
+        pRenderer = *DistortionRenderer::APICreateRegistry
+                        [apiConfig->Header.API](this, TimeManager, RenderState);
+    }
+
+    if (!pRenderer ||
+        !pRenderer->Initialize(apiConfig, distortionCaps))
+    {
+        RenderingConfigured = false;
+        return false;
+    }    
+
+    return true;
+}
+
+
+
+ovrPosef HMDState::BeginEyeRender(ovrEyeType eye)
+{
+    // Debug checks.
+    checkBeginFrameScope("ovrHmd_BeginEyeRender");
+    ThreadChecker::Scope checkScope(&RenderAPIThreadChecker, "ovrHmd_BeginEyeRender");
+
+    // Unknown eyeId provided in ovrHmd_BeginEyeRender
+    OVR_ASSERT_LOG(eye == ovrEye_Left || eye == ovrEye_Right,
+                   ("ovrHmd_BeginEyeRender eyeId out of range."));     
+    OVR_ASSERT_LOG(EyeRenderActive[eye] == false,
+                   ("Multiple calls to ovrHmd_BeginEyeRender for the same eye."));
+
+    EyeRenderActive[eye] = true;
+    
+    // Only process latency tester for drawing the left eye (assumes left eye is drawn first)
+    if (pRenderer && eye == 0)
+    {
+        LatencyTestActive = ProcessLatencyTest(LatencyTestDrawColor);
+    }
+
+    return ovrHmd_GetEyePose(this, eye);
+}
+
+
+void HMDState::EndEyeRender(ovrEyeType eye, ovrPosef renderPose, ovrTexture* eyeTexture)
+{
+    // Debug checks.
+    checkBeginFrameScope("ovrHmd_EndEyeRender");
+    ThreadChecker::Scope checkScope(&RenderAPIThreadChecker, "ovrHmd_EndEyeRender");
+
+    if (!EyeRenderActive[eye])
+    {
+        OVR_ASSERT_LOG(false,
+                       ("ovrHmd_EndEyeRender called without ovrHmd_BeginEyeRender."));
+        return;
+    }
+
+    RenderState.EyeRenderPoses[eye] = renderPose;
+
+    if (pRenderer)
+        pRenderer->SubmitEye(eye, eyeTexture);
+
+    EyeRenderActive[eye] = false;
+}
+
+}} // namespace OVR::CAPI
+
diff --git a/LibOVR/Src/CAPI/CAPI_HMDState.h b/LibOVR/Src/CAPI/CAPI_HMDState.h
new file mode 100644
index 0000000..0a1466f
--- /dev/null
+++ b/LibOVR/Src/CAPI/CAPI_HMDState.h
@@ -0,0 +1,347 @@
+/************************************************************************************
+
+Filename    :   CAPI_HMDState.h
+Content     :   State associated with a single HMD
+Created     :   January 24, 2014
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_CAPI_HMDState_h
+#define OVR_CAPI_HMDState_h
+
+#include "../Kernel/OVR_Math.h"
+#include "../Kernel/OVR_List.h"
+#include "../Kernel/OVR_Log.h"
+#include "../OVR_CAPI.h"
+#include "../OVR_SensorFusion.h"
+#include "../Util/Util_LatencyTest.h"
+#include "../Util/Util_LatencyTest2.h"
+
+#include "CAPI_FrameTimeManager.h"
+#include "CAPI_HMDRenderState.h"
+#include "CAPI_DistortionRenderer.h"
+
+// Define OVR_CAPI_VISIONSUPPORT to compile in vision support 
+#ifdef OVR_CAPI_VISIONSUPPORT
+    #define OVR_CAPI_VISION_CODE(c) c
+    #include "../Vision/Vision_PoseTracker.h"
+#else
+    #define OVR_CAPI_VISION_CODE(c)
+#endif
+
+
+struct ovrHmdStruct { };
+
+namespace OVR { namespace CAPI {
+
+using namespace OVR::Util::Render;
+
+
+//-------------------------------------------------------------------------------------
+// ***** ThreadChecker
+
+// This helper class is used to verify that the API is used according to supported
+// thread safety constraints (is not re-entrant for this and related functions).
+class ThreadChecker
+{
+public:
+
+#ifndef OVR_BUILD_DEBUG
+
+    // In release build, thread checks are disabled.
+    ThreadChecker() { }
+    void Begin(const char* functionName)    { OVR_UNUSED1(functionName); }
+    void End()                              {  }
+
+    // Add thread-re-entrancy check for function scope
+    struct Scope
+    {
+        Scope(ThreadChecker*, const char *) { }
+        ~Scope() { }
+    };
+
+
+#else // OVR_BUILD_DEBUG
+    ThreadChecker() : pFunctionName(0), FirstThread(0)
+    { }
+
+    void Begin(const char* functionName)
+    {        
+        if (!pFunctionName)
+        {
+            pFunctionName = functionName;
+            FirstThread   = GetCurrentThreadId();
+        }
+        else
+        {
+            // pFunctionName may be not null here if function is called internally on the same thread.
+            OVR_ASSERT_LOG((FirstThread == GetCurrentThreadId()),
+                ("%s (threadId=%p) called at the same times as %s (threadId=%p)\n",
+                functionName, GetCurrentThreadId(), pFunctionName, FirstThread) );
+        }        
+    }
+    void End()
+    {
+        pFunctionName = 0;
+        FirstThread   = 0;
+    }
+
+    // Add thread-re-entrancy check for function scope.
+    struct Scope
+    {
+        Scope(ThreadChecker* threadChecker, const char *functionName) : pChecker(threadChecker)
+        { pChecker->Begin(functionName); }
+        ~Scope()
+        { pChecker->End(); }
+    private:
+        ThreadChecker* pChecker;
+    };
+
+private:
+    // If not 0, contains the name of the function that first entered the scope.
+    const char * pFunctionName;
+    ThreadId     FirstThread;
+
+#endif // OVR_BUILD_DEBUG
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** HMDState
+
+// Describes a single HMD.
+class HMDState : public ListNode<HMDState>,
+                 public ovrHmdStruct, public NewOverrideBase 
+{
+public:   
+
+    HMDState(HMDDevice* device);
+    HMDState(ovrHmdType hmdType);
+    virtual ~HMDState();
+
+
+    // *** Sensor Setup
+
+    bool            StartSensor(unsigned supportedCaps, unsigned requiredCaps);
+    void            StopSensor();
+    void            ResetSensor();
+    ovrSensorState  PredictedSensorState(double absTime);
+    bool            GetSensorDesc(ovrSensorDesc* descOut);
+
+    // Changes HMD Caps.
+    // Capability bits that are not directly or logically tied to one system (such as sensor)
+    // are grouped here. ovrHmdCap_VSync, for example, affects rendering and timing.
+    void            SetEnabledHmdCaps(unsigned caps);
+
+
+    bool            ProcessLatencyTest(unsigned char rgbColorOut[3]);
+    void            ProcessLatencyTest2(unsigned char rgbColorOut[3], double startTime);
+    
+
+    // *** Rendering Setup
+
+    bool       ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2],
+                                  const ovrFovPort eyeFovIn[2],
+                                  const ovrRenderAPIConfig* apiConfig,                                  
+                                  unsigned distortionCaps);  
+    
+    ovrPosef    BeginEyeRender(ovrEyeType eye);
+    void        EndEyeRender(ovrEyeType eye, ovrPosef renderPose, ovrTexture* eyeTexture);
+
+
+    const char* GetLastError()
+    {
+        const char* p = pLastError;
+        pLastError = 0;
+        return p;
+    }    
+
+    void NotifyAddDevice(DeviceType deviceType)
+    {
+        if (deviceType == Device_Sensor)
+            AddSensorCount++;
+        else if (deviceType == Device_LatencyTester)
+        {
+            AddLatencyTestCount++;
+            AddLatencyTestDisplayCount++;
+        }
+    }
+
+    bool checkCreateSensor();
+
+    void applyProfileToSensorFusion();
+
+    // INlines so that they can be easily compiled out.    
+    // Does debug ASSERT checks for functions that require BeginFrame.
+    // Also verifies that we are on the right thread.
+    void checkBeginFrameScope(const char* functionName)
+    {
+        OVR_UNUSED1(functionName); // for Release build.
+        OVR_ASSERT_LOG(BeginFrameCalled == true,
+                       ("%s called outside ovrHmd_BeginFrame.", functionName));
+        OVR_ASSERT_LOG(BeginFrameThreadId == OVR::GetCurrentThreadId(),
+                       ("%s called on a different thread then ovrHmd_BeginFrame.", functionName));
+    }
+
+    void checkRenderingConfigured(const char* functionName)
+    {
+        OVR_UNUSED1(functionName); // for Release build.
+        OVR_ASSERT_LOG(RenderingConfigured == true,
+                       ("%s called without ovrHmd_ConfigureRendering.", functionName));
+    }
+
+    void checkBeginFrameTimingScope(const char* functionName)
+    {
+        OVR_UNUSED1(functionName); // for Release build.
+        OVR_ASSERT_LOG(BeginFrameTimingCalled == true,
+                       ("%s called outside ovrHmd_BeginFrameTiming.", functionName));
+    }
+
+
+    HMDState* getThis() { return this; }
+
+    void updateLowPersistenceMode(bool lowPersistence) const;
+	void updateLatencyTestForHmd(bool latencyTesting);
+
+    void updateDK2FeaturesTiedToSensor(bool sensorCreatedJustNow);
+    
+	// Get properties by name.
+	float    getFloatValue(const char* propertyName, float defaultVal);
+    bool     setFloatValue(const char* propertyName, float value);
+	unsigned getFloatArray(const char* propertyName, float values[], unsigned arraySize);
+    bool     setFloatArray(const char* propertyName, float values[], unsigned arraySize);
+	const char* getString(const char* propertyName, const char* defaultVal);
+public:
+    
+    // Wrapper to support 'const'
+    struct HMDInfoWrapper
+    {
+        HMDInfoWrapper(ovrHmdType hmdType)
+        {
+            HmdTypeEnum t = HmdType_None;
+            if (hmdType == ovrHmd_DK1)
+                t = HmdType_DK1;
+            else if (hmdType == ovrHmd_CrystalCoveProto)
+                t = HmdType_CrystalCoveProto;
+            else if (hmdType == ovrHmd_DK2)
+                t = HmdType_DK2;
+            h = CreateDebugHMDInfo(t);
+        }
+        HMDInfoWrapper(HMDDevice* device) { if (device) device->GetDeviceInfo(&h); }
+        OVR::HMDInfo h;
+    };
+
+    // Note: pHMD can be null if we are representing a virtualized debug HMD.
+    Ptr<HMDDevice>          pHMD;
+
+    // HMDInfo shouldn't change, as its string pointers are passed out.
+    const HMDInfoWrapper    HMDInfoW;
+    const OVR::HMDInfo&     HMDInfo;
+
+    const char*             pLastError;
+
+    // Caps enabled for the HMD.
+    unsigned                EnabledHmdCaps;
+    // These are the flags actually applied to the Sensor device,
+    // used to track whether SetDisplayReport calls are necessary.
+    unsigned                HmdCapsAppliedToSensor;
+
+    
+    // *** Sensor
+
+    // Lock used to support thread-safe lifetime access to sensor.
+    Lock                    DevicesLock;
+
+    // Atomic integer used as a flag that we should check the sensor device.
+    AtomicInt<int>          AddSensorCount;    
+
+    // All of Sensor variables may be modified/used with DevicesLock, with exception that
+    // the {SensorStarted, SensorCreated} can be read outside the lock to see
+    // if device creation check is necessary.
+    // Whether we called StartSensor() and requested sensor caps.    
+    volatile bool           SensorStarted;
+    volatile bool           SensorCreated;
+    // pSensor may still be null or non-running after start if it wasn't yet available
+    Ptr<SensorDevice>       pSensor;	// Head
+    unsigned                SensorCaps;    
+
+    // SensorFusion state may be accessible without a lock.
+    SensorFusion            SFusion;
+
+    
+    // Vision pose tracker is currently new-allocated
+    OVR_CAPI_VISION_CODE(
+    Vision::PoseTracker*    pPoseTracker;
+    )
+    
+    // Latency tester
+    Ptr<LatencyTestDevice>  pLatencyTester;
+    Util::LatencyTest	    LatencyUtil;
+    AtomicInt<int>          AddLatencyTestCount;
+
+    bool                    LatencyTestActive;
+    unsigned char           LatencyTestDrawColor[3];
+
+    // Using latency tester as debug display
+    Ptr<LatencyTestDevice>  pLatencyTesterDisplay;
+    AtomicInt<int>          AddLatencyTestDisplayCount;
+    Util::LatencyTest2	    LatencyUtil2;
+
+    bool                    LatencyTest2Active;
+    unsigned char           LatencyTest2DrawColor[3];
+    //bool                    ReadbackColor;
+
+    // Rendering part
+    FrameTimeManager        TimeManager;
+    HMDRenderState          RenderState;
+    Ptr<DistortionRenderer> pRenderer;
+       
+    // Last timing value reported by BeginFrame.
+    double                  LastFrameTimeSeconds;    
+    // Last timing value reported by GetFrameTime. These are separate since the intended
+    // use is from different threads. TBD: Move to FrameTimeManager? Make atomic?
+    double                  LastGetFrameTimeSeconds;
+
+    // Last cached value returned by ovrHmd_GetString/ovrHmd_GetStringArray.
+    char                    LastGetStringValue[256];
+   
+
+    // Debug flag set after ovrHmd_ConfigureRendering succeeds.
+    bool                    RenderingConfigured;
+    // Set after BeginFrame succeeds, and its corresponding thread id for debug checks.
+    bool                    BeginFrameCalled;
+    ThreadId                BeginFrameThreadId;    
+    // Graphics functions are not re-entrant from other threads.
+    ThreadChecker           RenderAPIThreadChecker;
+    // 
+    bool                    BeginFrameTimingCalled;
+    
+    // Flags set when we've called BeginEyeRender on a given eye.
+    bool                    EyeRenderActive[2];
+};
+
+
+}} // namespace OVR::CAPI
+
+
+#endif // OVR_CAPI_HMDState_h
+
+
diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp
new file mode 100644
index 0000000..21b6509
--- /dev/null
+++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp
@@ -0,0 +1,784 @@
+/************************************************************************************
+
+Filename    :   CAPI_GL_DistortionRenderer.h
+Content     :   Distortion renderer header for GL
+Created     :   November 11, 2013
+Authors     :   David Borel, Lee Cooper
+
+Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
+
+Use of this software is subject to the terms of the Oculus Inc license
+agreement provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+************************************************************************************/
+
+#include "CAPI_GL_DistortionRenderer.h"
+
+#include "CAPI_GL_DistortionShaders.h"
+
+#include "../../OVR_CAPI_GL.h"
+
+namespace OVR { namespace CAPI { namespace GL {
+
+// Distortion pixel shader lookup.
+//  Bit 0: Chroma Correction
+//  Bit 1: Timewarp
+
+enum {
+    DistortionVertexShaderBitMask = 3,
+    DistortionVertexShaderCount   = DistortionVertexShaderBitMask + 1,
+    DistortionPixelShaderBitMask  = 1,
+    DistortionPixelShaderCount    = DistortionPixelShaderBitMask + 1
+};
+
+struct ShaderInfo
+{
+    const char* ShaderData;
+    size_t ShaderSize;
+    const ShaderBase::Uniform* ReflectionData;
+    size_t ReflectionSize;
+};
+
+// Do add a new distortion shader use these macros (with or w/o reflection)
+#define SI_NOREFL(shader) { shader, sizeof(shader), NULL, 0 }
+#define SI_REFL__(shader) { shader, sizeof(shader), shader ## _refl, sizeof( shader ## _refl )/sizeof(*(shader ## _refl)) }
+
+
+static ShaderInfo DistortionVertexShaderLookup[DistortionVertexShaderCount] =
+{
+    SI_REFL__(Distortion_vs),
+    SI_REFL__(DistortionChroma_vs),
+    SI_REFL__(DistortionTimewarp_vs),
+    SI_REFL__(DistortionTimewarpChroma_vs)
+};
+
+static ShaderInfo DistortionPixelShaderLookup[DistortionPixelShaderCount] =
+{
+    SI_NOREFL(Distortion_fs),
+    SI_NOREFL(DistortionChroma_fs)
+};
+
+void DistortionShaderBitIndexCheck()
+{
+    OVR_COMPILER_ASSERT(ovrDistortionCap_Chromatic == 1);
+    OVR_COMPILER_ASSERT(ovrDistortionCap_TimeWarp  == 2);
+}
+
+
+
+struct DistortionVertex
+{
+    Vector2f Pos;
+    Vector2f TexR;
+    Vector2f TexG;
+    Vector2f TexB;
+    Color    Col;
+};
+
+
+// Vertex type; same format is used for all shapes for simplicity.
+// Shapes are built by adding vertices to Model.
+struct LatencyVertex
+{
+    Vector3f  Pos;
+    LatencyVertex (const Vector3f& p) : Pos(p) {}
+};
+
+
+//----------------------------------------------------------------------------
+// ***** GL::DistortionRenderer
+
+DistortionRenderer::DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager,
+                                       const HMDRenderState& renderState)
+    : CAPI::DistortionRenderer(ovrRenderAPI_OpenGL, hmd, timeManager, renderState)
+	, LatencyVAO(0)
+{
+	DistortionMeshVAOs[0] = 0;
+	DistortionMeshVAOs[1] = 0;
+}
+
+DistortionRenderer::~DistortionRenderer()
+{
+    destroy();
+}
+
+// static
+CAPI::DistortionRenderer* DistortionRenderer::Create(ovrHmd hmd,
+                                                     FrameTimeManager& timeManager,
+                                                     const HMDRenderState& renderState)
+{
+#if !defined(OVR_OS_MAC)
+    InitGLExtensions();
+#endif
+    return new DistortionRenderer(hmd, timeManager, renderState);
+}
+
+
+bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig,
+									unsigned distortionCaps)
+{
+	GfxState = *new GraphicsState();
+
+    const ovrGLConfig* config = (const ovrGLConfig*)apiConfig;
+
+    if (!config)
+    {
+        // Cleanup
+        pEyeTextures[0].Clear();
+        pEyeTextures[1].Clear();
+        memset(&RParams, 0, sizeof(RParams));
+        return true;
+    }
+
+	RParams.Multisample = config->OGL.Header.Multisample;
+	RParams.RTSize      = config->OGL.Header.RTSize;
+#if defined(OVR_OS_WIN32)
+	RParams.Window      = (config->OGL.Window) ? config->OGL.Window : GetActiveWindow();
+#elif defined(OVR_OS_LINUX)
+    RParams.Disp        = (config->OGL.Disp) ? config->OGL.Disp : XOpenDisplay(NULL);
+    RParams.Win         = config->OGL.Win;
+    if (!RParams.Win)
+    {
+        int unused;
+        XGetInputFocus(RParams.Disp, &RParams.Win, &unused);
+    }
+#endif
+	
+    DistortionCaps = distortionCaps;
+	
+    //DistortionWarper.SetVsync((hmdCaps & ovrHmdCap_NoVSync) ? false : true);
+
+    pEyeTextures[0] = *new Texture(&RParams, 0, 0);
+    pEyeTextures[1] = *new Texture(&RParams, 0, 0);
+
+    initBuffersAndShaders();
+
+    return true;
+}
+
+
+void DistortionRenderer::SubmitEye(int eyeId, ovrTexture* eyeTexture)
+{
+	// Doesn't do a lot in here??
+	const ovrGLTexture* tex = (const ovrGLTexture*)eyeTexture;
+
+	// Write in values
+    eachEye[eyeId].texture = tex->OGL.TexId;
+
+	if (tex)
+	{
+        // Its only at this point we discover what the viewport of the texture is.
+	    // because presumably we allow users to realtime adjust the resolution.
+        eachEye[eyeId].TextureSize    = tex->OGL.Header.TextureSize;
+        eachEye[eyeId].RenderViewport = tex->OGL.Header.RenderViewport;
+
+        const ovrEyeRenderDesc& erd = RState.EyeRenderDesc[eyeId];
+    
+        ovrHmd_GetRenderScaleAndOffset( erd.Fov,
+                                        eachEye[eyeId].TextureSize, eachEye[eyeId].RenderViewport,
+                                        eachEye[eyeId].UVScaleOffset );
+
+        pEyeTextures[eyeId]->UpdatePlaceholderTexture(tex->OGL.TexId,
+                                                      tex->OGL.Header.TextureSize);
+	}
+}
+
+void DistortionRenderer::EndFrame(bool swapBuffers,
+                                  unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor)
+{
+    if (!TimeManager.NeedDistortionTimeMeasurement())
+    {
+		if (RState.DistortionCaps & ovrDistortionCap_TimeWarp)
+		{
+			// Wait for timewarp distortion if it is time and Gpu idle
+			FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime);
+		}
+
+        renderDistortion(pEyeTextures[0], pEyeTextures[1]);
+    }
+    else
+    {
+        // If needed, measure distortion time so that TimeManager can better estimate
+        // latency-reducing time-warp wait timing.
+        WaitUntilGpuIdle();
+        double  distortionStartTime = ovr_GetTimeInSeconds();
+
+        renderDistortion(pEyeTextures[0], pEyeTextures[1]);
+
+        WaitUntilGpuIdle();
+        TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime);
+    }
+
+    if(latencyTesterDrawColor)
+    {
+        renderLatencyQuad(latencyTesterDrawColor);
+    }
+    else if(latencyTester2DrawColor)
+    {
+        renderLatencyPixel(latencyTester2DrawColor);
+    }
+
+    if (swapBuffers)
+    {
+		bool useVsync = ((RState.EnabledHmdCaps & ovrHmdCap_NoVSync) == 0);
+		int swapInterval = (useVsync) ? 1 : 0;
+#if defined(OVR_OS_WIN32)
+		if (wglGetSwapIntervalEXT() != swapInterval)
+            wglSwapIntervalEXT(swapInterval);
+
+        HDC dc = GetDC(RParams.Window);
+		BOOL success = SwapBuffers(dc);
+        ReleaseDC(RParams.Window, dc);
+		OVR_ASSERT(success);
+        OVR_UNUSED(success);
+#elif defined(OVR_OS_MAC)
+        CGLContextObj context = CGLGetCurrentContext();
+        GLint currentSwapInterval = 0;
+        CGLGetParameter(context, kCGLCPSwapInterval, &currentSwapInterval);
+        if (currentSwapInterval != swapInterval)
+            CGLSetParameter(context, kCGLCPSwapInterval, &swapInterval);
+        
+        CGLFlushDrawable(context);
+#elif defined(OVR_OS_LINUX)
+        static const char* extensions = glXQueryExtensionsString(RParams.Disp, 0);
+        static bool supportsVSync = (extensions != NULL && strstr(extensions, "GLX_EXT_swap_control"));
+        if (supportsVSync)
+        {
+            GLuint currentSwapInterval = 0;
+            glXQueryDrawable(RParams.Disp, RParams.Win, GLX_SWAP_INTERVAL_EXT, &currentSwapInterval);
+            if (currentSwapInterval != swapInterval)
+                glXSwapIntervalEXT(RParams.Disp, RParams.Win, swapInterval);
+        }
+
+        glXSwapBuffers(RParams.Disp, RParams.Win);
+#endif
+    }
+}
+
+void DistortionRenderer::WaitUntilGpuIdle()
+{
+	glFlush();
+	glFinish();
+}
+
+double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime)
+{
+	double       initialTime = ovr_GetTimeInSeconds();
+	if (initialTime >= absTime)
+		return 0.0;
+	
+	glFlush();
+	glFinish();
+
+	double newTime   = initialTime;
+	volatile int i;
+
+	while (newTime < absTime)
+	{
+		for (int j = 0; j < 50; j++)
+			i = 0;
+
+		newTime = ovr_GetTimeInSeconds();
+	}
+
+	// How long we waited
+	return newTime - initialTime;
+}
+    
+    
+DistortionRenderer::GraphicsState::GraphicsState()
+{
+    const char* glVersionString = (const char*)glGetString(GL_VERSION);
+    OVR_DEBUG_LOG(("GL_VERSION STRING: %s", (const char*)glVersionString));
+    char prefix[64];
+    bool foundVersion = false;
+    
+    for (int i = 10; i < 30; ++i)
+    {
+        int major = i / 10;
+        int minor = i % 10;
+        OVR_sprintf(prefix, 64, "%d.%d", major, minor);
+        if (strstr(glVersionString, prefix) == glVersionString)
+        {
+            GlMajorVersion = major;
+            GlMinorVersion = minor;
+            foundVersion = true;
+            break;
+        }
+    }
+    
+    if (!foundVersion)
+    {
+        glGetIntegerv(GL_MAJOR_VERSION, &GlMajorVersion);
+        glGetIntegerv(GL_MAJOR_VERSION, &GlMinorVersion);
+	}
+
+	OVR_ASSERT(GlMajorVersion >= 2);
+    
+    if (GlMajorVersion >= 3)
+    {
+        SupportsVao = true;
+    }
+    else
+    {
+        const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
+        SupportsVao = (strstr("GL_ARB_vertex_array_object", extensions) != NULL);
+    }
+}
+    
+    
+void DistortionRenderer::GraphicsState::ApplyBool(GLenum Name, GLint Value)
+{
+    if (Value != 0)
+        glEnable(Name);
+    else
+        glDisable(Name);
+}
+    
+    
+void DistortionRenderer::GraphicsState::Save()
+{
+    glGetIntegerv(GL_VIEWPORT, Viewport);
+    glGetFloatv(GL_COLOR_CLEAR_VALUE, ClearColor);
+    glGetIntegerv(GL_DEPTH_TEST, &DepthTest);
+    glGetIntegerv(GL_CULL_FACE, &CullFace);
+    glGetIntegerv(GL_CURRENT_PROGRAM, &Program);
+    glGetIntegerv(GL_ACTIVE_TEXTURE, &ActiveTexture);
+    glGetIntegerv(GL_TEXTURE_BINDING_2D, &TextureBinding);
+    glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &VertexArray);
+    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &FrameBufferBinding);
+    glGetIntegerv(GL_BLEND, &Blend);
+    glGetIntegerv(GL_COLOR_WRITEMASK, ColorWritemask);
+    glGetIntegerv(GL_DITHER, &Dither);
+    glGetIntegerv(GL_RASTERIZER_DISCARD, &RasterizerDiscard);
+    if (GlMajorVersion >= 3 && GlMajorVersion >= 2)
+        glGetIntegerv(GL_SAMPLE_MASK, &SampleMask);
+	glGetIntegerv(GL_SCISSOR_TEST, &ScissorTest);
+
+	IsValid = true;
+}
+    
+
+void DistortionRenderer::GraphicsState::Restore()
+{
+	// Don't allow restore-before-save.
+	if (!IsValid)
+		return;
+
+    glViewport(Viewport[0], Viewport[1], Viewport[2], Viewport[3]);
+    glClearColor(ClearColor[0], ClearColor[1], ClearColor[2], ClearColor[3]);
+    
+    ApplyBool(GL_DEPTH_TEST, DepthTest);
+    ApplyBool(GL_CULL_FACE, CullFace);
+    
+    glUseProgram(Program);
+    glActiveTexture(ActiveTexture);
+    glBindTexture(GL_TEXTURE_2D, TextureBinding);
+    if (SupportsVao)
+        glBindVertexArray(VertexArray);
+    glBindFramebuffer(GL_FRAMEBUFFER, FrameBufferBinding);
+    
+    ApplyBool(GL_BLEND, Blend);
+    
+	glColorMask((GLboolean)ColorWritemask[0], (GLboolean)ColorWritemask[1], (GLboolean)ColorWritemask[2], (GLboolean)ColorWritemask[3]);
+    ApplyBool(GL_DITHER, Dither);
+    ApplyBool(GL_RASTERIZER_DISCARD, RasterizerDiscard);
+    if (GlMajorVersion >= 3 && GlMajorVersion >= 2)
+        ApplyBool(GL_SAMPLE_MASK, SampleMask);
+    ApplyBool(GL_SCISSOR_TEST, ScissorTest);
+}
+
+
+void DistortionRenderer::initBuffersAndShaders()
+{
+    for ( int eyeNum = 0; eyeNum < 2; eyeNum++ )
+    {
+        // Allocate & generate distortion mesh vertices.
+        ovrDistortionMesh meshData;
+
+//        double startT = ovr_GetTimeInSeconds();
+
+        if (!ovrHmd_CreateDistortionMesh( HMD,
+                                          RState.EyeRenderDesc[eyeNum].Eye,
+                                          RState.EyeRenderDesc[eyeNum].Fov,
+                                          RState.DistortionCaps,
+                                          &meshData) )
+        {
+            OVR_ASSERT(false);
+            continue;
+        }
+
+        // Now parse the vertex data and create a render ready vertex buffer from it
+        DistortionVertex *   pVBVerts    = (DistortionVertex*)OVR_ALLOC ( sizeof(DistortionVertex) * meshData.VertexCount );
+        DistortionVertex *   pCurVBVert  = pVBVerts;
+        ovrDistortionVertex* pCurOvrVert = meshData.pVertexData;
+
+        for ( unsigned vertNum = 0; vertNum < meshData.VertexCount; vertNum++ )
+        {
+            pCurVBVert->Pos.x = pCurOvrVert->Pos.x;
+            pCurVBVert->Pos.y = pCurOvrVert->Pos.y;
+            pCurVBVert->TexR  = (*(Vector2f*)&pCurOvrVert->TexR);
+            pCurVBVert->TexG  = (*(Vector2f*)&pCurOvrVert->TexG);
+            pCurVBVert->TexB  = (*(Vector2f*)&pCurOvrVert->TexB);
+            // Convert [0.0f,1.0f] to [0,255]
+            pCurVBVert->Col.R = (OVR::UByte)( pCurOvrVert->VignetteFactor * 255.99f );
+            pCurVBVert->Col.G = pCurVBVert->Col.R;
+            pCurVBVert->Col.B = pCurVBVert->Col.R;
+            pCurVBVert->Col.A = (OVR::UByte)( pCurOvrVert->TimeWarpFactor * 255.99f );;
+            pCurOvrVert++;
+            pCurVBVert++;
+        }
+
+        DistortionMeshVBs[eyeNum] = *new Buffer(&RParams);
+        DistortionMeshVBs[eyeNum]->Data ( Buffer_Vertex | Buffer_ReadOnly, pVBVerts, sizeof(DistortionVertex) * meshData.VertexCount );
+        DistortionMeshIBs[eyeNum] = *new Buffer(&RParams);
+        DistortionMeshIBs[eyeNum]->Data ( Buffer_Index | Buffer_ReadOnly, meshData.pIndexData, ( sizeof(SInt16) * meshData.IndexCount ) );
+
+        OVR_FREE ( pVBVerts );
+        ovrHmd_DestroyDistortionMesh( &meshData );
+    }
+
+    initShaders();
+}
+
+void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture)
+{
+    GraphicsState* glState = (GraphicsState*)GfxState.GetPtr();
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    setViewport( Recti(0,0, RParams.RTSize.w, RParams.RTSize.h) );
+
+	glDisable(GL_CULL_FACE);
+	glDisable(GL_DEPTH_TEST);
+    glDisable(GL_BLEND);
+    
+    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+    glDisable(GL_DITHER);
+    glDisable(GL_RASTERIZER_DISCARD);
+    if (glState->GlMajorVersion >= 3 && glState->GlMajorVersion >= 2)
+        glDisable(GL_SAMPLE_MASK);
+    glDisable(GL_SCISSOR_TEST);
+        
+	glClearColor(
+		RState.ClearColor[0],
+		RState.ClearColor[1],
+		RState.ClearColor[2],
+		RState.ClearColor[3] );
+
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    for (int eyeNum = 0; eyeNum < 2; eyeNum++)
+    {        
+		ShaderFill distortionShaderFill(DistortionShader);
+        distortionShaderFill.SetTexture(0, eyeNum == 0 ? leftEyeTexture : rightEyeTexture);
+
+		DistortionShader->SetUniform2f("EyeToSourceUVScale",  eachEye[eyeNum].UVScaleOffset[0].x, eachEye[eyeNum].UVScaleOffset[0].y);
+		DistortionShader->SetUniform2f("EyeToSourceUVOffset", eachEye[eyeNum].UVScaleOffset[1].x, eachEye[eyeNum].UVScaleOffset[1].y);
+        
+		if (DistortionCaps & ovrDistortionCap_TimeWarp)
+		{                       
+            ovrMatrix4f timeWarpMatrices[2];            
+            ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum,
+                                          RState.EyeRenderPoses[eyeNum], timeWarpMatrices);
+
+            // Feed identity like matrices in until we get proper timewarp calculation going on
+			DistortionShader->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0]).Transposed());
+			DistortionShader->SetUniform4x4f("EyeRotationEnd",   Matrix4f(timeWarpMatrices[1]).Transposed());
+
+            renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum],
+                            0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true);
+		}
+        else
+        {
+            renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum],
+                            0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles, &DistortionMeshVAOs[eyeNum], true);
+        }
+    }
+}
+
+void DistortionRenderer::createDrawQuad()
+{
+    const int numQuadVerts = 4;
+    LatencyTesterQuadVB = *new Buffer(&RParams);
+    if(!LatencyTesterQuadVB)
+    {
+        return;
+    }
+
+    LatencyTesterQuadVB->Data(Buffer_Vertex, NULL, numQuadVerts * sizeof(LatencyVertex));
+    LatencyVertex* vertices = (LatencyVertex*)LatencyTesterQuadVB->Map(0, numQuadVerts * sizeof(LatencyVertex), Map_Discard);
+    if(!vertices)
+    {
+        OVR_ASSERT(false); // failed to lock vertex buffer
+        return;
+    }
+
+    const float left   = -1.0f;
+    const float top    = -1.0f;
+    const float right  =  1.0f;
+    const float bottom =  1.0f;
+
+    vertices[0] = LatencyVertex(Vector3f(left,  top,    0.0f));
+    vertices[1] = LatencyVertex(Vector3f(left,  bottom, 0.0f));
+    vertices[2] = LatencyVertex(Vector3f(right, top,    0.0f));
+    vertices[3] = LatencyVertex(Vector3f(right, bottom, 0.0f));
+
+    LatencyTesterQuadVB->Unmap(vertices);
+}
+
+void DistortionRenderer::renderLatencyQuad(unsigned char* latencyTesterDrawColor)
+{
+    const int numQuadVerts = 4;
+
+    if(!LatencyTesterQuadVB)
+    {
+        createDrawQuad();
+    }
+       
+    ShaderFill quadFill(SimpleQuadShader);
+    //quadFill.SetInputLayout(SimpleQuadVertexIL);
+
+    setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h));
+
+    SimpleQuadShader->SetUniform2f("Scale", 0.2f, 0.2f);
+    SimpleQuadShader->SetUniform4f("Color", (float)latencyTesterDrawColor[0] / 255.99f,
+                                            (float)latencyTesterDrawColor[0] / 255.99f,
+                                            (float)latencyTesterDrawColor[0] / 255.99f,
+                                            1.0f);
+
+    for(int eyeNum = 0; eyeNum < 2; eyeNum++)
+    {
+        SimpleQuadShader->SetUniform2f("PositionOffset", eyeNum == 0 ? -0.4f : 0.4f, 0.0f);    
+        renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false);
+    }
+}
+
+void DistortionRenderer::renderLatencyPixel(unsigned char* latencyTesterPixelColor)
+{
+    const int numQuadVerts = 4;
+
+    if(!LatencyTesterQuadVB)
+    {
+        createDrawQuad();
+    }
+
+    ShaderFill quadFill(SimpleQuadShader);
+
+    setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h));
+
+    SimpleQuadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f,
+                                            (float)latencyTesterPixelColor[0] / 255.99f,
+                                            (float)latencyTesterPixelColor[0] / 255.99f,
+                                            1.0f);
+
+    Vector2f scale(2.0f / RParams.RTSize.w, 2.0f / RParams.RTSize.h); 
+    SimpleQuadShader->SetUniform2f("Scale", scale.x, scale.y);
+    SimpleQuadShader->SetUniform2f("PositionOffset", 1.0f, 1.0f);
+	renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, 0, numQuadVerts, Prim_TriangleStrip, &LatencyVAO, false);
+}
+
+void DistortionRenderer::renderPrimitives(
+                          const ShaderFill* fill,
+                          Buffer* vertices, Buffer* indices,
+                          int offset, int count,
+                          PrimitiveType rprim, GLuint* vao, bool isDistortionMesh)
+{
+    GraphicsState* glState = (GraphicsState*)GfxState.GetPtr();
+
+    GLenum prim;
+    switch (rprim)
+    {
+    case Prim_Triangles:
+        prim = GL_TRIANGLES;
+        break;
+    case Prim_Lines:
+        prim = GL_LINES;
+        break;
+    case Prim_TriangleStrip:
+        prim = GL_TRIANGLE_STRIP;
+        break;
+    default:
+        OVR_ASSERT(false);
+        return;
+    }
+
+    fill->Set();
+    
+    GLuint prog = fill->GetShaders()->Prog;
+
+	if (vao != NULL)
+	{
+		if (*vao != 0)
+		{
+			glBindVertexArray(*vao);
+
+			if (isDistortionMesh)
+				glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
+			else
+				glDrawArrays(prim, 0, count);
+		}
+		else
+		{
+            if (glState->SupportsVao)
+            {
+                glGenVertexArrays(1, vao);
+                glBindVertexArray(*vao);
+			}
+
+			int attributeCount = (isDistortionMesh) ? 5 : 1;
+			int* locs = new int[attributeCount];
+
+			glBindBuffer(GL_ARRAY_BUFFER, ((Buffer*)vertices)->GLBuffer);
+
+			if (isDistortionMesh)
+			{
+				glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ((Buffer*)indices)->GLBuffer);
+
+				locs[0] = glGetAttribLocation(prog, "Position");
+				locs[1] = glGetAttribLocation(prog, "Color");
+				locs[2] = glGetAttribLocation(prog, "TexCoord0");
+				locs[3] = glGetAttribLocation(prog, "TexCoord1");
+				locs[4] = glGetAttribLocation(prog, "TexCoord2");
+
+				glVertexAttribPointer(locs[0], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, Pos));
+				glVertexAttribPointer(locs[1], 4, GL_UNSIGNED_BYTE, true, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, Col));
+				glVertexAttribPointer(locs[2], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TexR));
+				glVertexAttribPointer(locs[3], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TexG));
+				glVertexAttribPointer(locs[4], 2, GL_FLOAT, false, sizeof(DistortionVertex), reinterpret_cast<char*>(offset)+offsetof(DistortionVertex, TexB));
+			}
+			else
+			{
+				locs[0] = glGetAttribLocation(prog, "Position");
+
+				glVertexAttribPointer(locs[0], 3, GL_FLOAT, false, sizeof(LatencyVertex), reinterpret_cast<char*>(offset)+offsetof(LatencyVertex, Pos));
+			}
+
+            for (int i = 0; i < attributeCount; ++i)
+                glEnableVertexAttribArray(locs[i]);
+            
+			if (isDistortionMesh)
+				glDrawElements(prim, count, GL_UNSIGNED_SHORT, NULL);
+			else
+				glDrawArrays(prim, 0, count);
+
+
+            if (!glState->SupportsVao)
+            {
+				for (int i = 0; i < attributeCount; ++i)
+                    glDisableVertexAttribArray(locs[i]);
+            }
+
+			delete[] locs;
+		}
+	}
+}
+
+void DistortionRenderer::setViewport(const Recti& vp)
+{
+    glViewport(vp.x, vp.y, vp.w, vp.h);
+}
+
+
+void DistortionRenderer::initShaders()
+{
+    GraphicsState* glState = (GraphicsState*)GfxState.GetPtr();
+
+    const char* shaderPrefix =
+        (glState->GlMajorVersion < 3 || (glState->GlMajorVersion == 3 && glState->GlMinorVersion < 2)) ?
+            glsl2Prefix : glsl3Prefix;
+
+    {
+		ShaderInfo vsInfo = DistortionVertexShaderLookup[DistortionVertexShaderBitMask & DistortionCaps];
+
+		size_t vsSize = strlen(shaderPrefix)+vsInfo.ShaderSize;
+		char* vsSource = new char[vsSize];
+		OVR_strcpy(vsSource, vsSize, shaderPrefix);
+		OVR_strcat(vsSource, vsSize, vsInfo.ShaderData);
+
+        Ptr<GL::VertexShader> vs = *new GL::VertexShader(
+            &RParams,
+			(void*)vsSource, vsSize,
+			vsInfo.ReflectionData, vsInfo.ReflectionSize);
+
+        DistortionShader = *new ShaderSet;
+        DistortionShader->SetShader(vs);
+
+		delete[](vsSource);
+
+		ShaderInfo psInfo = DistortionPixelShaderLookup[DistortionPixelShaderBitMask & DistortionCaps];
+
+		size_t psSize = strlen(shaderPrefix)+psInfo.ShaderSize;
+		char* psSource = new char[psSize];
+		OVR_strcpy(psSource, psSize, shaderPrefix);
+		OVR_strcat(psSource, psSize, psInfo.ShaderData);
+
+        Ptr<GL::FragmentShader> ps  = *new GL::FragmentShader(
+            &RParams,
+			(void*)psSource, psSize,
+			psInfo.ReflectionData, psInfo.ReflectionSize);
+
+        DistortionShader->SetShader(ps);
+
+		delete[](psSource);
+    }
+	{
+		size_t vsSize = strlen(shaderPrefix)+sizeof(SimpleQuad_vs);
+		char* vsSource = new char[vsSize];
+		OVR_strcpy(vsSource, vsSize, shaderPrefix);
+		OVR_strcat(vsSource, vsSize, SimpleQuad_vs);
+
+        Ptr<GL::VertexShader> vs = *new GL::VertexShader(
+            &RParams,
+            (void*)vsSource, vsSize,
+			SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0]));
+
+        SimpleQuadShader = *new ShaderSet;
+		SimpleQuadShader->SetShader(vs);
+
+		delete[](vsSource);
+
+		size_t psSize = strlen(shaderPrefix)+sizeof(SimpleQuad_fs);
+		char* psSource = new char[psSize];
+		OVR_strcpy(psSource, psSize, shaderPrefix);
+		OVR_strcat(psSource, psSize, SimpleQuad_fs);
+
+        Ptr<GL::FragmentShader> ps  = *new GL::FragmentShader(
+            &RParams,
+            (void*)psSource, psSize,
+            SimpleQuad_fs_refl, sizeof(SimpleQuad_fs_refl) / sizeof(SimpleQuad_fs_refl[0]));
+
+		SimpleQuadShader->SetShader(ps);
+
+		delete[](psSource);
+	}
+}
+
+
+void DistortionRenderer::destroy()
+{
+    GraphicsState* glState = (GraphicsState*)GfxState.GetPtr();
+
+	for(int eyeNum = 0; eyeNum < 2; eyeNum++)
+	{
+        if (glState->SupportsVao)
+            glDeleteVertexArrays(1, &DistortionMeshVAOs[eyeNum]);
+
+		DistortionMeshVAOs[eyeNum] = 0;
+
+		DistortionMeshVBs[eyeNum].Clear();
+		DistortionMeshIBs[eyeNum].Clear();
+	}
+
+	if (DistortionShader)
+    {
+        DistortionShader->UnsetShader(Shader_Vertex);
+	    DistortionShader->UnsetShader(Shader_Pixel);
+	    DistortionShader.Clear();
+    }
+
+    LatencyTesterQuadVB.Clear();
+	LatencyVAO = 0;
+}
+
+}}} // OVR::CAPI::GL
diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h
new file mode 100644
index 0000000..60f1a9f
--- /dev/null
+++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h
@@ -0,0 +1,178 @@
+/************************************************************************************
+
+Filename    :   CAPI_GL_DistortionRenderer.h
+Content     :   Distortion renderer header for GL
+Created     :   November 11, 2013
+Authors     :   David Borel, Lee Cooper
+
+Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
+
+Use of this software is subject to the terms of the Oculus Inc license
+agreement provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+************************************************************************************/
+
+#ifndef OVR_CAPI_GL_DistortionRenderer_h
+#define OVR_CAPI_GL_DistortionRenderer_h
+
+#include "../CAPI_DistortionRenderer.h"
+
+#include "../../Kernel/OVR_Log.h"
+#include "CAPI_GL_Util.h"
+
+namespace OVR { namespace CAPI { namespace GL {
+
+// ***** GL::DistortionRenderer
+
+// Implementation of DistortionRenderer for GL.
+
+class DistortionRenderer : public CAPI::DistortionRenderer
+{
+public:    
+    DistortionRenderer(ovrHmd hmd,
+                       FrameTimeManager& timeManager,
+                       const HMDRenderState& renderState);
+    ~DistortionRenderer();
+
+    
+    // Creation function for the device.    
+    static CAPI::DistortionRenderer* Create(ovrHmd hmd,
+                                            FrameTimeManager& timeManager,
+                                            const HMDRenderState& renderState);
+
+
+    // ***** Public DistortionRenderer interface
+	
+    virtual bool Initialize(const ovrRenderAPIConfig* apiConfig,
+                            unsigned distortionCaps);
+
+    virtual void SubmitEye(int eyeId, ovrTexture* eyeTexture);
+
+    virtual void EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor);
+
+    void         WaitUntilGpuIdle();
+
+	// Similar to ovr_WaitTillTime but it also flushes GPU.
+	// Note, it exits when time expires, even if GPU is not in idle state yet.
+	double       FlushGpuAndWaitTillTime(double absTime);
+
+protected:
+    
+    
+    class GraphicsState : public CAPI::DistortionRenderer::GraphicsState
+    {
+    public:
+        GraphicsState();
+        virtual void Save();
+        virtual void Restore();
+        
+    protected:
+        void ApplyBool(GLenum Name, GLint Value);
+        
+    public:
+        GLint GlMajorVersion;
+        GLint GlMinorVersion;
+        bool SupportsVao;
+        
+        GLint Viewport[4];
+        GLfloat ClearColor[4];
+        GLint DepthTest;
+        GLint CullFace;
+        GLint Program;
+        GLint ActiveTexture;
+        GLint TextureBinding;
+        GLint VertexArray;
+        GLint FrameBufferBinding;
+        
+        GLint Blend;
+        GLint ColorWritemask[4];
+        GLint Dither;
+        GLint Fog;
+        GLint Lighting;
+        GLint RasterizerDiscard;
+        GLint RenderMode;
+        GLint SampleMask;
+        GLint ScissorTest;
+        GLfloat ZoomX;
+        GLfloat ZoomY;
+    };
+
+    // TBD: Should we be using oe from RState instead?
+    unsigned            DistortionCaps;
+
+	struct FOR_EACH_EYE
+	{
+        FOR_EACH_EYE() : TextureSize(0), RenderViewport(Sizei(0)) { }
+
+#if 0
+		IDirect3DVertexBuffer9  * dxVerts;
+		IDirect3DIndexBuffer9   * dxIndices;
+#endif
+		int                       numVerts;
+		int                       numIndices;
+
+		GLuint                    texture;
+
+		ovrVector2f			 	  UVScaleOffset[2];
+        Sizei                     TextureSize;
+        Recti                     RenderViewport;
+	} eachEye[2];
+
+    // GL context and utility variables.
+    RenderParams        RParams;    
+
+	// Helpers
+    void initBuffersAndShaders();
+    void initShaders();
+    void initFullscreenQuad();
+    void destroy();
+	
+    void setViewport(const Recti& vp);
+
+    void renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture);
+
+    void renderPrimitives(const ShaderFill* fill, Buffer* vertices, Buffer* indices,
+                          int offset, int count,
+						  PrimitiveType rprim, GLuint* vao, bool isDistortionMesh);
+
+	void createDrawQuad();
+    void renderLatencyQuad(unsigned char* latencyTesterDrawColor);
+    void renderLatencyPixel(unsigned char* latencyTesterPixelColor);
+	
+    Ptr<Texture>        pEyeTextures[2];
+
+	Ptr<Buffer>         DistortionMeshVBs[2];    // one per-eye
+	Ptr<Buffer>         DistortionMeshIBs[2];    // one per-eye
+	GLuint              DistortionMeshVAOs[2];   // one per-eye
+
+	Ptr<ShaderSet>      DistortionShader;
+
+    struct StandardUniformData
+    {
+        Matrix4f  Proj;
+        Matrix4f  View;
+    }                   StdUniforms;
+	
+	GLuint              LatencyVAO;
+    Ptr<Buffer>         LatencyTesterQuadVB;
+    Ptr<ShaderSet>      SimpleQuadShader;
+
+    Ptr<Texture>             CurRenderTarget;
+    Array<Ptr<Texture> >     DepthBuffers;
+    GLuint                   CurrentFbo;
+
+	GLint SavedViewport[4];
+	GLfloat SavedClearColor[4];
+	GLint SavedDepthTest;
+	GLint SavedCullFace;
+	GLint SavedProgram;
+	GLint SavedActiveTexture;
+	GLint SavedBoundTexture;
+	GLint SavedVertexArray;
+    GLint SavedBoundFrameBuffer;
+};
+
+}}} // OVR::CAPI::GL
+
+#endif // OVR_CAPI_GL_DistortionRenderer_h
\ No newline at end of file
diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h
new file mode 100644
index 0000000..03fd174
--- /dev/null
+++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h
@@ -0,0 +1,326 @@
+/************************************************************************************
+ 
+ Filename    :   CAPI_GL_Shaders.h
+ Content     :   Distortion shader header for GL
+ Created     :   November 11, 2013
+ Authors     :   David Borel, Volga Aksoy
+ 
+ Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
+ 
+ Use of this software is subject to the terms of the Oculus Inc license
+ agreement provided at the time of installation or download, or which
+ otherwise accompanies this software in either electronic or hard copy form.
+ 
+ ************************************************************************************/
+
+
+#ifndef OVR_CAPI_GL_Shaders_h
+#define OVR_CAPI_GL_Shaders_h
+
+
+#include "CAPI_GL_Util.h"
+
+namespace OVR { namespace CAPI { namespace GL {
+    
+    static const char glsl2Prefix[] =
+    "#version 110\n"
+    "#extension GL_ARB_shader_texture_lod : enable\n"
+    "#define _FRAGCOLOR_DECLARATION\n"
+    "#define _VS_IN attribute\n"
+    "#define _VS_OUT varying\n"
+    "#define _FS_IN varying\n"
+    "#define _TEXTURELOD texture2DLod\n"
+    "#define _FRAGCOLOR gl_FragColor\n";
+    
+    static const char glsl3Prefix[] =
+    "#version 150\n"
+    "#define _FRAGCOLOR_DECLARATION out vec4 FragColor;\n"
+    "#define _VS_IN in\n"
+    "#define _VS_OUT out\n"
+    "#define _FS_IN in\n"
+    "#define _TEXTURELOD textureLod\n"
+    "#define _FRAGCOLOR FragColor\n";
+    
+    static const char SimpleQuad_vs[] =
+    "uniform vec2 PositionOffset;\n"
+    "uniform vec2 Scale;\n"
+    
+    "_VS_IN vec3 Position;\n"
+    
+	"void main()\n"
+	"{\n"
+	"	gl_Position = vec4(Position.xy * Scale + PositionOffset, 0.5, 1.0);\n"
+	"}\n";
+    
+    const OVR::CAPI::GL::ShaderBase::Uniform SimpleQuad_vs_refl[] =
+    {
+        { "PositionOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
+        { "Scale",          OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
+    };
+    
+    static const char SimpleQuad_fs[] =
+    "uniform vec4 Color;\n"
+    
+    "_FRAGCOLOR_DECLARATION\n"
+    
+	"void main()\n"
+	"{\n"
+	"    _FRAGCOLOR = Color;\n"
+	"}\n";
+    
+    const OVR::CAPI::GL::ShaderBase::Uniform SimpleQuad_fs_refl[] =
+    {
+        { "Color", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 16 },
+    };
+    
+    
+    static const char Distortion_vs[] =
+    "uniform vec2 EyeToSourceUVScale;\n"
+    "uniform vec2 EyeToSourceUVOffset;\n"
+    
+    "_VS_IN vec2 Position;\n"
+    "_VS_IN vec4 Color;\n"
+    "_VS_IN vec2 TexCoord0;\n"
+    
+    "_VS_OUT vec4 oColor;\n"
+    "_VS_OUT vec2 oTexCoord0;\n"
+    
+    "void main()\n"
+    "{\n"
+    "   gl_Position.x = Position.x;\n"
+    "   gl_Position.y = Position.y;\n"
+    "   gl_Position.z = 0.5;\n"
+    "   gl_Position.w = 1.0;\n"
+    // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+    // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+    "   oTexCoord0 = TexCoord0 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
+    "   oTexCoord0.y = 1.0 - oTexCoord0.y;\n"
+    "   oColor = Color;\n"              // Used for vignette fade.
+    "}\n";
+    
+    const OVR::CAPI::GL::ShaderBase::Uniform Distortion_vs_refl[] =
+    {
+        { "EyeToSourceUVScale",  OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
+        { "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
+    };
+    
+    static const char Distortion_fs[] =
+    "uniform sampler2D Texture0;\n"
+    
+    "_FS_IN vec4 oColor;\n"
+    "_FS_IN vec2 oTexCoord0;\n"
+    
+    "_FRAGCOLOR_DECLARATION\n"
+    
+    "void main()\n"
+    "{\n"
+    "   _FRAGCOLOR = _TEXTURELOD(Texture0, oTexCoord0, 0.0);\n"
+    "   _FRAGCOLOR.a = 1.0;\n"
+    "}\n";
+    
+    
+    static const char DistortionTimewarp_vs[] =
+    "uniform vec2 EyeToSourceUVScale;\n"
+    "uniform vec2 EyeToSourceUVOffset;\n"
+    "uniform mat4 EyeRotationStart;\n"
+    "uniform mat4 EyeRotationEnd;\n"
+    
+    "_VS_IN vec2 Position;\n"
+    "_VS_IN vec4 Color;\n"
+    "_VS_IN vec2 TexCoord0;\n"
+    
+    "_FS_IN vec4 oColor;\n"
+    "_FS_IN vec2 oTexCoord0;\n"
+    
+    "void main()\n"
+    "{\n"
+    "   gl_Position.x = Position.x;\n"
+    "   gl_Position.y = Position.y;\n"
+    "   gl_Position.z = 0.0;\n"
+    "   gl_Position.w = 1.0;\n"
+    
+    // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+    // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
+    "   vec3 TanEyeAngle = vec3 ( TexCoord0.x, TexCoord0.y, 1.0 );\n"
+    
+    // Accurate time warp lerp vs. faster
+#if 1
+    // Apply the two 3x3 timewarp rotations to these vectors.
+	"   vec3 TransformedStart = (EyeRotationStart * vec4(TanEyeAngle, 0)).xyz;\n"
+	"   vec3 TransformedEnd   = (EyeRotationEnd * vec4(TanEyeAngle, 0)).xyz;\n"
+    // And blend between them.
+    "   vec3 Transformed = mix ( TransformedStart, TransformedEnd, Color.a );\n"
+#else
+    "   mat4 EyeRotation = mix ( EyeRotationStart, EyeRotationEnd, Color.a );\n"
+    "   vec3 Transformed   = EyeRotation * TanEyeAngle;\n"
+#endif
+    
+    // Project them back onto the Z=1 plane of the rendered images.
+    "   float RecipZ = 1.0 / Transformed.z;\n"
+    "   vec2 Flattened = vec2 ( Transformed.x * RecipZ, Transformed.y * RecipZ );\n"
+    
+    // These are now still in TanEyeAngle space.
+    // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+    "   vec2 SrcCoord = Flattened * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
+    "   oTexCoord0 = SrcCoord;\n"
+    "   oTexCoord0.y = 1.0-oTexCoord0.y;\n"
+    "   oColor = vec4(Color.r, Color.r, Color.r, Color.r);\n"              // Used for vignette fade.
+    "}\n";
+
+    
+    const OVR::CAPI::GL::ShaderBase::Uniform DistortionTimewarp_vs_refl[] =
+    {
+        { "EyeToSourceUVScale",  OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
+        { "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
+    };
+    
+    static const char DistortionChroma_vs[] =
+    "uniform vec2 EyeToSourceUVScale;\n"
+    "uniform vec2 EyeToSourceUVOffset;\n"
+    
+    "_VS_IN vec2 Position;\n"
+    "_VS_IN vec4 Color;\n"
+    "_VS_IN vec2 TexCoord0;\n"
+    "_VS_IN vec2 TexCoord1;\n"
+    "_VS_IN vec2 TexCoord2;\n"
+    
+    "_VS_OUT vec4 oColor;\n"
+    "_VS_OUT vec2 oTexCoord0;\n"
+    "_VS_OUT vec2 oTexCoord1;\n"
+    "_VS_OUT vec2 oTexCoord2;\n"
+    
+    "void main()\n"
+    "{\n"
+    "   gl_Position.x = Position.x;\n"
+    "   gl_Position.y = Position.y;\n"
+    "   gl_Position.z = 0.5;\n"
+    "   gl_Position.w = 1.0;\n"
+    
+    // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+    // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+    "   oTexCoord0 = TexCoord0 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
+    "   oTexCoord0.y = 1.0-oTexCoord0.y;\n"
+    "   oTexCoord1 = TexCoord1 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
+    "   oTexCoord1.y = 1.0-oTexCoord1.y;\n"
+    "   oTexCoord2 = TexCoord2 * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
+    "   oTexCoord2.y = 1.0-oTexCoord2.y;\n"
+    
+    "   oColor = Color;\n" // Used for vignette fade.
+    "}\n";
+    
+    const OVR::CAPI::GL::ShaderBase::Uniform DistortionChroma_vs_refl[] =
+    {
+        { "EyeToSourceUVScale",  OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
+        { "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
+    };
+    
+    static const char DistortionChroma_fs[] =
+    "uniform sampler2D Texture0;\n"
+    
+    "_FS_IN vec4 oColor;\n"
+    "_FS_IN vec2 oTexCoord0;\n"
+    "_FS_IN vec2 oTexCoord1;\n"
+    "_FS_IN vec2 oTexCoord2;\n"
+    
+    "_FRAGCOLOR_DECLARATION\n"
+    
+    "void main()\n"
+    "{\n"
+    "   float ResultR = _TEXTURELOD(Texture0, oTexCoord0, 0.0).r;\n"
+    "   float ResultG = _TEXTURELOD(Texture0, oTexCoord1, 0.0).g;\n"
+    "   float ResultB = _TEXTURELOD(Texture0, oTexCoord2, 0.0).b;\n"
+    
+    "   _FRAGCOLOR = vec4(ResultR * oColor.r, ResultG * oColor.g, ResultB * oColor.b, 1.0);\n"
+    "}\n";
+
+    
+    static const char DistortionTimewarpChroma_vs[] =
+    "uniform vec2 EyeToSourceUVScale;\n"
+    "uniform vec2 EyeToSourceUVOffset;\n"
+    "uniform mat4 EyeRotationStart;\n"
+    "uniform mat4 EyeRotationEnd;\n"
+    
+    "_VS_IN vec2 Position;\n"
+    "_VS_IN vec4 Color;\n"
+    "_VS_IN vec2 TexCoord0;\n"
+    "_VS_IN vec2 TexCoord1;\n"
+    "_VS_IN vec2 TexCoord2;\n"
+    
+    "_VS_OUT vec4 oColor;\n"
+    "_VS_OUT vec2 oTexCoord0;\n"
+    "_VS_OUT vec2 oTexCoord1;\n"
+    "_VS_OUT vec2 oTexCoord2;\n"
+    
+    "void main()\n"
+    "{\n"
+    "   gl_Position.x = Position.x;\n"
+    "   gl_Position.y = Position.y;\n"
+    "   gl_Position.z = 0.0;\n"
+    "   gl_Position.w = 1.0;\n"
+    
+    // Vertex inputs are in TanEyeAngle space for the R,G,B channels (i.e. after chromatic aberration and distortion).
+    // These are now "real world" vectors in direction (x,y,1) relative to the eye of the HMD.
+    "   vec3 TanEyeAngleR = vec3 ( TexCoord0.x, TexCoord0.y, 1.0 );\n"
+    "   vec3 TanEyeAngleG = vec3 ( TexCoord1.x, TexCoord1.y, 1.0 );\n"
+    "   vec3 TanEyeAngleB = vec3 ( TexCoord2.x, TexCoord2.y, 1.0 );\n"
+    
+    // Accurate time warp lerp vs. faster
+#if 1
+    // Apply the two 3x3 timewarp rotations to these vectors.
+	"   vec3 TransformedRStart = (EyeRotationStart * vec4(TanEyeAngleR, 0)).xyz;\n"
+	"   vec3 TransformedGStart = (EyeRotationStart * vec4(TanEyeAngleG, 0)).xyz;\n"
+	"   vec3 TransformedBStart = (EyeRotationStart * vec4(TanEyeAngleB, 0)).xyz;\n"
+	"   vec3 TransformedREnd   = (EyeRotationEnd * vec4(TanEyeAngleR, 0)).xyz;\n"
+	"   vec3 TransformedGEnd   = (EyeRotationEnd * vec4(TanEyeAngleG, 0)).xyz;\n"
+	"   vec3 TransformedBEnd   = (EyeRotationEnd * vec4(TanEyeAngleB, 0)).xyz;\n"
+    
+    // And blend between them.
+    "   vec3 TransformedR = mix ( TransformedRStart, TransformedREnd, Color.a );\n"
+    "   vec3 TransformedG = mix ( TransformedGStart, TransformedGEnd, Color.a );\n"
+    "   vec3 TransformedB = mix ( TransformedBStart, TransformedBEnd, Color.a );\n"
+#else
+    "   mat3 EyeRotation;\n"
+    "   EyeRotation[0] = mix ( EyeRotationStart[0], EyeRotationEnd[0], Color.a ).xyz;\n"
+    "   EyeRotation[1] = mix ( EyeRotationStart[1], EyeRotationEnd[1], Color.a ).xyz;\n"
+    "   EyeRotation[2] = mix ( EyeRotationStart[2], EyeRotationEnd[2], Color.a ).xyz;\n"
+    "   vec3 TransformedR   = EyeRotation * TanEyeAngleR;\n"
+    "   vec3 TransformedG   = EyeRotation * TanEyeAngleG;\n"
+    "   vec3 TransformedB   = EyeRotation * TanEyeAngleB;\n"
+#endif
+    
+    // Project them back onto the Z=1 plane of the rendered images.
+    "   float RecipZR = 1.0 / TransformedR.z;\n"
+    "   float RecipZG = 1.0 / TransformedG.z;\n"
+    "   float RecipZB = 1.0 / TransformedB.z;\n"
+    "   vec2 FlattenedR = vec2 ( TransformedR.x * RecipZR, TransformedR.y * RecipZR );\n"
+    "   vec2 FlattenedG = vec2 ( TransformedG.x * RecipZG, TransformedG.y * RecipZG );\n"
+    "   vec2 FlattenedB = vec2 ( TransformedB.x * RecipZB, TransformedB.y * RecipZB );\n"
+    
+    // These are now still in TanEyeAngle space.
+    // Scale them into the correct [0-1],[0-1] UV lookup space (depending on eye)
+    "   vec2 SrcCoordR = FlattenedR * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
+    "   vec2 SrcCoordG = FlattenedG * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
+    "   vec2 SrcCoordB = FlattenedB * EyeToSourceUVScale + EyeToSourceUVOffset;\n"
+    
+    "   oTexCoord0 = SrcCoordR;\n"
+    "   oTexCoord0.y = 1.0-oTexCoord0.y;\n"
+    "   oTexCoord1 = SrcCoordG;\n"
+    "   oTexCoord1.y = 1.0-oTexCoord1.y;\n"
+    "   oTexCoord2 = SrcCoordB;\n"
+    "   oTexCoord2.y = 1.0-oTexCoord2.y;\n"
+    
+    "   oColor = vec4(Color.r, Color.r, Color.r, Color.r);\n"              // Used for vignette fade.
+    "}\n";
+    
+
+    const OVR::CAPI::GL::ShaderBase::Uniform DistortionTimewarpChroma_vs_refl[] =
+    {
+        { "EyeToSourceUVScale",  OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 0, 8 },
+        { "EyeToSourceUVOffset", OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 8, 8 },
+        { "EyeRotationStart",    OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 16, 64 },
+        { "EyeRotationEnd",      OVR::CAPI::GL::ShaderBase::VARTYPE_FLOAT, 80, 64 },
+    };
+    
+}}} // OVR::CAPI::GL
+
+#endif // OVR_CAPI_GL_Shaders_h
diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp
new file mode 100644
index 0000000..910e28c
--- /dev/null
+++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp
@@ -0,0 +1,530 @@
+/************************************************************************************
+
+Filename    :   Render_GL_Device.cpp
+Content     :   RenderDevice implementation for OpenGL
+Created     :   September 10, 2012
+Authors     :   David Borel, Andrew Reisse
+
+Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "CAPI_GL_Util.h"
+#include "../../Kernel/OVR_Log.h"
+#include <string.h>
+
+namespace OVR { namespace CAPI { namespace GL {
+
+
+
+// GL Hooks for non-Mac.
+#if !defined(OVR_OS_MAC)
+
+#if defined(OVR_OS_WIN32)
+
+PFNWGLGETPROCADDRESS                     wglGetProcAddress;
+
+PFNGLENABLEPROC                          glEnable;
+PFNGLDISABLEPROC                         glDisable;
+PFNGLGETFLOATVPROC                       glGetFloatv;
+PFNGLGETINTEGERVPROC                     glGetIntegerv;
+PFNGLGETSTRINGPROC                       glGetString;
+PFNGLCOLORMASKPROC                       glColorMask;
+PFNGLCLEARPROC                           glClear;
+PFNGLCLEARCOLORPROC                      glClearColor;
+PFNGLCLEARDEPTHPROC                      glClearDepth;
+PFNGLVIEWPORTPROC                        glViewport;
+PFNGLDRAWELEMENTSPROC                    glDrawElements;
+PFNGLTEXPARAMETERIPROC                   glTexParameteri;
+PFNGLFLUSHPROC                           glFlush;
+PFNGLFINISHPROC                          glFinish;
+PFNGLDRAWARRAYSPROC                      glDrawArrays;
+PFNGLGENTEXTURESPROC                     glGenTextures;
+PFNGLDELETETEXTURESPROC                  glDeleteTextures;
+PFNGLBINDTEXTUREPROC                     glBindTexture;
+
+PFNWGLGETSWAPINTERVALEXTPROC             wglGetSwapIntervalEXT;
+PFNWGLSWAPINTERVALEXTPROC                wglSwapIntervalEXT;
+
+#elif defined(OVR_OS_LINUX)
+
+PFNGLXSWAPINTERVALEXTPROC                glXSwapIntervalEXT;
+
+#endif
+
+PFNGLDELETESHADERPROC                    glDeleteShader;
+PFNGLBINDFRAMEBUFFERPROC                 glBindFramebuffer;
+PFNGLACTIVETEXTUREPROC                   glActiveTexture;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC        glDisableVertexAttribArray;
+PFNGLVERTEXATTRIBPOINTERPROC             glVertexAttribPointer;
+PFNGLENABLEVERTEXATTRIBARRAYPROC         glEnableVertexAttribArray;
+PFNGLBINDBUFFERPROC                      glBindBuffer;
+PFNGLUNIFORMMATRIX3FVPROC                glUniformMatrix3fv;
+PFNGLUNIFORMMATRIX4FVPROC                glUniformMatrix4fv;
+PFNGLDELETEBUFFERSPROC                   glDeleteBuffers;
+PFNGLBUFFERDATAPROC                      glBufferData;
+PFNGLGENBUFFERSPROC                      glGenBuffers;
+PFNGLMAPBUFFERPROC                       glMapBuffer;
+PFNGLUNMAPBUFFERPROC                     glUnmapBuffer;
+PFNGLGETSHADERINFOLOGPROC                glGetShaderInfoLog;
+PFNGLGETSHADERIVPROC                     glGetShaderiv;
+PFNGLCOMPILESHADERPROC                   glCompileShader;
+PFNGLSHADERSOURCEPROC                    glShaderSource;
+PFNGLCREATESHADERPROC                    glCreateShader;
+PFNGLCREATEPROGRAMPROC                   glCreateProgram;
+PFNGLATTACHSHADERPROC                    glAttachShader;
+PFNGLDETACHSHADERPROC                    glDetachShader;
+PFNGLDELETEPROGRAMPROC                   glDeleteProgram;
+PFNGLUNIFORM1IPROC                       glUniform1i;
+PFNGLGETUNIFORMLOCATIONPROC              glGetUniformLocation;
+PFNGLGETACTIVEUNIFORMPROC                glGetActiveUniform;
+PFNGLUSEPROGRAMPROC                      glUseProgram;
+PFNGLGETPROGRAMINFOLOGPROC               glGetProgramInfoLog;
+PFNGLGETPROGRAMIVPROC                    glGetProgramiv;
+PFNGLLINKPROGRAMPROC                     glLinkProgram;
+PFNGLBINDATTRIBLOCATIONPROC              glBindAttribLocation;
+PFNGLGETATTRIBLOCATIONPROC               glGetAttribLocation;
+PFNGLUNIFORM4FVPROC                      glUniform4fv;
+PFNGLUNIFORM3FVPROC                      glUniform3fv;
+PFNGLUNIFORM2FVPROC                      glUniform2fv;
+PFNGLUNIFORM1FVPROC                      glUniform1fv;
+PFNGLGENVERTEXARRAYSPROC                 glGenVertexArrays;
+PFNGLDELETEVERTEXARRAYSPROC              glDeleteVertexArrays;
+PFNGLBINDVERTEXARRAYPROC                 glBindVertexArray;
+
+
+#if defined(OVR_OS_WIN32)
+
+void* GetFunction(const char* functionName)
+{
+    return wglGetProcAddress(functionName);
+}
+
+#else
+
+void (*GetFunction(const char *functionName))( void )
+{
+    return glXGetProcAddress((GLubyte*)functionName);
+}
+
+#endif
+
+void InitGLExtensions()
+{
+    if (glGenVertexArrays)
+        return;
+
+#if defined(OVR_OS_WIN32)
+	HINSTANCE hInst = LoadLibrary(L"Opengl32.dll");
+	if (!hInst)
+		return;
+
+	glGetFloatv =                       (PFNGLGETFLOATVPROC)                       GetProcAddress(hInst, "glGetFloatv");
+	glGetIntegerv =                     (PFNGLGETINTEGERVPROC)                     GetProcAddress(hInst, "glGetIntegerv");
+	glGetString =                       (PFNGLGETSTRINGPROC)                       GetProcAddress(hInst, "glGetString");
+	glEnable =                          (PFNGLENABLEPROC)                          GetProcAddress(hInst, "glEnable");
+	glDisable =                         (PFNGLDISABLEPROC)                         GetProcAddress(hInst, "glDisable");
+	glColorMask =                       (PFNGLCOLORMASKPROC)                       GetProcAddress(hInst, "glColorMask");
+	glClear =                           (PFNGLCLEARPROC)                           GetProcAddress(hInst, "glClear" );
+	glClearColor =                      (PFNGLCLEARCOLORPROC)                      GetProcAddress(hInst, "glClearColor");
+	glClearDepth =                      (PFNGLCLEARDEPTHPROC)                      GetProcAddress(hInst, "glClearDepth");
+	glViewport =                        (PFNGLVIEWPORTPROC)                        GetProcAddress(hInst, "glViewport");
+	glFlush =                           (PFNGLFLUSHPROC)                           GetProcAddress(hInst, "glFlush");
+	glFinish =                          (PFNGLFINISHPROC)                          GetProcAddress(hInst, "glFinish");
+    glDrawArrays =                      (PFNGLDRAWARRAYSPROC)                      GetProcAddress(hInst, "glDrawArrays");
+	glDrawElements =                    (PFNGLDRAWELEMENTSPROC)                    GetProcAddress(hInst, "glDrawElements");
+    glGenTextures =                     (PFNGLGENTEXTURESPROC)                     GetProcAddress(hInst,"glGenTextures");
+    glDeleteTextures =                  (PFNGLDELETETEXTURESPROC)                  GetProcAddress(hInst,"glDeleteTextures");
+    glBindTexture =                     (PFNGLBINDTEXTUREPROC)                     GetProcAddress(hInst,"glBindTexture");
+	glTexParameteri =                   (PFNGLTEXPARAMETERIPROC)                   GetProcAddress(hInst, "glTexParameteri");
+
+    wglGetProcAddress =                 (PFNWGLGETPROCADDRESS)                     GetProcAddress(hInst, "wglGetProcAddress");
+
+    wglGetSwapIntervalEXT =             (PFNWGLGETSWAPINTERVALEXTPROC)             GetFunction("wglGetSwapIntervalEXT");
+    wglSwapIntervalEXT =                (PFNWGLSWAPINTERVALEXTPROC)                GetFunction("wglSwapIntervalEXT");
+#elif defined(OVR_OS_LINUX)
+    glXSwapIntervalEXT =                (PFNGLXSWAPINTERVALEXTPROC)                GetFunction("glXSwapIntervalEXT");
+#endif
+
+    glBindFramebuffer =                 (PFNGLBINDFRAMEBUFFERPROC)                 GetFunction("glBindFramebufferEXT");
+    glGenVertexArrays =                 (PFNGLGENVERTEXARRAYSPROC)                 GetFunction("glGenVertexArrays");
+    glDeleteVertexArrays =              (PFNGLDELETEVERTEXARRAYSPROC)              GetFunction("glDeleteVertexArrays");
+    glBindVertexArray =                 (PFNGLBINDVERTEXARRAYPROC)                 GetFunction("glBindVertexArray");
+    glGenBuffers =                      (PFNGLGENBUFFERSPROC)                      GetFunction("glGenBuffers");
+    glDeleteBuffers =                   (PFNGLDELETEBUFFERSPROC)                   GetFunction("glDeleteBuffers");
+    glBindBuffer =                      (PFNGLBINDBUFFERPROC)                      GetFunction("glBindBuffer");	
+    glBufferData =                      (PFNGLBUFFERDATAPROC)                      GetFunction("glBufferData");
+    glMapBuffer =                       (PFNGLMAPBUFFERPROC)                       GetFunction("glMapBuffer");
+    glUnmapBuffer =                     (PFNGLUNMAPBUFFERPROC)                     GetFunction("glUnmapBuffer");
+    glDisableVertexAttribArray =        (PFNGLDISABLEVERTEXATTRIBARRAYPROC)        GetFunction("glDisableVertexAttribArray");
+    glVertexAttribPointer =             (PFNGLVERTEXATTRIBPOINTERPROC)             GetFunction("glVertexAttribPointer");
+    glEnableVertexAttribArray =         (PFNGLENABLEVERTEXATTRIBARRAYPROC)         GetFunction("glEnableVertexAttribArray");
+    glActiveTexture =                   (PFNGLACTIVETEXTUREPROC)                   GetFunction("glActiveTexture");
+    glUniformMatrix3fv =                (PFNGLUNIFORMMATRIX3FVPROC)                GetFunction("glUniformMatrix3fv");
+    glUniformMatrix4fv =                (PFNGLUNIFORMMATRIX4FVPROC)                GetFunction("glUniformMatrix4fv");
+    glUniform1i =                       (PFNGLUNIFORM1IPROC)                       GetFunction("glUniform1i");
+    glUniform1fv =                      (PFNGLUNIFORM1FVPROC)                      GetFunction("glUniform1fv");
+    glUniform2fv =                      (PFNGLUNIFORM2FVPROC)                      GetFunction("glUniform2fv");
+    glUniform3fv =                      (PFNGLUNIFORM3FVPROC)                      GetFunction("glUniform3fv");
+    glUniform2fv =                      (PFNGLUNIFORM2FVPROC)                      GetFunction("glUniform2fv");
+    glUniform4fv =                      (PFNGLUNIFORM4FVPROC)                      GetFunction("glUniform4fv");
+    glGetUniformLocation =              (PFNGLGETUNIFORMLOCATIONPROC)              GetFunction("glGetUniformLocation");
+    glGetActiveUniform =                (PFNGLGETACTIVEUNIFORMPROC)                GetFunction("glGetActiveUniform");
+    glGetShaderInfoLog =                (PFNGLGETSHADERINFOLOGPROC)                GetFunction("glGetShaderInfoLog");
+    glGetShaderiv =                     (PFNGLGETSHADERIVPROC)                     GetFunction("glGetShaderiv");
+    glCompileShader =                   (PFNGLCOMPILESHADERPROC)                   GetFunction("glCompileShader");
+    glShaderSource =                    (PFNGLSHADERSOURCEPROC)                    GetFunction("glShaderSource");
+    glCreateShader =                    (PFNGLCREATESHADERPROC)                    GetFunction("glCreateShader");
+    glDeleteShader =                    (PFNGLDELETESHADERPROC)                    GetFunction("glDeleteShader");
+    glCreateProgram =                   (PFNGLCREATEPROGRAMPROC)                   GetFunction("glCreateProgram");
+    glDeleteProgram =                   (PFNGLDELETEPROGRAMPROC)                   GetFunction("glDeleteProgram");
+    glUseProgram =                      (PFNGLUSEPROGRAMPROC)                      GetFunction("glUseProgram");
+    glGetProgramInfoLog =               (PFNGLGETPROGRAMINFOLOGPROC)               GetFunction("glGetProgramInfoLog");
+    glGetProgramiv =                    (PFNGLGETPROGRAMIVPROC)                    GetFunction("glGetProgramiv");
+    glLinkProgram =                     (PFNGLLINKPROGRAMPROC)                     GetFunction("glLinkProgram");
+    glAttachShader =                    (PFNGLATTACHSHADERPROC)                    GetFunction("glAttachShader");
+    glDetachShader =                    (PFNGLDETACHSHADERPROC)                    GetFunction("glDetachShader");
+    glBindAttribLocation =              (PFNGLBINDATTRIBLOCATIONPROC)              GetFunction("glBindAttribLocation");
+    glGetAttribLocation =               (PFNGLGETATTRIBLOCATIONPROC)               GetFunction("glGetAttribLocation");
+}
+    
+#endif
+    
+Buffer::Buffer(RenderParams* rp) : pParams(rp), Size(0), Use(0), GLBuffer(0)
+{
+}
+
+Buffer::~Buffer()
+{
+    if (GLBuffer)
+        glDeleteBuffers(1, &GLBuffer);
+}
+
+bool Buffer::Data(int use, const void* buffer, size_t size)
+{
+	Size = size;
+
+    switch (use & Buffer_TypeMask)
+    {
+    case Buffer_Index:     Use = GL_ELEMENT_ARRAY_BUFFER; break;
+    default:               Use = GL_ARRAY_BUFFER; break;
+    }
+
+    if (!GLBuffer)
+        glGenBuffers(1, &GLBuffer);
+
+    int mode = GL_DYNAMIC_DRAW;
+    if (use & Buffer_ReadOnly)
+        mode = GL_STATIC_DRAW;
+
+    glBindBuffer(Use, GLBuffer);
+    glBufferData(Use, size, buffer, mode);
+    return 1;
+}
+
+void* Buffer::Map(size_t, size_t, int)
+{
+    int mode = GL_WRITE_ONLY;
+    //if (flags & Map_Unsynchronized)
+    //    mode |= GL_MAP_UNSYNCHRONIZED;
+    
+    glBindBuffer(Use, GLBuffer);
+    void* v = glMapBuffer(Use, mode);
+    return v;
+}
+
+bool Buffer::Unmap(void*)
+{
+    glBindBuffer(Use, GLBuffer);
+    int r = glUnmapBuffer(Use);
+    return r != 0;
+}
+
+ShaderSet::ShaderSet()
+{
+    Prog = glCreateProgram();
+}
+ShaderSet::~ShaderSet()
+{
+    glDeleteProgram(Prog);
+}
+
+GLint ShaderSet::GetGLShader(Shader* s)
+{
+	switch (s->Stage)
+	{
+	case Shader_Vertex: {
+		ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>* gls = (ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER>*)s;
+		return gls->GLShader;
+	} break;
+	case Shader_Fragment: {
+		ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>* gls = (ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER>*)s;
+		return gls->GLShader;
+	} break;
+    default: break;
+	}
+
+	return -1;
+}
+
+void ShaderSet::SetShader(Shader *s)
+{
+    Shaders[s->Stage] = s;
+	GLint GLShader = GetGLShader(s);
+    glAttachShader(Prog, GLShader);
+    if (Shaders[Shader_Vertex] && Shaders[Shader_Fragment])
+        Link();
+}
+
+void ShaderSet::UnsetShader(int stage)
+{
+    if (Shaders[stage] == NULL)
+		return;
+
+	GLint GLShader = GetGLShader(Shaders[stage]);
+    glDetachShader(Prog, GLShader);
+
+    Shaders[stage] = NULL;
+}
+
+bool ShaderSet::SetUniform(const char* name, int n, const float* v)
+{
+    for (unsigned int i = 0; i < UniformInfo.GetSize(); i++)
+        if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
+        {
+            OVR_ASSERT(UniformInfo[i].Location >= 0);
+            glUseProgram(Prog);
+            switch (UniformInfo[i].Type)
+            {
+            case 1:   glUniform1fv(UniformInfo[i].Location, n, v); break;
+            case 2:   glUniform2fv(UniformInfo[i].Location, n/2, v); break;
+            case 3:   glUniform3fv(UniformInfo[i].Location, n/3, v); break;
+            case 4:   glUniform4fv(UniformInfo[i].Location, n/4, v); break;
+            case 12:  glUniformMatrix3fv(UniformInfo[i].Location, 1, 1, v); break;
+            case 16:  glUniformMatrix4fv(UniformInfo[i].Location, 1, 1, v); break;
+            default: OVR_ASSERT(0);
+            }
+            return 1;
+        }
+
+    OVR_DEBUG_LOG(("Warning: uniform %s not present in selected shader", name));
+    return 0;
+}
+
+bool ShaderSet::Link()
+{
+    glLinkProgram(Prog);
+    GLint r;
+    glGetProgramiv(Prog, GL_LINK_STATUS, &r);
+    if (!r)
+    {
+        GLchar msg[1024];
+        glGetProgramInfoLog(Prog, sizeof(msg), 0, msg);
+        OVR_DEBUG_LOG(("Linking shaders failed: %s\n", msg));
+        if (!r)
+            return 0;
+    }
+    glUseProgram(Prog);
+
+    UniformInfo.Clear();
+    LightingVer = 0;
+    UsesLighting = 0;
+
+	GLint uniformCount = 0;
+	glGetProgramiv(Prog, GL_ACTIVE_UNIFORMS, &uniformCount);
+	OVR_ASSERT(uniformCount >= 0);
+
+    for(GLuint i = 0; i < (GLuint)uniformCount; i++)
+    {
+        GLsizei namelen;
+        GLint size = 0;
+        GLenum type;
+        GLchar name[32];
+        glGetActiveUniform(Prog, i, sizeof(name), &namelen, &size, &type, name);
+
+        if (size)
+        {
+            int l = glGetUniformLocation(Prog, name);
+            char *np = name;
+            while (*np)
+            {
+                if (*np == '[')
+                    *np = 0;
+                np++;
+            }
+            Uniform u;
+            u.Name = name;
+            u.Location = l;
+            u.Size = size;
+            switch (type)
+            {
+            case GL_FLOAT:      u.Type = 1; break;
+            case GL_FLOAT_VEC2: u.Type = 2; break;
+            case GL_FLOAT_VEC3: u.Type = 3; break;
+            case GL_FLOAT_VEC4: u.Type = 4; break;
+            case GL_FLOAT_MAT3: u.Type = 12; break;
+            case GL_FLOAT_MAT4: u.Type = 16; break;
+            default:
+                continue;
+            }
+            UniformInfo.PushBack(u);
+            if (!strcmp(name, "LightCount"))
+                UsesLighting = 1;
+        }
+        else
+            break;
+    }
+
+    ProjLoc = glGetUniformLocation(Prog, "Proj");
+    ViewLoc = glGetUniformLocation(Prog, "View");
+    for (int i = 0; i < 8; i++)
+    {
+        char texv[32];
+        OVR_sprintf(texv, 10, "Texture%d", i);
+        TexLoc[i] = glGetUniformLocation(Prog, texv);
+        if (TexLoc[i] < 0)
+            break;
+
+        glUniform1i(TexLoc[i], i);
+    }
+    if (UsesLighting)
+        OVR_ASSERT(ProjLoc >= 0 && ViewLoc >= 0);
+    return 1;
+}
+
+bool ShaderBase::SetUniform(const char* name, int n, const float* v)
+{
+    for(unsigned i = 0; i < UniformReflSize; i++)
+    {
+        if (!strcmp(UniformRefl[i].Name, name))
+        {
+            memcpy(UniformData + UniformRefl[i].Offset, v, n * sizeof(float));
+            return 1;
+        }
+    }
+    return 0;
+}
+
+bool ShaderBase::SetUniformBool(const char* name, int n, const bool* v) 
+{
+    OVR_UNUSED(n);
+    for(unsigned i = 0; i < UniformReflSize; i++)
+    {
+        if (!strcmp(UniformRefl[i].Name, name))
+        {
+            memcpy(UniformData + UniformRefl[i].Offset, v, UniformRefl[i].Size);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+void ShaderBase::InitUniforms(const Uniform* refl, size_t reflSize)
+{
+    if(!refl)
+    {
+        UniformRefl = NULL;
+        UniformReflSize = 0;
+
+        UniformsSize = 0;
+        if (UniformData)
+        {
+            OVR_FREE(UniformData);
+            UniformData = 0;
+        }
+        return; // no reflection data
+    }
+
+    UniformRefl = refl;
+    UniformReflSize = reflSize;
+    
+    UniformsSize = UniformRefl[UniformReflSize-1].Offset + UniformRefl[UniformReflSize-1].Size;
+    UniformData = (unsigned char*)OVR_ALLOC(UniformsSize);
+}
+
+Texture::Texture(RenderParams* rp, int w, int h) : IsUserAllocated(true), pParams(rp), TexId(0), Width(w), Height(h)
+{
+	if (w && h)
+		glGenTextures(1, &TexId);
+}
+
+Texture::~Texture()
+{
+    if (TexId && !IsUserAllocated)
+        glDeleteTextures(1, &TexId);
+}
+
+void Texture::Set(int slot, ShaderStage) const
+{
+	glActiveTexture(GL_TEXTURE0 + slot);
+	glBindTexture(GL_TEXTURE_2D, TexId);
+}
+
+void Texture::SetSampleMode(int sm)
+{
+    glBindTexture(GL_TEXTURE_2D, TexId);
+    switch (sm & Sample_FilterMask)
+    {
+    case Sample_Linear:
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
+        break;
+
+    case Sample_Anisotropic:
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);
+        break;
+
+    case Sample_Nearest:
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
+        break;
+    }
+
+    switch (sm & Sample_AddressMask)
+    {
+    case Sample_Repeat:
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+        break;
+
+    case Sample_Clamp:
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+        break;
+
+    case Sample_ClampBorder:
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
+        break;
+    }
+}
+
+void Texture::UpdatePlaceholderTexture(GLuint texId, const Sizei& textureSize)
+{
+	if (!IsUserAllocated && TexId && texId != TexId)
+		glDeleteTextures(1, &TexId);
+
+    TexId = texId;
+	Width = textureSize.w;
+	Height = textureSize.h;
+
+	IsUserAllocated = true;
+}
+
+}}}
diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h
new file mode 100644
index 0000000..a410f17
--- /dev/null
+++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h
@@ -0,0 +1,537 @@
+/************************************************************************************
+
+Filename    :   CAPI_GL_Util.h
+Content     :   Utility header for OpenGL
+Created     :   March 27, 2014
+Authors     :   Andrew Reisse, David Borel
+
+Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef INC_OVR_CAPI_GL_Util_h
+#define INC_OVR_CAPI_GL_Util_h
+
+#include "../../OVR_CAPI.h"  
+#include "../../Kernel/OVR_Array.h"
+#include "../../Kernel/OVR_Math.h"
+#include "../../Kernel/OVR_RefCount.h"
+#include "../../Kernel/OVR_String.h"
+#include "../../Kernel/OVR_Types.h"
+#include "../../Kernel/OVR_Log.h"
+
+#if defined(OVR_OS_WIN32)
+#include <Windows.h>
+#endif
+
+#if defined(OVR_OS_MAC)
+#include <OpenGL/gl3.h>
+#include <OpenGL/gl3ext.h>
+#else
+#ifndef GL_GLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+#endif
+#include <GL/gl.h>
+#include <GL/glext.h>
+#if defined(OVR_OS_WIN32)
+#include <GL/wglext.h>
+#elif defined(OVR_OS_LINUX)
+#include <GL/glx.h>
+#endif
+#endif
+
+namespace OVR { namespace CAPI { namespace GL {
+
+// GL extension Hooks for Non-Mac.
+#if !defined(OVR_OS_MAC)
+
+// Let Windows apps build without linking GL.
+#if defined(OVR_OS_WIN32)
+
+typedef void (__stdcall *PFNGLENABLEPROC) (GLenum);
+typedef void (__stdcall *PFNGLDISABLEPROC) (GLenum);
+typedef void (__stdcall *PFNGLGETFLOATVPROC) (GLenum, GLfloat*);
+typedef const GLubyte * (__stdcall *PFNGLGETSTRINGPROC) (GLenum);
+typedef void (__stdcall *PFNGLGETINTEGERVPROC) (GLenum, GLint*);
+typedef PROC (__stdcall *PFNWGLGETPROCADDRESS) (LPCSTR);
+typedef void (__stdcall *PFNGLFLUSHPROC) ();
+typedef void (__stdcall *PFNGLFINISHPROC) ();
+typedef void (__stdcall *PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (__stdcall *PFNGLCLEARPROC) (GLbitfield);
+typedef void (__stdcall *PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (__stdcall *PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (__stdcall *PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (__stdcall *PFNGLDELETETEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (__stdcall *PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (__stdcall *PFNGLCLEARCOLORPROC) (GLfloat r, GLfloat g, GLfloat b, GLfloat a);
+typedef void (__stdcall *PFNGLCLEARDEPTHPROC) (GLclampd depth);
+typedef void (__stdcall *PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (__stdcall *PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+
+extern PFNWGLGETPROCADDRESS                     wglGetProcAddress;
+extern PFNWGLGETSWAPINTERVALEXTPROC             wglGetSwapIntervalEXT;
+extern PFNWGLSWAPINTERVALEXTPROC                wglSwapIntervalEXT;
+
+extern PFNGLENABLEPROC                          glEnable;
+extern PFNGLDISABLEPROC                         glDisable;
+extern PFNGLCOLORMASKPROC                       glColorMask;
+extern PFNGLGETFLOATVPROC                       glGetFloatv;
+extern PFNGLGETSTRINGPROC                       glGetString;
+extern PFNGLGETINTEGERVPROC                     glGetIntegerv;
+extern PFNGLCLEARPROC                           glClear;
+extern PFNGLCLEARCOLORPROC                      glClearColor;
+extern PFNGLCLEARDEPTHPROC                      glClearDepth;
+extern PFNGLVIEWPORTPROC                        glViewport;
+extern PFNGLDRAWARRAYSPROC                      glDrawArrays;
+extern PFNGLDRAWELEMENTSPROC                    glDrawElements;
+extern PFNGLGENTEXTURESPROC                     glGenTextures;
+extern PFNGLDELETETEXTURESPROC                  glDeleteTextures;
+extern PFNGLBINDTEXTUREPROC                     glBindTexture;
+extern PFNGLTEXPARAMETERIPROC                   glTexParameteri;
+extern PFNGLFLUSHPROC                           glFlush;
+extern PFNGLFINISHPROC                          glFinish;
+
+#elif defined(OVR_OS_LINUX)
+
+extern PFNGLXSWAPINTERVALEXTPROC                glXSwapIntervalEXT;
+
+#endif // defined(OVR_OS_WIN32)
+
+extern PFNGLDELETESHADERPROC                    glDeleteShader;
+extern PFNGLBINDFRAMEBUFFERPROC                 glBindFramebuffer;
+extern PFNGLACTIVETEXTUREPROC                   glActiveTexture;
+extern PFNGLDISABLEVERTEXATTRIBARRAYPROC        glDisableVertexAttribArray;
+extern PFNGLVERTEXATTRIBPOINTERPROC             glVertexAttribPointer;
+extern PFNGLENABLEVERTEXATTRIBARRAYPROC         glEnableVertexAttribArray;
+extern PFNGLBINDBUFFERPROC                      glBindBuffer;
+extern PFNGLUNIFORMMATRIX4FVPROC                glUniformMatrix4fv;
+extern PFNGLDELETEBUFFERSPROC                   glDeleteBuffers;
+extern PFNGLBUFFERDATAPROC                      glBufferData;
+extern PFNGLGENBUFFERSPROC                      glGenBuffers;
+extern PFNGLMAPBUFFERPROC                       glMapBuffer;
+extern PFNGLUNMAPBUFFERPROC                     glUnmapBuffer;
+extern PFNGLGETSHADERINFOLOGPROC                glGetShaderInfoLog;
+extern PFNGLGETSHADERIVPROC                     glGetShaderiv;
+extern PFNGLCOMPILESHADERPROC                   glCompileShader;
+extern PFNGLSHADERSOURCEPROC                    glShaderSource;
+extern PFNGLCREATESHADERPROC                    glCreateShader;
+extern PFNGLCREATEPROGRAMPROC                   glCreateProgram;
+extern PFNGLATTACHSHADERPROC                    glAttachShader;
+extern PFNGLDETACHSHADERPROC                    glDetachShader;
+extern PFNGLDELETEPROGRAMPROC                   glDeleteProgram;
+extern PFNGLUNIFORM1IPROC                       glUniform1i;
+extern PFNGLGETUNIFORMLOCATIONPROC              glGetUniformLocation;
+extern PFNGLGETACTIVEUNIFORMPROC                glGetActiveUniform;
+extern PFNGLUSEPROGRAMPROC                      glUseProgram;
+extern PFNGLGETPROGRAMINFOLOGPROC               glGetProgramInfoLog;
+extern PFNGLGETPROGRAMIVPROC                    glGetProgramiv;
+extern PFNGLLINKPROGRAMPROC                     glLinkProgram;
+extern PFNGLBINDATTRIBLOCATIONPROC              glBindAttribLocation;
+extern PFNGLGETATTRIBLOCATIONPROC               glGetAttribLocation;
+extern PFNGLUNIFORM4FVPROC                      glUniform4fv;
+extern PFNGLUNIFORM3FVPROC                      glUniform3fv;
+extern PFNGLUNIFORM2FVPROC                      glUniform2fv;
+extern PFNGLUNIFORM1FVPROC                      glUniform1fv;
+extern PFNGLGENVERTEXARRAYSPROC                 glGenVertexArrays;
+extern PFNGLDELETEVERTEXARRAYSPROC              glDeleteVertexArrays;
+extern PFNGLBINDVERTEXARRAYPROC                 glBindVertexArray;
+
+extern void InitGLExtensions();
+
+#endif // !defined(OVR_OS_MAC)
+
+
+// Rendering primitive type used to render Model.
+enum PrimitiveType
+{
+    Prim_Triangles,
+    Prim_Lines,
+    Prim_TriangleStrip,
+    Prim_Unknown,
+    Prim_Count
+};
+
+// Types of shaders that can be stored together in a ShaderSet.
+enum ShaderStage
+{
+    Shader_Vertex   = 0,
+    Shader_Fragment = 2,
+    Shader_Pixel    = 2,
+    Shader_Count    = 3,
+};
+
+enum MapFlags
+{
+    Map_Discard        = 1,
+    Map_Read           = 2, // do not use
+    Map_Unsynchronized = 4, // like D3D11_MAP_NO_OVERWRITE
+};
+
+
+// Buffer types used for uploading geometry & constants.
+enum BufferUsage
+{
+    Buffer_Unknown  = 0,
+    Buffer_Vertex   = 1,
+    Buffer_Index    = 2,
+    Buffer_Uniform  = 4,
+    Buffer_TypeMask = 0xff,
+    Buffer_ReadOnly = 0x100, // Buffer must be created with Data().
+};
+
+enum TextureFormat
+{
+    Texture_RGBA            = 0x0100,
+    Texture_Depth           = 0x8000,
+    Texture_TypeMask        = 0xff00,
+    Texture_SamplesMask     = 0x00ff,
+    Texture_RenderTarget    = 0x10000,
+    Texture_GenMipmaps      = 0x20000,
+};
+
+// Texture sampling modes.
+enum SampleMode
+{
+    Sample_Linear       = 0,
+    Sample_Nearest      = 1,
+    Sample_Anisotropic  = 2,
+    Sample_FilterMask   = 3,
+
+    Sample_Repeat       = 0,
+    Sample_Clamp        = 4,
+    Sample_ClampBorder  = 8, // If unsupported Clamp is used instead.
+    Sample_AddressMask  =12,
+
+    Sample_Count        =13,
+};
+
+
+// Rendering parameters/pointers describing GL rendering setup.
+struct RenderParams
+{
+#if defined(OVR_OS_WIN32)
+    HWND   Window;
+#elif defined(OVR_OS_LINUX)
+    Display* Disp;
+    Window   Win;
+#endif
+
+    ovrSizei  RTSize;
+    int    Multisample;
+};
+
+
+class Buffer : public RefCountBase<Buffer>
+{
+public:
+    RenderParams* pParams;
+    size_t        Size;
+    GLenum        Use;
+    GLuint        GLBuffer;
+
+public:
+    Buffer(RenderParams* r);
+    ~Buffer();
+
+    GLuint         GetBuffer() { return GLBuffer; }
+
+    virtual size_t GetSize() { return Size; }
+    virtual void*  Map(size_t start, size_t size, int flags = 0);
+    virtual bool   Unmap(void *m);
+    virtual bool   Data(int use, const void* buffer, size_t size);
+};
+
+class Texture : public RefCountBase<Texture>
+{
+	bool IsUserAllocated;
+
+public:
+    RenderParams* pParams;
+    GLuint        TexId;
+    int           Width, Height;
+
+    Texture(RenderParams* rp, int w, int h);
+    ~Texture();
+
+    virtual int GetWidth() const { return Width; }
+    virtual int GetHeight() const { return Height; }
+
+    virtual void SetSampleMode(int sm);
+
+    // Updates texture to point to specified resources
+    //  - used for slave rendering.
+    void UpdatePlaceholderTexture(GLuint texId,
+                                  const Sizei& textureSize);
+
+    virtual void Set(int slot, ShaderStage stage = Shader_Fragment) const;
+};
+
+// Base class for vertex and pixel shaders. Stored in ShaderSet.
+class Shader : public RefCountBase<Shader>
+{
+    friend class ShaderSet;
+
+protected:
+    ShaderStage Stage;
+
+public:
+    Shader(ShaderStage s) : Stage(s) {}
+    virtual ~Shader() {}
+
+    ShaderStage GetStage() const { return Stage; }
+
+    virtual void Set(PrimitiveType) const { }
+    virtual void SetUniformBuffer(class Buffer* buffers, int i = 0) { OVR_UNUSED2(buffers, i); }
+
+protected:
+    virtual bool SetUniform(const char* name, int n, const float* v) { OVR_UNUSED3(name, n, v); return false; }
+    virtual bool SetUniformBool(const char* name, int n, const bool* v) { OVR_UNUSED3(name, n, v); return false; }
+};
+
+
+
+// A group of shaders, one per stage.
+// A ShaderSet is applied for rendering with a given fill.
+class ShaderSet : public RefCountBase<ShaderSet>
+{
+protected:
+    Ptr<Shader> Shaders[Shader_Count];
+
+    struct Uniform
+    {
+        String Name;
+        int    Location, Size;
+        int    Type; // currently number of floats in vector
+    };
+    Array<Uniform> UniformInfo;
+	
+public:
+	GLuint    Prog;
+    GLint     ProjLoc, ViewLoc;
+    GLint     TexLoc[8];
+    bool      UsesLighting;
+    int       LightingVer;
+
+    ShaderSet();
+    ~ShaderSet();
+
+    virtual void SetShader(Shader *s);
+    virtual void UnsetShader(int stage);
+    Shader* GetShader(int stage) { return Shaders[stage]; }
+
+    virtual void Set(PrimitiveType prim) const
+    {
+		glUseProgram(Prog);
+
+        for (int i = 0; i < Shader_Count; i++)
+            if (Shaders[i])
+                Shaders[i]->Set(prim);
+    }
+
+    // Set a uniform (other than the standard matrices). It is undefined whether the
+    // uniforms from one shader occupy the same space as those in other shaders
+    // (unless a buffer is used, then each buffer is independent).     
+    virtual bool SetUniform(const char* name, int n, const float* v);
+    bool SetUniform1f(const char* name, float x)
+    {
+        const float v[] = {x};
+        return SetUniform(name, 1, v);
+    }
+    bool SetUniform2f(const char* name, float x, float y)
+    {
+        const float v[] = {x,y};
+        return SetUniform(name, 2, v);
+    }
+    bool SetUniform3f(const char* name, float x, float y, float z)
+    {
+        const float v[] = {x,y,z};
+        return SetUniform(name, 3, v);
+    }
+    bool SetUniform4f(const char* name, float x, float y, float z, float w = 1)
+    {
+        const float v[] = {x,y,z,w};
+        return SetUniform(name, 4, v);
+    }
+
+    bool SetUniformv(const char* name, const Vector3f& v)
+    {
+        const float a[] = {v.x,v.y,v.z,1};
+        return SetUniform(name, 4, a);
+    }
+ 
+    virtual bool SetUniform4x4f(const char* name, const Matrix4f& m)
+    {
+        Matrix4f mt = m.Transposed();
+        return SetUniform(name, 16, &mt.M[0][0]);
+    }
+
+protected:
+	GLint GetGLShader(Shader* s);
+    bool Link();
+};
+
+
+// Fill combines a ShaderSet (vertex, pixel) with textures, if any.
+// Every model has a fill.
+class ShaderFill : public RefCountBase<ShaderFill>
+{
+    Ptr<ShaderSet>     Shaders;
+    Ptr<class Texture> Textures[8];
+    void*              InputLayout; // HACK this should be abstracted
+
+public:
+    ShaderFill(ShaderSet* sh) : Shaders(sh) { InputLayout = NULL; }
+    ShaderFill(ShaderSet& sh) : Shaders(sh) { InputLayout = NULL; }    
+
+    ShaderSet*  GetShaders() const      { return Shaders; }
+    void*       GetInputLayout() const  { return InputLayout; }
+
+    virtual void Set(PrimitiveType prim = Prim_Unknown) const {
+		Shaders->Set(prim);
+		for(int i = 0; i < 8; i++)
+		{
+			if(Textures[i])
+			{
+				Textures[i]->Set(i);
+			}
+		}
+	}
+
+    virtual void SetTexture(int i, class Texture* tex) { if (i < 8) Textures[i] = tex; }
+};
+
+    
+struct DisplayId
+{
+    // Windows
+    String MonitorName; // Monitor name for fullscreen mode
+    
+    // MacOS
+    long   CgDisplayId; // CGDirectDisplayID
+    
+    DisplayId() : CgDisplayId(0) {}
+    DisplayId(long id) : CgDisplayId(id) {}
+    DisplayId(String m, long id=0) : MonitorName(m), CgDisplayId(id) {}
+    
+    operator bool () const
+    {
+        return MonitorName.GetLength() || CgDisplayId;
+    }
+    
+    bool operator== (const DisplayId& b) const
+    {
+        return CgDisplayId == b.CgDisplayId &&
+            (strstr(MonitorName.ToCStr(), b.MonitorName.ToCStr()) ||
+             strstr(b.MonitorName.ToCStr(), MonitorName.ToCStr()));
+    }
+};
+
+
+class ShaderBase : public Shader
+{
+public:    
+    RenderParams*   pParams;
+    unsigned char*  UniformData;
+    int             UniformsSize;
+
+	enum VarType
+	{
+		VARTYPE_FLOAT,
+		VARTYPE_INT,
+		VARTYPE_BOOL,
+	};
+
+	struct Uniform
+	{
+		const char* Name;
+		VarType Type;
+		int     Offset, Size;
+	};
+    const Uniform* UniformRefl;
+    size_t UniformReflSize;
+
+	ShaderBase(RenderParams* rp, ShaderStage stage) : Shader(stage), pParams(rp), UniformData(0), UniformsSize(0) {}
+	~ShaderBase()
+	{
+		if (UniformData)    
+			OVR_FREE(UniformData);
+	}
+
+    void InitUniforms(const Uniform* refl, size_t reflSize);
+	bool SetUniform(const char* name, int n, const float* v);
+	bool SetUniformBool(const char* name, int n, const bool* v);
+};
+
+
+template<ShaderStage SStage, GLenum SType>
+class ShaderImpl : public ShaderBase
+{
+    friend class ShaderSet;
+
+public:
+    ShaderImpl(RenderParams* rp, void* s, size_t size, const Uniform* refl, size_t reflSize)
+		: ShaderBase(rp, SStage)
+		, GLShader(0)
+    {
+		bool success;
+        OVR_UNUSED(size);
+        success = Compile((const char*) s);
+        OVR_ASSERT(success);
+		InitUniforms(refl, reflSize);
+    }
+    ~ShaderImpl()
+    {      
+		if (GLShader)
+		{
+			glDeleteShader(GLShader);
+			GLShader = 0;
+		}
+    }
+    bool Compile(const char* src)
+	{
+		if (!GLShader)
+			GLShader = glCreateShader(GLStage());
+
+		glShaderSource(GLShader, 1, &src, 0);
+		glCompileShader(GLShader);
+		GLint r;
+		glGetShaderiv(GLShader, GL_COMPILE_STATUS, &r);
+		if (!r)
+		{
+			GLchar msg[1024];
+			glGetShaderInfoLog(GLShader, sizeof(msg), 0, msg);
+			if (msg[0])
+				OVR_DEBUG_LOG(("Compiling shader\n%s\nfailed: %s\n", src, msg));
+
+			return 0;
+		}
+		return 1;
+	}
+	
+    GLenum GLStage() const
+    {
+		return SType;
+	}
+
+private:
+	GLuint GLShader;
+};
+
+typedef ShaderImpl<Shader_Vertex,  GL_VERTEX_SHADER> VertexShader;
+typedef ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER> FragmentShader;
+
+}}}
+
+#endif // INC_OVR_CAPI_GL_Util_h
diff --git a/LibOVR/Src/Kernel/OVR_Alg.cpp b/LibOVR/Src/Kernel/OVR_Alg.cpp
new file mode 100644
index 0000000..2e52bc3
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Alg.cpp
@@ -0,0 +1,57 @@
+/************************************************************************************
+
+Filename    :   OVR_Alg.cpp
+Content     :   Static lookup tables for Alg functions
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_Types.h"
+
+namespace OVR { namespace Alg {
+
+//------------------------------------------------------------------------
+extern const UByte UpperBitTable[256] =
+{
+    0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+
+extern const UByte LowerBitTable[256] =
+{
+    8,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+    5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+    6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+    5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+    7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+    5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+    6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,
+    5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0
+};
+
+
+}} // OVE::Alg
diff --git a/LibOVR/Src/Kernel/OVR_Alg.h b/LibOVR/Src/Kernel/OVR_Alg.h
new file mode 100644
index 0000000..e03cea0
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Alg.h
@@ -0,0 +1,1060 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Alg.h
+Content     :   Simple general purpose algorithms: Sort, Binary Search, etc.
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Alg_h
+#define OVR_Alg_h
+
+#include "OVR_Types.h"
+#include <string.h>
+
+namespace OVR { namespace Alg {
+
+
+//-----------------------------------------------------------------------------------
+// ***** Operator extensions
+
+template <typename T> OVR_FORCE_INLINE void Swap(T &a, T &b) 
+{  T temp(a); a = b; b = temp; }
+
+
+// ***** min/max are not implemented in Visual Studio 6 standard STL
+
+template <typename T> OVR_FORCE_INLINE const T Min(const T a, const T b)
+{ return (a < b) ? a : b; }
+
+template <typename T> OVR_FORCE_INLINE const T Max(const T a, const T b)
+{ return (b < a) ? a : b; }
+
+template <typename T> OVR_FORCE_INLINE const T Clamp(const T v, const T minVal, const T maxVal)
+{ return Max<T>(minVal, Min<T>(v, maxVal)); }
+
+template <typename T> OVR_FORCE_INLINE int     Chop(T f)
+{ return (int)f; }
+
+template <typename T> OVR_FORCE_INLINE T       Lerp(T a, T b, T f) 
+{ return (b - a) * f + a; }
+
+
+// These functions stand to fix a stupid VC++ warning (with /Wp64 on):
+// "warning C4267: 'argument' : conversion from 'size_t' to 'const unsigned', possible loss of data"
+// Use these functions instead of gmin/gmax if the argument has size
+// of the pointer to avoid the warning. Though, functionally they are
+// absolutelly the same as regular gmin/gmax.
+template <typename T>   OVR_FORCE_INLINE const T PMin(const T a, const T b)
+{
+    OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt));
+    return (a < b) ? a : b;
+}
+template <typename T>   OVR_FORCE_INLINE const T PMax(const T a, const T b)
+{
+    OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt));
+    return (b < a) ? a : b;
+}
+
+
+template <typename T>   OVR_FORCE_INLINE const T Abs(const T v)
+{ return (v>=0) ? v : -v; }
+
+
+//-----------------------------------------------------------------------------------
+// ***** OperatorLess
+//
+template<class T> struct OperatorLess
+{
+    static bool Compare(const T& a, const T& b)
+    {
+        return a < b;
+    }
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** QuickSortSliced
+//
+// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
+// The range is specified with start, end, where "end" is exclusive!
+// The comparison predicate must be specified.
+template<class Array, class Less> 
+void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less)
+{
+    enum 
+    {
+        Threshold = 9
+    };
+
+    if(end - start <  2) return;
+
+    SPInt  stack[80];
+    SPInt* top   = stack; 
+    SPInt  base  = (SPInt)start;
+    SPInt  limit = (SPInt)end;
+
+    for(;;)
+    {
+        SPInt len = limit - base;
+        SPInt i, j, pivot;
+
+        if(len > Threshold)
+        {
+            // we use base + len/2 as the pivot
+            pivot = base + len / 2;
+            Swap(arr[base], arr[pivot]);
+
+            i = base + 1;
+            j = limit - 1;
+
+            // now ensure that *i <= *base <= *j 
+            if(less(arr[j],    arr[i])) Swap(arr[j],    arr[i]);
+            if(less(arr[base], arr[i])) Swap(arr[base], arr[i]);
+            if(less(arr[j], arr[base])) Swap(arr[j], arr[base]);
+
+            for(;;)
+            {
+                do i++; while( less(arr[i], arr[base]) );
+                do j--; while( less(arr[base], arr[j]) );
+
+                if( i > j )
+                {
+                    break;
+                }
+
+                Swap(arr[i], arr[j]);
+            }
+
+            Swap(arr[base], arr[j]);
+
+            // now, push the largest sub-array
+            if(j - base > limit - i)
+            {
+                top[0] = base;
+                top[1] = j;
+                base   = i;
+            }
+            else
+            {
+                top[0] = i;
+                top[1] = limit;
+                limit  = j;
+            }
+            top += 2;
+        }
+        else
+        {
+            // the sub-array is small, perform insertion sort
+            j = base;
+            i = j + 1;
+
+            for(; i < limit; j = i, i++)
+            {
+                for(; less(arr[j + 1], arr[j]); j--)
+                {
+                    Swap(arr[j + 1], arr[j]);
+                    if(j == base)
+                    {
+                        break;
+                    }
+                }
+            }
+            if(top > stack)
+            {
+                top  -= 2;
+                base  = top[0];
+                limit = top[1];
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** QuickSortSliced
+//
+// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
+// The range is specified with start, end, where "end" is exclusive!
+// The data type must have a defined "<" operator.
+template<class Array> 
+void QuickSortSliced(Array& arr, UPInt start, UPInt end)
+{
+    typedef typename Array::ValueType ValueType;
+    QuickSortSliced(arr, start, end, OperatorLess<ValueType>::Compare);
+}
+
+// Same as corresponding G_QuickSortSliced but with checking array limits to avoid
+// crash in the case of wrong comparator functor.
+template<class Array, class Less> 
+bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less)
+{
+    enum 
+    {
+        Threshold = 9
+    };
+
+    if(end - start <  2) return true;
+
+    SPInt  stack[80];
+    SPInt* top   = stack; 
+    SPInt  base  = (SPInt)start;
+    SPInt  limit = (SPInt)end;
+
+    for(;;)
+    {
+        SPInt len = limit - base;
+        SPInt i, j, pivot;
+
+        if(len > Threshold)
+        {
+            // we use base + len/2 as the pivot
+            pivot = base + len / 2;
+            Swap(arr[base], arr[pivot]);
+
+            i = base + 1;
+            j = limit - 1;
+
+            // now ensure that *i <= *base <= *j 
+            if(less(arr[j],    arr[i])) Swap(arr[j],    arr[i]);
+            if(less(arr[base], arr[i])) Swap(arr[base], arr[i]);
+            if(less(arr[j], arr[base])) Swap(arr[j], arr[base]);
+
+            for(;;)
+            {
+                do 
+                {   
+                    i++; 
+                    if (i >= limit)
+                        return false;
+                } while( less(arr[i], arr[base]) );
+                do 
+                {
+                    j--; 
+                    if (j < 0)
+                        return false;
+                } while( less(arr[base], arr[j]) );
+
+                if( i > j )
+                {
+                    break;
+                }
+
+                Swap(arr[i], arr[j]);
+            }
+
+            Swap(arr[base], arr[j]);
+
+            // now, push the largest sub-array
+            if(j - base > limit - i)
+            {
+                top[0] = base;
+                top[1] = j;
+                base   = i;
+            }
+            else
+            {
+                top[0] = i;
+                top[1] = limit;
+                limit  = j;
+            }
+            top += 2;
+        }
+        else
+        {
+            // the sub-array is small, perform insertion sort
+            j = base;
+            i = j + 1;
+
+            for(; i < limit; j = i, i++)
+            {
+                for(; less(arr[j + 1], arr[j]); j--)
+                {
+                    Swap(arr[j + 1], arr[j]);
+                    if(j == base)
+                    {
+                        break;
+                    }
+                }
+            }
+            if(top > stack)
+            {
+                top  -= 2;
+                base  = top[0];
+                limit = top[1];
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+    return true;
+}
+
+template<class Array> 
+bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end)
+{
+    typedef typename Array::ValueType ValueType;
+    return QuickSortSlicedSafe(arr, start, end, OperatorLess<ValueType>::Compare);
+}
+
+//-----------------------------------------------------------------------------------
+// ***** QuickSort
+//
+// Sort an array Array, ArrayPaged, ArrayUnsafe.
+// The array must have GetSize() function.
+// The comparison predicate must be specified.
+template<class Array, class Less> 
+void QuickSort(Array& arr, Less less)
+{
+    QuickSortSliced(arr, 0, arr.GetSize(), less);
+}
+
+// checks for boundaries
+template<class Array, class Less> 
+bool QuickSortSafe(Array& arr, Less less)
+{
+    return QuickSortSlicedSafe(arr, 0, arr.GetSize(), less);
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** QuickSort
+//
+// Sort an array Array, ArrayPaged, ArrayUnsafe.
+// The array must have GetSize() function.
+// The data type must have a defined "<" operator.
+template<class Array> 
+void QuickSort(Array& arr)
+{
+    typedef typename Array::ValueType ValueType;
+    QuickSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
+}
+
+template<class Array> 
+bool QuickSortSafe(Array& arr)
+{
+    typedef typename Array::ValueType ValueType;
+    return QuickSortSlicedSafe(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
+}
+
+//-----------------------------------------------------------------------------------
+// ***** InsertionSortSliced
+//
+// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
+// The range is specified with start, end, where "end" is exclusive!
+// The comparison predicate must be specified.
+// Unlike Quick Sort, the Insertion Sort works much slower in average, 
+// but may be much faster on almost sorted arrays. Besides, it guarantees
+// that the elements will not be swapped if not necessary. For example, 
+// an array with all equal elements will remain "untouched", while 
+// Quick Sort will considerably shuffle the elements in this case.
+template<class Array, class Less> 
+void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less)
+{
+    UPInt j = start;
+    UPInt i = j + 1;
+    UPInt limit = end;
+
+    for(; i < limit; j = i, i++)
+    {
+        for(; less(arr[j + 1], arr[j]); j--)
+        {
+            Swap(arr[j + 1], arr[j]);
+            if(j <= start)
+            {
+                break;
+            }
+        }
+    }
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** InsertionSortSliced
+//
+// Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
+// The range is specified with start, end, where "end" is exclusive!
+// The data type must have a defined "<" operator.
+template<class Array> 
+void InsertionSortSliced(Array& arr, UPInt start, UPInt end)
+{
+    typedef typename Array::ValueType ValueType;
+    InsertionSortSliced(arr, start, end, OperatorLess<ValueType>::Compare);
+}
+
+//-----------------------------------------------------------------------------------
+// ***** InsertionSort
+//
+// Sort an array Array, ArrayPaged, ArrayUnsafe.
+// The array must have GetSize() function.
+// The comparison predicate must be specified.
+
+template<class Array, class Less> 
+void InsertionSort(Array& arr, Less less)
+{
+    InsertionSortSliced(arr, 0, arr.GetSize(), less);
+}
+
+//-----------------------------------------------------------------------------------
+// ***** InsertionSort
+//
+// Sort an array Array, ArrayPaged, ArrayUnsafe.
+// The array must have GetSize() function.
+// The data type must have a defined "<" operator.
+template<class Array> 
+void InsertionSort(Array& arr)
+{
+    typedef typename Array::ValueType ValueType;
+    InsertionSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
+}
+
+//-----------------------------------------------------------------------------------
+// ***** Median
+// Returns a median value of the input array.
+// Caveats: partially sorts the array, returns a reference to the array element
+// TBD: This needs to be optimized and generalized
+//
+template<class Array> 
+typename Array::ValueType& Median(Array& arr)
+{
+    UPInt count = arr.GetSize();
+    UPInt mid = (count - 1) / 2;
+    OVR_ASSERT(count > 0);
+
+	for (UPInt j = 0; j <= mid; j++)
+    {
+		UPInt min = j;
+		for (UPInt k = j + 1; k < count; k++)
+            if (arr[k] < arr[min]) 
+                min = k;
+        Swap(arr[j], arr[min]);
+    }
+    return arr[mid];
+}
+
+//-----------------------------------------------------------------------------------
+// ***** LowerBoundSliced
+//
+template<class Array, class Value, class Less>
+UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less)
+{
+    SPInt first = (SPInt)start;
+    SPInt len   = (SPInt)(end - start);
+    SPInt half;
+    SPInt middle;
+    
+    while(len > 0) 
+    {
+        half = len >> 1;
+        middle = first + half;
+        if(less(arr[middle], val)) 
+        {
+            first = middle + 1;
+            len   = len - half - 1;
+        }
+        else
+        {
+            len = half;
+        }
+    }
+    return (UPInt)first;
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** LowerBoundSliced
+//
+template<class Array, class Value>
+UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val)
+{
+    return LowerBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare);
+}
+
+//-----------------------------------------------------------------------------------
+// ***** LowerBoundSized
+//
+template<class Array, class Value>
+UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val)
+{
+    return LowerBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare);
+}
+
+//-----------------------------------------------------------------------------------
+// ***** LowerBound
+//
+template<class Array, class Value, class Less>
+UPInt LowerBound(const Array& arr, const Value& val, Less less)
+{
+    return LowerBoundSliced(arr, 0, arr.GetSize(), val, less);
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** LowerBound
+//
+template<class Array, class Value>
+UPInt LowerBound(const Array& arr, const Value& val)
+{
+    return LowerBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare);
+}
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** UpperBoundSliced
+//
+template<class Array, class Value, class Less>
+UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less)
+{
+    SPInt first = (SPInt)start;
+    SPInt len   = (SPInt)(end - start);
+    SPInt half;
+    SPInt middle;
+    
+    while(len > 0) 
+    {
+        half = len >> 1;
+        middle = first + half;
+        if(less(val, arr[middle]))
+        {
+            len = half;
+        }
+        else 
+        {
+            first = middle + 1;
+            len   = len - half - 1;
+        }
+    }
+    return (UPInt)first;
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** UpperBoundSliced
+//
+template<class Array, class Value>
+UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val)
+{
+    return UpperBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare);
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** UpperBoundSized
+//
+template<class Array, class Value>
+UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val)
+{
+    return UpperBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare);
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** UpperBound
+//
+template<class Array, class Value, class Less>
+UPInt UpperBound(const Array& arr, const Value& val, Less less)
+{
+    return UpperBoundSliced(arr, 0, arr.GetSize(), val, less);
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** UpperBound
+//
+template<class Array, class Value>
+UPInt UpperBound(const Array& arr, const Value& val)
+{
+    return UpperBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare);
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** ReverseArray
+//
+template<class Array> void ReverseArray(Array& arr)
+{
+    SPInt from = 0;
+    SPInt to   = arr.GetSize() - 1;
+    while(from < to)
+    {
+        Swap(arr[from], arr[to]);
+        ++from;
+        --to;
+    }
+}
+
+
+// ***** AppendArray
+//
+template<class CDst, class CSrc> 
+void AppendArray(CDst& dst, const CSrc& src)
+{
+    UPInt i;
+    for(i = 0; i < src.GetSize(); i++) 
+        dst.PushBack(src[i]);
+}
+
+//-----------------------------------------------------------------------------------
+// ***** ArrayAdaptor
+//
+// A simple adapter that provides the GetSize() method and overloads 
+// operator []. Used to wrap plain arrays in QuickSort and such.
+template<class T> class ArrayAdaptor
+{
+public:
+    typedef T ValueType;
+    ArrayAdaptor() : Data(0), Size(0) {}
+    ArrayAdaptor(T* ptr, UPInt size) : Data(ptr), Size(size) {}
+    UPInt GetSize() const { return Size; }
+    const T& operator [] (UPInt i) const { return Data[i]; }
+          T& operator [] (UPInt i)       { return Data[i]; }
+private:
+    T*      Data;
+    UPInt   Size;
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** GConstArrayAdaptor
+//
+// A simple const adapter that provides the GetSize() method and overloads 
+// operator []. Used to wrap plain arrays in LowerBound and such.
+template<class T> class ConstArrayAdaptor
+{
+public:
+    typedef T ValueType;
+    ConstArrayAdaptor() : Data(0), Size(0) {}
+    ConstArrayAdaptor(const T* ptr, UPInt size) : Data(ptr), Size(size) {}
+    UPInt GetSize() const { return Size; }
+    const T& operator [] (UPInt i) const { return Data[i]; }
+private:
+    const T* Data;
+    UPInt    Size;
+};
+
+
+
+//-----------------------------------------------------------------------------------
+extern const UByte UpperBitTable[256];
+extern const UByte LowerBitTable[256];
+
+
+
+//-----------------------------------------------------------------------------------
+inline UByte UpperBit(UPInt val)
+{
+#ifndef OVR_64BIT_POINTERS
+
+    if (val & 0xFFFF0000)
+    {
+        return (val & 0xFF000000) ? 
+            UpperBitTable[(val >> 24)       ] + 24: 
+            UpperBitTable[(val >> 16) & 0xFF] + 16;
+    }
+    return (val & 0xFF00) ?
+        UpperBitTable[(val >> 8) & 0xFF] + 8:
+        UpperBitTable[(val     ) & 0xFF];
+
+#else
+
+    if (val & 0xFFFFFFFF00000000)
+    {
+        if (val & 0xFFFF000000000000)
+        {
+            return (val & 0xFF00000000000000) ?
+                UpperBitTable[(val >> 56)       ] + 56: 
+                UpperBitTable[(val >> 48) & 0xFF] + 48;
+        }
+        return (val & 0xFF0000000000) ?
+            UpperBitTable[(val >> 40) & 0xFF] + 40:
+            UpperBitTable[(val >> 32) & 0xFF] + 32;
+    }
+    else
+    {
+        if (val & 0xFFFF0000)
+        {
+            return (val & 0xFF000000) ? 
+                UpperBitTable[(val >> 24)       ] + 24: 
+                UpperBitTable[(val >> 16) & 0xFF] + 16;
+        }
+        return (val & 0xFF00) ?
+            UpperBitTable[(val >> 8) & 0xFF] + 8:
+            UpperBitTable[(val     ) & 0xFF];
+    }
+
+#endif
+}
+
+//-----------------------------------------------------------------------------------
+inline UByte LowerBit(UPInt val)
+{
+#ifndef OVR_64BIT_POINTERS
+
+    if (val & 0xFFFF)
+    {
+        return (val & 0xFF) ?
+            LowerBitTable[ val & 0xFF]:
+            LowerBitTable[(val >> 8) & 0xFF] + 8;
+    }
+    return (val & 0xFF0000) ?
+            LowerBitTable[(val >> 16) & 0xFF] + 16:
+            LowerBitTable[(val >> 24) & 0xFF] + 24;
+
+#else
+
+    if (val & 0xFFFFFFFF)
+    {
+        if (val & 0xFFFF)
+        {
+            return (val & 0xFF) ?
+                LowerBitTable[ val & 0xFF]:
+                LowerBitTable[(val >> 8) & 0xFF] + 8;
+        }
+        return (val & 0xFF0000) ?
+                LowerBitTable[(val >> 16) & 0xFF] + 16:
+                LowerBitTable[(val >> 24) & 0xFF] + 24;
+    }
+    else
+    {
+        if (val & 0xFFFF00000000)
+        {
+             return (val & 0xFF00000000) ?
+                LowerBitTable[(val >> 32) & 0xFF] + 32:
+                LowerBitTable[(val >> 40) & 0xFF] + 40;
+        }
+        return (val & 0xFF000000000000) ?
+            LowerBitTable[(val >> 48) & 0xFF] + 48:
+            LowerBitTable[(val >> 56) & 0xFF] + 56;
+    }
+
+#endif
+}
+
+
+
+// ******* Special (optimized) memory routines
+// Note: null (bad) pointer is not tested
+class MemUtil
+{
+public:
+                                    
+    // Memory compare
+    static int      Cmp  (const void* p1, const void* p2, UPInt byteCount)      { return memcmp(p1, p2, byteCount); }
+    static int      Cmp16(const void* p1, const void* p2, UPInt int16Count);
+    static int      Cmp32(const void* p1, const void* p2, UPInt int32Count);
+    static int      Cmp64(const void* p1, const void* p2, UPInt int64Count); 
+};
+
+// ** Inline Implementation
+
+inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count)
+{
+    SInt16*  pa  = (SInt16*)p1; 
+    SInt16*  pb  = (SInt16*)p2;
+    unsigned ic  = 0;
+    if (int16Count == 0)
+        return 0;
+    while (pa[ic] == pb[ic])
+        if (++ic==int16Count)
+            return 0;
+    return pa[ic] > pb[ic] ? 1 : -1;
+}
+inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count)
+{
+    SInt32*  pa  = (SInt32*)p1;
+    SInt32*  pb  = (SInt32*)p2;
+    unsigned ic  = 0;
+    if (int32Count == 0)
+        return 0;
+    while (pa[ic] == pb[ic])
+        if (++ic==int32Count)
+            return 0;
+    return pa[ic] > pb[ic] ? 1 : -1;
+}
+inline int MemUtil::Cmp64(const void* p1, const void* p2, UPInt int64Count)
+{
+    SInt64*  pa  = (SInt64*)p1;
+    SInt64*  pb  = (SInt64*)p2;
+    unsigned ic  = 0;
+    if (int64Count == 0)
+        return 0;
+    while (pa[ic] == pb[ic])
+        if (++ic==int64Count)
+            return 0;
+    return pa[ic] > pb[ic] ? 1 : -1;
+}
+
+// ** End Inline Implementation
+
+
+//-----------------------------------------------------------------------------------
+// ******* Byte Order Conversions
+namespace ByteUtil {
+
+    // *** Swap Byte Order
+
+    // Swap the byte order of a byte array
+    inline void     SwapOrder(void* pv, int size)
+    {
+        UByte*  pb = (UByte*)pv;
+        UByte   temp;
+        for (int i = 0; i < size>>1; i++)
+        { 
+            temp            = pb[size-1-i];
+            pb[size-1-i]    = pb[i];
+            pb[i]           = temp; 
+        }
+    }
+
+    // Swap the byte order of primitive types
+    inline UByte    SwapOrder(UByte v)      { return v; }
+    inline SByte    SwapOrder(SByte v)      { return v; }
+    inline UInt16   SwapOrder(UInt16 v)     { return UInt16(v>>8)|UInt16(v<<8); }
+    inline SInt16   SwapOrder(SInt16 v)     { return SInt16((UInt16(v)>>8)|(v<<8)); }
+    inline UInt32   SwapOrder(UInt32 v)     { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); }
+    inline SInt32   SwapOrder(SInt32 p)     { return (SInt32)SwapOrder(UInt32(p)); }
+    inline UInt64   SwapOrder(UInt64 v)
+    { 
+        return   (v>>56) |
+                 ((v&UInt64(0x00FF000000000000ULL))>>40) |
+                 ((v&UInt64(0x0000FF0000000000ULL))>>24) |
+                 ((v&UInt64(0x000000FF00000000ULL))>>8)  |
+                 ((v&UInt64(0x00000000FF000000ULL))<<8)  |
+                 ((v&UInt64(0x0000000000FF0000ULL))<<24) |
+                 ((v&UInt64(0x000000000000FF00ULL))<<40) |
+                 (v<<56); 
+    }
+    inline SInt64   SwapOrder(SInt64 v)     { return (SInt64)SwapOrder(UInt64(v)); }
+    inline float    SwapOrder(float p)      
+    { 
+        union {
+            float p;
+            UInt32 v;
+        } u;
+        u.p = p;
+        u.v = SwapOrder(u.v);
+        return u.p;
+    }
+
+    inline double   SwapOrder(double p)
+    { 
+        union {
+            double p;
+            UInt64 v;
+        } u;
+        u.p = p;
+        u.v = SwapOrder(u.v);
+        return u.p;
+    }
+    
+    // *** Byte-order conversion
+
+#if (OVR_BYTE_ORDER == OVR_LITTLE_ENDIAN)
+    // Little Endian to System (LE)
+    inline UByte    LEToSystem(UByte  v)    { return v; }
+    inline SByte    LEToSystem(SByte  v)    { return v; }
+    inline UInt16   LEToSystem(UInt16 v)    { return v; }
+    inline SInt16   LEToSystem(SInt16 v)    { return v; }
+    inline UInt32   LEToSystem(UInt32 v)    { return v; }
+    inline SInt32   LEToSystem(SInt32 v)    { return v; }
+    inline UInt64   LEToSystem(UInt64 v)    { return v; }
+    inline SInt64   LEToSystem(SInt64 v)    { return v; }
+    inline float    LEToSystem(float  v)    { return v; }
+    inline double   LEToSystem(double v)    { return v; }
+
+    // Big Endian to System (LE)
+    inline UByte    BEToSystem(UByte  v)    { return SwapOrder(v); }
+    inline SByte    BEToSystem(SByte  v)    { return SwapOrder(v); }
+    inline UInt16   BEToSystem(UInt16 v)    { return SwapOrder(v); }
+    inline SInt16   BEToSystem(SInt16 v)    { return SwapOrder(v); }
+    inline UInt32   BEToSystem(UInt32 v)    { return SwapOrder(v); }
+    inline SInt32   BEToSystem(SInt32 v)    { return SwapOrder(v); }
+    inline UInt64   BEToSystem(UInt64 v)    { return SwapOrder(v); }
+    inline SInt64   BEToSystem(SInt64 v)    { return SwapOrder(v); }
+    inline float    BEToSystem(float  v)    { return SwapOrder(v); }
+    inline double   BEToSystem(double v)    { return SwapOrder(v); }
+
+    // System (LE) to Little Endian
+    inline UByte    SystemToLE(UByte  v)    { return v; }
+    inline SByte    SystemToLE(SByte  v)    { return v; }
+    inline UInt16   SystemToLE(UInt16 v)    { return v; }
+    inline SInt16   SystemToLE(SInt16 v)    { return v; }
+    inline UInt32   SystemToLE(UInt32 v)    { return v; }
+    inline SInt32   SystemToLE(SInt32 v)    { return v; }
+    inline UInt64   SystemToLE(UInt64 v)    { return v; }
+    inline SInt64   SystemToLE(SInt64 v)    { return v; }
+    inline float    SystemToLE(float  v)    { return v; }
+    inline double   SystemToLE(double v)    { return v; }   
+
+    // System (LE) to Big Endian
+    inline UByte    SystemToBE(UByte  v)    { return SwapOrder(v); }
+    inline SByte    SystemToBE(SByte  v)    { return SwapOrder(v); }
+    inline UInt16   SystemToBE(UInt16 v)    { return SwapOrder(v); }
+    inline SInt16   SystemToBE(SInt16 v)    { return SwapOrder(v); }
+    inline UInt32   SystemToBE(UInt32 v)    { return SwapOrder(v); }
+    inline SInt32   SystemToBE(SInt32 v)    { return SwapOrder(v); }
+    inline UInt64   SystemToBE(UInt64 v)    { return SwapOrder(v); }
+    inline SInt64   SystemToBE(SInt64 v)    { return SwapOrder(v); }
+    inline float    SystemToBE(float  v)    { return SwapOrder(v); }
+    inline double   SystemToBE(double v)    { return SwapOrder(v); }
+
+#elif (OVR_BYTE_ORDER == OVR_BIG_ENDIAN)
+    // Little Endian to System (BE)
+    inline UByte    LEToSystem(UByte  v)    { return SwapOrder(v); }
+    inline SByte    LEToSystem(SByte  v)    { return SwapOrder(v); }
+    inline UInt16   LEToSystem(UInt16 v)    { return SwapOrder(v); }
+    inline SInt16   LEToSystem(SInt16 v)    { return SwapOrder(v); }
+    inline UInt32   LEToSystem(UInt32 v)    { return SwapOrder(v); }
+    inline SInt32   LEToSystem(SInt32 v)    { return SwapOrder(v); }
+    inline UInt64   LEToSystem(UInt64 v)    { return SwapOrder(v); }
+    inline SInt64   LEToSystem(SInt64 v)    { return SwapOrder(v); }
+    inline float    LEToSystem(float  v)    { return SwapOrder(v); }
+    inline double   LEToSystem(double v)    { return SwapOrder(v); }
+
+    // Big Endian to System (BE)
+    inline UByte    BEToSystem(UByte  v)    { return v; }
+    inline SByte    BEToSystem(SByte  v)    { return v; }
+    inline UInt16   BEToSystem(UInt16 v)    { return v; }
+    inline SInt16   BEToSystem(SInt16 v)    { return v; }
+    inline UInt32   BEToSystem(UInt32 v)    { return v; }
+    inline SInt32   BEToSystem(SInt32 v)    { return v; }
+    inline UInt64   BEToSystem(UInt64 v)    { return v; }
+    inline SInt64   BEToSystem(SInt64 v)    { return v; }
+    inline float    BEToSystem(float  v)    { return v; }
+    inline double   BEToSystem(double v)    { return v; }
+
+    // System (BE) to Little Endian
+    inline UByte    SystemToLE(UByte  v)    { return SwapOrder(v); }
+    inline SByte    SystemToLE(SByte  v)    { return SwapOrder(v); }
+    inline UInt16   SystemToLE(UInt16 v)    { return SwapOrder(v); }
+    inline SInt16   SystemToLE(SInt16 v)    { return SwapOrder(v); }
+    inline UInt32   SystemToLE(UInt32 v)    { return SwapOrder(v); }
+    inline SInt32   SystemToLE(SInt32 v)    { return SwapOrder(v); }
+    inline UInt64   SystemToLE(UInt64 v)    { return SwapOrder(v); }
+    inline SInt64   SystemToLE(SInt64 v)    { return SwapOrder(v); }
+    inline float    SystemToLE(float  v)    { return SwapOrder(v); }
+    inline double   SystemToLE(double v)    { return SwapOrder(v); }
+
+    // System (BE) to Big Endian
+    inline UByte    SystemToBE(UByte  v)    { return v; }
+    inline SByte    SystemToBE(SByte  v)    { return v; }
+    inline UInt16   SystemToBE(UInt16 v)    { return v; }
+    inline SInt16   SystemToBE(SInt16 v)    { return v; }
+    inline UInt32   SystemToBE(UInt32 v)    { return v; }
+    inline SInt32   SystemToBE(SInt32 v)    { return v; }
+    inline UInt64   SystemToBE(UInt64 v)    { return v; }
+    inline SInt64   SystemToBE(SInt64 v)    { return v; }
+    inline float    SystemToBE(float  v)    { return v; }
+    inline double   SystemToBE(double v)    { return v; }
+
+#else
+    #error "OVR_BYTE_ORDER must be defined to OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN"
+#endif
+
+} // namespace ByteUtil
+
+
+
+// Used primarily for hardware interfacing such as sensor reports, firmware, etc.
+// Reported data is all little-endian.
+inline UInt16 DecodeUInt16(const UByte* buffer)
+{
+    return ByteUtil::LEToSystem ( *(const UInt16*)buffer );
+}
+
+inline SInt16 DecodeSInt16(const UByte* buffer)
+{
+    return ByteUtil::LEToSystem ( *(const SInt16*)buffer );
+}
+
+inline UInt32 DecodeUInt32(const UByte* buffer)
+{    
+    return ByteUtil::LEToSystem ( *(const UInt32*)buffer );
+}
+
+inline SInt32 DecodeSInt32(const UByte* buffer)
+{    
+    return ByteUtil::LEToSystem ( *(const SInt32*)buffer );
+}
+
+inline float DecodeFloat(const UByte* buffer)
+{
+    union {
+        UInt32 U;
+        float  F;
+    };
+
+    U = DecodeUInt32(buffer);
+    return F;
+}
+
+inline void EncodeUInt16(UByte* buffer, UInt16 val)
+{
+    *(UInt16*)buffer = ByteUtil::SystemToLE ( val );
+}
+
+inline void EncodeSInt16(UByte* buffer, SInt16 val)
+{
+    *(SInt16*)buffer = ByteUtil::SystemToLE ( val );
+}
+
+inline void EncodeUInt32(UByte* buffer, UInt32 val)
+{
+    *(UInt32*)buffer = ByteUtil::SystemToLE ( val );
+}
+
+inline void EncodeSInt32(UByte* buffer, SInt32 val)
+{
+    *(SInt32*)buffer = ByteUtil::SystemToLE ( val );
+}
+
+inline void EncodeFloat(UByte* buffer, float val)
+{
+    union {
+        UInt32 U;
+        float  F;
+    };
+
+    F = val;
+    EncodeUInt32(buffer, U);
+}
+
+// Converts an 8-bit binary-coded decimal
+inline SByte DecodeBCD(UByte byte)
+{
+    UByte digit1 = (byte >> 4) & 0x0f;
+    UByte digit2 = byte & 0x0f;
+    int decimal = digit1 * 10 + digit2;   // maximum value = 99
+    return (SByte)decimal;
+}
+
+
+}} // OVR::Alg
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_Allocator.cpp b/LibOVR/Src/Kernel/OVR_Allocator.cpp
new file mode 100644
index 0000000..0f82561
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Allocator.cpp
@@ -0,0 +1,95 @@
+/************************************************************************************
+
+Filename    :   OVR_Allocator.cpp
+Content     :   Installable memory allocator implementation
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_Allocator.h"
+#ifdef OVR_OS_MAC
+ #include <stdlib.h>
+#else
+ #include <malloc.h>
+#endif
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** Allocator
+
+Allocator* Allocator::pInstance = 0;
+
+// Default AlignedAlloc implementation will delegate to Alloc/Free after doing rounding.
+void* Allocator::AllocAligned(UPInt size, UPInt align)
+{
+    OVR_ASSERT((align & (align-1)) == 0);
+    align = (align > sizeof(UPInt)) ? align : sizeof(UPInt);
+    UPInt p = (UPInt)Alloc(size+align);
+    UPInt aligned = 0;
+    if (p)
+    {
+        aligned = (UPInt(p) + align-1) & ~(align-1);
+        if (aligned == p) 
+            aligned += align;
+        *(((UPInt*)aligned)-1) = aligned-p;
+    }
+    return (void*)aligned;
+}
+
+void Allocator::FreeAligned(void* p)
+{
+    UPInt src = UPInt(p) - *(((UPInt*)p)-1);
+    Free((void*)src);
+}
+
+
+//------------------------------------------------------------------------
+// ***** Default Allocator
+
+// This allocator is created and used if no other allocator is installed.
+// Default allocator delegates to system malloc.
+
+void* DefaultAllocator::Alloc(UPInt size)
+{
+    return malloc(size);
+}
+void* DefaultAllocator::AllocDebug(UPInt size, const char* file, unsigned line)
+{
+#if defined(OVR_CC_MSVC) && defined(_CRTDBG_MAP_ALLOC)
+    return _malloc_dbg(size, _NORMAL_BLOCK, file, line);
+#else
+    OVR_UNUSED2(file, line);
+    return malloc(size);
+#endif
+}
+
+void* DefaultAllocator::Realloc(void* p, UPInt newSize)
+{
+    return realloc(p, newSize);
+}
+void DefaultAllocator::Free(void *p)
+{
+    return free(p);
+}
+
+
+} // OVR
diff --git a/LibOVR/Src/Kernel/OVR_Allocator.h b/LibOVR/Src/Kernel/OVR_Allocator.h
new file mode 100644
index 0000000..b862557
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Allocator.h
@@ -0,0 +1,347 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Allocator.h
+Content     :   Installable memory allocator
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Allocator_h
+#define OVR_Allocator_h
+
+#include "OVR_Types.h"
+
+//-----------------------------------------------------------------------------------
+
+// ***** Disable template-unfriendly MS VC++ warnings
+#if defined(OVR_CC_MSVC)
+// Pragma to prevent long name warnings in in VC++
+#pragma warning(disable : 4503)
+#pragma warning(disable : 4786)
+// In MSVC 7.1, warning about placement new POD default initializer
+#pragma warning(disable : 4345)
+#endif
+
+// Un-define new so that placement constructors work
+#undef new
+
+
+//-----------------------------------------------------------------------------------
+// ***** Placement new overrides
+
+// Calls constructor on own memory created with "new(ptr) type"
+#ifndef __PLACEMENT_NEW_INLINE
+#define __PLACEMENT_NEW_INLINE
+
+#   if defined(OVR_CC_MWERKS) || defined(OVR_CC_BORLAND) || defined(OVR_CC_GNU)
+#      include <new>
+#   else
+    // Useful on MSVC
+    OVR_FORCE_INLINE void* operator new     (OVR::UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; }
+    OVR_FORCE_INLINE void  operator delete  (void *, void *)     { }
+#   endif
+
+#endif // __PLACEMENT_NEW_INLINE
+
+
+
+//------------------------------------------------------------------------
+// ***** Macros to redefine class new/delete operators
+
+// Types specifically declared to allow disambiguation of address in
+// class member operator new.
+
+#define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete)                          \
+    void*   operator new(UPInt sz)                                                      \
+    { void *p = OVR_ALLOC_DEBUG(sz, __FILE__, __LINE__); return p; }                                              \
+    void*   operator new(UPInt sz, const char* file, int line)                          \
+    { void* p = OVR_ALLOC_DEBUG(sz, file, line); OVR_UNUSED2(file, line); return p; }   \
+    void    operator delete(void *p)                                                    \
+    { check_delete(class_name, p); OVR_FREE(p); }                                       \
+    void    operator delete(void *p, const char*, int)                                  \
+    { check_delete(class_name, p); OVR_FREE(p); }                          
+
+#define OVR_MEMORY_DEFINE_PLACEMENT_NEW                                                 \
+    void*   operator new        (UPInt n, void *ptr)    { OVR_UNUSED(n); return ptr; }  \
+    void    operator delete     (void *ptr, void *ptr2) { OVR_UNUSED2(ptr,ptr2); }
+
+
+#define OVR_MEMORY_CHECK_DELETE_NONE(class_name, p)
+
+// Redefined all delete/new operators in a class without custom memory initialization
+#define OVR_MEMORY_REDEFINE_NEW(class_name) \
+    OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, OVR_MEMORY_CHECK_DELETE_NONE)
+
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** Construct / Destruct
+
+// Construct/Destruct functions are useful when new is redefined, as they can
+// be called instead of placement new constructors.
+
+
+template <class T>
+OVR_FORCE_INLINE T*  Construct(void *p)
+{
+    return ::new(p) T();
+}
+
+template <class T>
+OVR_FORCE_INLINE T*  Construct(void *p, const T& source)
+{
+    return ::new(p) T(source);
+}
+
+// Same as above, but allows for a different type of constructor.
+template <class T, class S>
+OVR_FORCE_INLINE T*  ConstructAlt(void *p, const S& source)
+{
+    return ::new(p) T(source);
+}
+
+template <class T, class S1, class S2>
+OVR_FORCE_INLINE T*  ConstructAlt(void *p, const S1& src1, const S2& src2)
+{
+    return ::new(p) T(src1, src2);
+}
+
+template <class T>
+OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count)
+{
+    UByte *pdata = (UByte*)p;
+    for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
+    {
+        Construct<T>(pdata);
+    }
+}
+
+template <class T>
+OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count, const T& source)
+{
+    UByte *pdata = (UByte*)p;
+    for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
+    {
+        Construct<T>(pdata, source);
+    }
+}
+
+template <class T>
+OVR_FORCE_INLINE void Destruct(T *pobj)
+{
+    pobj->~T();
+    OVR_UNUSED1(pobj); // Fix incorrect 'unused variable' MSVC warning.
+}
+
+template <class T>
+OVR_FORCE_INLINE void DestructArray(T *pobj, UPInt count)
+{   
+    for (UPInt i=0; i<count; ++i, ++pobj)
+        pobj->~T();
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** Allocator
+
+// Allocator defines a memory allocation interface that developers can override
+// to to provide memory for OVR; an instance of this class is typically created on
+// application startup and passed into System or OVR::System constructor.
+// 
+//
+// Users implementing this interface must provide three functions: Alloc, Free,
+// and Realloc. Implementations of these functions must honor the requested alignment.
+// Although arbitrary alignment requests are possible, requested alignment will
+// typically be small, such as 16 bytes or less.
+
+class Allocator
+{
+    friend class System;
+public:
+
+    // *** Standard Alignment Alloc/Free
+
+    // Allocate memory of specified size with default alignment.
+    // Alloc of size==0 will allocate a tiny block & return a valid pointer;
+    // this makes it suitable for new operator.
+    virtual void*   Alloc(UPInt size) = 0;
+    // Same as Alloc, but provides an option of passing debug data.
+    virtual void*   AllocDebug(UPInt size, const char* file, unsigned line)
+    { OVR_UNUSED2(file, line); return Alloc(size); }
+
+    // Reallocate memory block to a new size, copying data if necessary. Returns the pointer to
+    // new memory block, which may be the same as original pointer. Will return 0 if reallocation
+    // failed, in which case previous memory is still valid.
+    // Realloc to decrease size will never fail.
+    // Realloc of pointer == 0 is equivalent to Alloc
+    // Realloc to size == 0, shrinks to the minimal size, pointer remains valid and requires Free().
+    virtual void*   Realloc(void* p, UPInt newSize) = 0;
+
+    // Frees memory allocated by Alloc/Realloc.
+    // Free of null pointer is valid and will do nothing.
+    virtual void    Free(void *p) = 0;
+
+
+    // *** Standard Alignment Alloc/Free
+
+    // Allocate memory of specified alignment.
+    // Memory allocated with AllocAligned MUST be freed with FreeAligned.
+    // Default implementation will delegate to Alloc/Free after doing rounding.
+    virtual void*   AllocAligned(UPInt size, UPInt align);    
+    // Frees memory allocated with AllocAligned.
+    virtual void    FreeAligned(void* p);
+    
+    // Returns the pointer to the current globally installed Allocator instance.
+    // This pointer is used for most of the memory allocations.
+    static Allocator* GetInstance() { return pInstance; }
+
+
+protected:
+    // onSystemShutdown is called on the allocator during System::Shutdown.
+    // At this point, all allocations should've been freed.
+    virtual void    onSystemShutdown() { }
+
+public:
+    static  void    setInstance(Allocator* palloc)    
+    {
+        OVR_ASSERT((pInstance == 0) || (palloc == 0));
+        pInstance = palloc;
+    }
+
+private:
+
+    static Allocator* pInstance;
+};
+
+
+
+//------------------------------------------------------------------------
+// ***** Allocator_SingletonSupport
+
+// Allocator_SingletonSupport is a Allocator wrapper class that implements
+// the InitSystemSingleton static function, used to create a global singleton
+// used for the OVR::System default argument initialization.
+//
+// End users implementing custom Allocator interface don't need to make use of this base
+// class; they can just create an instance of their own class on stack and pass it to System.
+
+template<class D>
+class Allocator_SingletonSupport : public Allocator
+{
+    struct AllocContainer
+    {        
+        UPInt Data[(sizeof(D) + sizeof(UPInt)-1) / sizeof(UPInt)];
+        bool  Initialized;
+        AllocContainer() : Initialized(0) { }
+    };
+
+    AllocContainer* pContainer;
+
+public:
+    Allocator_SingletonSupport() : pContainer(0) { }
+
+    // Creates a singleton instance of this Allocator class used
+    // on OVR_DEFAULT_ALLOCATOR during System initialization.
+    static  D*  InitSystemSingleton()
+    {
+        static AllocContainer Container;
+        OVR_ASSERT(Container.Initialized == false);
+
+        Allocator_SingletonSupport<D> *presult = Construct<D>((void*)Container.Data);
+        presult->pContainer   = &Container;
+        Container.Initialized = true;
+        return (D*)presult;
+    }
+
+protected:
+    virtual void onSystemShutdown()
+    {
+        Allocator::onSystemShutdown();
+        if (pContainer)
+        {
+            pContainer->Initialized = false;
+            Destruct((D*)this);
+            pContainer = 0;
+        }
+    }
+};
+
+//------------------------------------------------------------------------
+// ***** Default Allocator
+
+// This allocator is created and used if no other allocator is installed.
+// Default allocator delegates to system malloc.
+
+class DefaultAllocator : public Allocator_SingletonSupport<DefaultAllocator>
+{
+public:
+    virtual void*   Alloc(UPInt size);
+    virtual void*   AllocDebug(UPInt size, const char* file, unsigned line);
+    virtual void*   Realloc(void* p, UPInt newSize);
+    virtual void    Free(void *p);
+};
+
+
+//------------------------------------------------------------------------
+// ***** Memory Allocation Macros
+
+// These macros should be used for global allocation. In the future, these
+// macros will allows allocation to be extended with debug file/line information
+// if necessary.
+
+#define OVR_REALLOC(p,s)        OVR::Allocator::GetInstance()->Realloc((p),(s))
+#define OVR_FREE(p)             OVR::Allocator::GetInstance()->Free((p))
+#define OVR_ALLOC_ALIGNED(s,a)  OVR::Allocator::GetInstance()->AllocAligned((s),(a))
+#define OVR_FREE_ALIGNED(p)     OVR::Allocator::GetInstance()->FreeAligned((p))
+
+#ifdef OVR_BUILD_DEBUG
+#define OVR_ALLOC(s)            OVR::Allocator::GetInstance()->AllocDebug((s), __FILE__, __LINE__)
+#define OVR_ALLOC_DEBUG(s,f,l)  OVR::Allocator::GetInstance()->AllocDebug((s), f, l)
+#else
+#define OVR_ALLOC(s)            OVR::Allocator::GetInstance()->Alloc((s))
+#define OVR_ALLOC_DEBUG(s,f,l)  OVR::Allocator::GetInstance()->Alloc((s))
+#endif
+
+//------------------------------------------------------------------------
+
+// Base class that overrides the new and delete operators.
+// Deriving from this class, even as a multiple base, incurs no space overhead.
+class NewOverrideBase
+{
+public:
+
+    // Redefine all new & delete operators.
+    OVR_MEMORY_REDEFINE_NEW(NewOverrideBase)
+};
+
+
+} // OVR
+
+
+// Redefine operator 'new' if necessary.
+#if defined(OVR_DEFINE_NEW)
+#define new OVR_DEFINE_NEW
+#endif
+
+
+#endif // OVR_Memory
diff --git a/LibOVR/Src/Kernel/OVR_Array.h b/LibOVR/Src/Kernel/OVR_Array.h
new file mode 100644
index 0000000..7a715ba
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Array.h
@@ -0,0 +1,833 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Array.h
+Content     :   Template implementation for Array
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Array_h
+#define OVR_Array_h
+
+#include "OVR_ContainerAllocator.h"
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** ArrayDefaultPolicy
+//
+// Default resize behavior. No minimal capacity, Granularity=4, 
+// Shrinking as needed. ArrayConstPolicy actually is the same as 
+// ArrayDefaultPolicy, but parametrized with constants. 
+// This struct is used only in order to reduce the template "matroska".
+struct ArrayDefaultPolicy
+{
+    ArrayDefaultPolicy() : Capacity(0) {}
+    ArrayDefaultPolicy(const ArrayDefaultPolicy&) : Capacity(0) {}
+
+    UPInt GetMinCapacity() const { return 0; }
+    UPInt GetGranularity() const { return 4; }
+    bool  NeverShrinking() const { return 0; }
+
+    UPInt GetCapacity()    const      { return Capacity; }
+    void  SetCapacity(UPInt capacity) { Capacity = capacity; }
+private:
+    UPInt Capacity;
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** ArrayConstPolicy
+//
+// Statically parametrized resizing behavior:
+// MinCapacity, Granularity, and Shrinking flag.
+template<int MinCapacity=0, int Granularity=4, bool NeverShrink=false>
+struct ArrayConstPolicy
+{
+    typedef ArrayConstPolicy<MinCapacity, Granularity, NeverShrink> SelfType;
+
+    ArrayConstPolicy() : Capacity(0) {}
+    ArrayConstPolicy(const SelfType&) : Capacity(0) {}
+
+    UPInt GetMinCapacity() const { return MinCapacity; }
+    UPInt GetGranularity() const { return Granularity; }
+    bool  NeverShrinking() const { return NeverShrink; }
+
+    UPInt GetCapacity()    const      { return Capacity; }
+    void  SetCapacity(UPInt capacity) { Capacity = capacity; }
+private:
+    UPInt Capacity;
+};
+
+//-----------------------------------------------------------------------------------
+// ***** ArrayDataBase
+//
+// Basic operations with array data: Reserve, Resize, Free, ArrayPolicy.
+// For internal use only: ArrayData,ArrayDataCC and others.
+template<class T, class Allocator, class SizePolicy>
+struct ArrayDataBase
+{
+    typedef T                                           ValueType;
+    typedef Allocator                                   AllocatorType;
+    typedef SizePolicy                                  SizePolicyType;
+    typedef ArrayDataBase<T, Allocator, SizePolicy>     SelfType;
+
+    ArrayDataBase()
+        : Data(0), Size(0), Policy() {}
+
+    ArrayDataBase(const SizePolicy& p)
+        : Data(0), Size(0), Policy(p) {}
+
+    ~ArrayDataBase() 
+    {
+        Allocator::DestructArray(Data, Size);
+        Allocator::Free(Data);
+    }
+
+    UPInt GetCapacity() const 
+    { 
+        return Policy.GetCapacity(); 
+    }
+
+    void ClearAndRelease()
+    {
+        Allocator::DestructArray(Data, Size);
+        Allocator::Free(Data);
+        Data = 0;
+        Size = 0;
+        Policy.SetCapacity(0);
+    }
+
+    void Reserve(UPInt newCapacity)
+    {
+        if (Policy.NeverShrinking() && newCapacity < GetCapacity())
+            return;
+
+        if (newCapacity < Policy.GetMinCapacity())
+            newCapacity = Policy.GetMinCapacity();
+
+        // Resize the buffer.
+        if (newCapacity == 0)
+        {
+            if (Data)
+            {
+                Allocator::Free(Data);
+                Data = 0;
+            }
+            Policy.SetCapacity(0);
+        }
+        else
+        {
+            UPInt gran = Policy.GetGranularity();
+            newCapacity = (newCapacity + gran - 1) / gran * gran;
+            if (Data)
+            {
+                if (Allocator::IsMovable())
+                {
+                    Data = (T*)Allocator::Realloc(Data, sizeof(T) * newCapacity);
+                }
+                else
+                {
+                    T* newData = (T*)Allocator::Alloc(sizeof(T) * newCapacity);
+                    UPInt i, s;
+                    s = (Size < newCapacity) ? Size : newCapacity;
+                    for (i = 0; i < s; ++i)
+                    {
+                        Allocator::Construct(&newData[i], Data[i]);
+                        Allocator::Destruct(&Data[i]);
+                    }
+                    for (i = s; i < Size; ++i)
+                    {
+                        Allocator::Destruct(&Data[i]);
+                    }
+                    Allocator::Free(Data);
+                    Data = newData;
+                }
+            }
+            else
+            {
+                Data = (T*)Allocator::Alloc(sizeof(T) * newCapacity);
+                //memset(Buffer, 0, (sizeof(ValueType) * newSize)); // Do we need this?
+            }
+            Policy.SetCapacity(newCapacity);
+            // OVR_ASSERT(Data); // need to throw (or something) on alloc failure!
+        }
+    }
+
+    // This version of Resize DOES NOT construct the elements.
+    // It's done to optimize PushBack, which uses a copy constructor 
+    // instead of the default constructor and assignment
+    void ResizeNoConstruct(UPInt newSize)
+    {
+        UPInt oldSize = Size;
+
+        if (newSize < oldSize)
+        {
+            Allocator::DestructArray(Data + newSize, oldSize - newSize);
+            if (newSize < (Policy.GetCapacity() >> 1))
+            {
+                Reserve(newSize);
+            }
+        }
+        else if(newSize >= Policy.GetCapacity())
+        {
+            Reserve(newSize + (newSize >> 2));
+        }
+        //! IMPORTANT to modify Size only after Reserve completes, because garbage collectable
+        // array may use this array and may traverse it during Reserve (in the case, if 
+        // collection occurs because of heap limit exceeded).
+        Size = newSize;
+    }
+
+    ValueType*  Data;
+    UPInt       Size;
+    SizePolicy  Policy;
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** ArrayData
+//
+// General purpose array data.
+// For internal use only in Array, ArrayLH, ArrayPOD and so on.
+template<class T, class Allocator, class SizePolicy>
+struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy>
+{
+    typedef T ValueType;
+    typedef Allocator                                   AllocatorType;
+    typedef SizePolicy                                  SizePolicyType;
+    typedef ArrayDataBase<T, Allocator, SizePolicy>     BaseType;
+    typedef ArrayData    <T, Allocator, SizePolicy>     SelfType;
+
+    ArrayData()
+        : BaseType() { }
+
+    ArrayData(UPInt size)
+        : BaseType() { Resize(size); }
+
+    ArrayData(const SelfType& a)
+        : BaseType(a.Policy) { Append(a.Data, a.Size); }
+
+
+    void Resize(UPInt newSize)
+    {
+        UPInt oldSize = this->Size;
+        BaseType::ResizeNoConstruct(newSize);
+        if(newSize > oldSize)
+            Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize);
+    }
+
+    void PushBack(const ValueType& val)
+    {
+        BaseType::ResizeNoConstruct(this->Size + 1);
+        Allocator::Construct(this->Data + this->Size - 1, val);
+    }
+
+    template<class S>
+    void PushBackAlt(const S& val)
+    {
+        BaseType::ResizeNoConstruct(this->Size + 1);
+        Allocator::ConstructAlt(this->Data + this->Size - 1, val);
+    }
+
+    // Append the given data to the array.
+    void Append(const ValueType other[], UPInt count)
+    {
+        if (count)
+        {
+            UPInt oldSize = this->Size;
+            BaseType::ResizeNoConstruct(this->Size + count);
+            Allocator::ConstructArray(this->Data + oldSize, count, other);
+        }
+    }
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** ArrayDataCC
+//
+// A modification of ArrayData that always copy-constructs new elements
+// using a specified DefaultValue. For internal use only in ArrayCC.
+template<class T, class Allocator, class SizePolicy>
+struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy>
+{
+    typedef T                                           ValueType;
+    typedef Allocator                                   AllocatorType;
+    typedef SizePolicy                                  SizePolicyType;
+    typedef ArrayDataBase<T, Allocator, SizePolicy>     BaseType;
+    typedef ArrayDataCC  <T, Allocator, SizePolicy>     SelfType;
+
+    ArrayDataCC(const ValueType& defval)
+        : BaseType(), DefaultValue(defval) { }
+
+    ArrayDataCC(const ValueType& defval, UPInt size)
+        : BaseType(), DefaultValue(defval) { Resize(size); }
+
+    ArrayDataCC(const SelfType& a)
+        : BaseType(a.Policy), DefaultValue(a.DefaultValue) { Append(a.Data, a.Size); }
+
+
+    void Resize(UPInt newSize)
+    {
+        UPInt oldSize = this->Size;
+        BaseType::ResizeNoConstruct(newSize);
+        if(newSize > oldSize)
+            Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize, DefaultValue);
+    }
+
+    void PushBack(const ValueType& val)
+    {
+        BaseType::ResizeNoConstruct(this->Size + 1);
+        Allocator::Construct(this->Data + this->Size - 1, val);
+    }
+
+    template<class S>
+    void PushBackAlt(const S& val)
+    {
+        BaseType::ResizeNoConstruct(this->Size + 1);
+        Allocator::ConstructAlt(this->Data + this->Size - 1, val);
+    }
+
+    // Append the given data to the array.
+    void Append(const ValueType other[], UPInt count)
+    {
+        if (count)
+        {
+            UPInt oldSize = this->Size;
+            BaseType::ResizeNoConstruct(this->Size + count);
+            Allocator::ConstructArray(this->Data + oldSize, count, other);
+        }
+    }
+
+    ValueType   DefaultValue;
+};
+
+
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** ArrayBase
+//
+// Resizable array. The behavior can be POD (suffix _POD) and 
+// Movable (no suffix) depending on the allocator policy.
+// In case of _POD the constructors and destructors are not called.
+// 
+// Arrays can't handle non-movable objects! Don't put anything in here 
+// that can't be moved around by bitwise copy. 
+// 
+// The addresses of elements are not persistent! Don't keep the address 
+// of an element; the array contents will move around as it gets resized.
+template<class ArrayData>
+class ArrayBase
+{
+public:
+    typedef typename ArrayData::ValueType       ValueType;
+    typedef typename ArrayData::AllocatorType   AllocatorType;
+    typedef typename ArrayData::SizePolicyType  SizePolicyType;
+    typedef ArrayBase<ArrayData>                SelfType;
+
+
+#undef new
+    OVR_MEMORY_REDEFINE_NEW(ArrayBase)
+// Redefine operator 'new' if necessary.
+#if defined(OVR_DEFINE_NEW)
+#define new OVR_DEFINE_NEW
+#endif
+
+
+    ArrayBase()
+        : Data() {}
+    ArrayBase(UPInt size)
+        : Data(size) {}
+    ArrayBase(const SelfType& a)
+        : Data(a.Data) {}
+
+    ArrayBase(const ValueType& defval)
+        : Data(defval) {}
+    ArrayBase(const ValueType& defval, UPInt size)
+        : Data(defval, size) {}
+  
+    SizePolicyType* GetSizePolicy() const                  { return Data.Policy; }
+    void            SetSizePolicy(const SizePolicyType& p) { Data.Policy = p; }
+
+    bool    NeverShrinking()const       { return Data.Policy.NeverShrinking(); }
+    UPInt   GetSize()       const       { return Data.Size;  }
+    bool    IsEmpty()       const       { return Data.Size == 0; }
+    UPInt   GetCapacity()   const       { return Data.GetCapacity(); }
+    UPInt   GetNumBytes()   const       { return Data.GetCapacity() * sizeof(ValueType); }
+
+    void    ClearAndRelease()           { Data.ClearAndRelease(); }
+    void    Clear()                     { Data.Resize(0); }
+    void    Resize(UPInt newSize)       { Data.Resize(newSize); }
+
+    // Reserve can only increase the capacity
+    void    Reserve(UPInt newCapacity)  
+    { 
+        if (newCapacity > Data.GetCapacity())
+            Data.Reserve(newCapacity); 
+    }
+
+    // Basic access.
+    ValueType& At(UPInt index)
+    {
+        OVR_ASSERT(index < Data.Size);
+        return Data.Data[index]; 
+    }
+    const ValueType& At(UPInt index) const
+    {
+        OVR_ASSERT(index < Data.Size);
+        return Data.Data[index]; 
+    }
+
+    ValueType ValueAt(UPInt index) const
+    {
+        OVR_ASSERT(index < Data.Size);
+        return Data.Data[index]; 
+    }
+
+    // Basic access.
+    ValueType& operator [] (UPInt index)
+    {
+        OVR_ASSERT(index < Data.Size);
+        return Data.Data[index]; 
+    }
+    const ValueType& operator [] (UPInt index) const
+    {
+        OVR_ASSERT(index < Data.Size);
+        return Data.Data[index]; 
+    }
+
+    // Raw pointer to the data. Use with caution!
+    const ValueType* GetDataPtr() const { return Data.Data; }
+          ValueType* GetDataPtr()       { return Data.Data; }
+
+    // Insert the given element at the end of the array.
+    void    PushBack(const ValueType& val)
+    {
+        // DO NOT pass elements of your own vector into
+        // push_back()!  Since we're using references,
+        // resize() may munge the element storage!
+        // OVR_ASSERT(&val < &Buffer[0] || &val > &Buffer[BufferSize]);
+        Data.PushBack(val);
+    }
+
+    template<class S>
+    void PushBackAlt(const S& val)
+    {
+        Data.PushBackAlt(val);
+    }
+
+    // Remove the last element.
+    void    PopBack(UPInt count = 1)
+    {
+        OVR_ASSERT(Data.Size >= count);
+        Data.Resize(Data.Size - count);
+    }
+
+    ValueType& PushDefault()
+    {
+        Data.PushBack(ValueType());
+        return Back();
+    }
+
+    ValueType Pop()
+    {
+        ValueType t = Back();
+        PopBack();
+        return t;
+    }
+
+
+    // Access the first element.
+    ValueType&          Front()         { return At(0); }
+    const ValueType&    Front() const   { return At(0); }
+
+    // Access the last element.
+    ValueType&          Back()          { return At(Data.Size - 1); }
+    const ValueType&    Back() const    { return At(Data.Size - 1); }
+
+    // Array copy.  Copies the contents of a into this array.
+    const SelfType& operator = (const SelfType& a)   
+    {
+        Resize(a.GetSize());
+        for (UPInt i = 0; i < Data.Size; i++) {
+            *(Data.Data + i) = a[i];
+        }
+        return *this;
+    }
+
+    // Removing multiple elements from the array.
+    void    RemoveMultipleAt(UPInt index, UPInt num)
+    {
+        OVR_ASSERT(index + num <= Data.Size);
+        if (Data.Size == num)
+        {
+            Clear();
+        }
+        else
+        {
+            AllocatorType::DestructArray(Data.Data + index, num);
+            AllocatorType::CopyArrayForward(
+                Data.Data + index, 
+                Data.Data + index + num,
+                Data.Size - num - index);
+            Data.Size -= num;
+        }
+    }
+
+    // Removing an element from the array is an expensive operation!
+    // It compacts only after removing the last element.
+    // If order of elements in the array is not important then use 
+    // RemoveAtUnordered, that could be much faster than the regular
+    // RemoveAt.
+    void    RemoveAt(UPInt index)
+    {
+        OVR_ASSERT(index < Data.Size);
+        if (Data.Size == 1)
+        {
+            Clear();
+        }
+        else
+        {
+            AllocatorType::Destruct(Data.Data + index);
+            AllocatorType::CopyArrayForward(
+                Data.Data + index, 
+                Data.Data + index + 1,
+                Data.Size - 1 - index);
+            --Data.Size;
+        }
+    }
+
+    // Removes an element from the array without respecting of original order of 
+    // elements for better performance. Do not use on array where order of elements
+    // is important, otherwise use it instead of regular RemoveAt().
+    void    RemoveAtUnordered(UPInt index)
+    {
+        OVR_ASSERT(index < Data.Size);
+        if (Data.Size == 1)
+        {
+            Clear();
+        }
+        else
+        {
+            // copy the last element into the 'index' position 
+            // and decrement the size (instead of moving all elements
+            // in [index + 1 .. size - 1] range).
+            const UPInt lastElemIndex = Data.Size - 1;
+            if (index < lastElemIndex)
+            {
+                AllocatorType::Destruct(Data.Data + index);
+                AllocatorType::Construct(Data.Data + index, Data.Data[lastElemIndex]);
+            }
+            AllocatorType::Destruct(Data.Data + lastElemIndex);
+            --Data.Size;
+        }
+    }
+
+    // Insert the given object at the given index shifting all the elements up.
+    void    InsertAt(UPInt index, const ValueType& val = ValueType())
+    {
+        OVR_ASSERT(index <= Data.Size);
+
+        Data.Resize(Data.Size + 1);
+        if (index < Data.Size - 1)
+        {
+            AllocatorType::CopyArrayBackward(
+                Data.Data + index + 1, 
+                Data.Data + index, 
+                Data.Size - 1 - index);
+        }
+        AllocatorType::Construct(Data.Data + index, val);
+    }
+
+    // Insert the given object at the given index shifting all the elements up.
+    void    InsertMultipleAt(UPInt index, UPInt num, const ValueType& val = ValueType())
+    {
+        OVR_ASSERT(index <= Data.Size);
+
+        Data.Resize(Data.Size + num);
+        if (index < Data.Size - num)
+        {
+            AllocatorType::CopyArrayBackward(
+                Data.Data + index + num,
+                Data.Data + index,
+                Data.Size - num - index);
+        }
+        for (UPInt i = 0; i < num; ++i)
+            AllocatorType::Construct(Data.Data + index + i, val);
+    }
+
+    // Append the given data to the array.
+    void    Append(const SelfType& other)
+    {
+        Append(other.Data.Data, other.GetSize());
+    }
+
+    // Append the given data to the array.
+    void    Append(const ValueType other[], UPInt count)
+    {
+        Data.Append(other, count);
+    }
+
+    class Iterator
+    {
+        SelfType*       pArray;
+        SPInt           CurIndex;
+
+    public:
+        Iterator() : pArray(0), CurIndex(-1) {}
+        Iterator(SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {}
+
+        bool operator==(const Iterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; }
+        bool operator!=(const Iterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; }
+
+        Iterator& operator++()
+        {
+            if (pArray)
+            {
+                if (CurIndex < (SPInt)pArray->GetSize())
+                    ++CurIndex;
+            }
+            return *this;
+        }
+        Iterator operator++(int)
+        {
+            Iterator it(*this);
+            operator++();
+            return it;
+        }
+        Iterator& operator--()
+        {
+            if (pArray)
+            {
+                if (CurIndex >= 0)
+                    --CurIndex;
+            }
+            return *this;
+        }
+        Iterator operator--(int)
+        {
+            Iterator it(*this);
+            operator--();
+            return it;
+        }
+        Iterator operator+(int delta) const
+        {
+            return Iterator(pArray, CurIndex + delta);
+        }
+        Iterator operator-(int delta) const
+        {
+            return Iterator(pArray, CurIndex - delta);
+        }
+        SPInt operator-(const Iterator& right) const
+        {
+            OVR_ASSERT(pArray == right.pArray);
+            return CurIndex - right.CurIndex;
+        }
+        ValueType& operator*() const    { OVR_ASSERT(pArray); return  (*pArray)[CurIndex]; }
+        ValueType* operator->() const   { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
+        ValueType* GetPtr() const       { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
+
+        bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); }
+
+        void Remove()
+        {
+            if (!IsFinished())
+                pArray->RemoveAt(CurIndex);
+        }
+
+        SPInt GetIndex() const { return CurIndex; }
+    };
+
+    Iterator Begin() { return Iterator(this); }
+    Iterator End()   { return Iterator(this, (SPInt)GetSize()); }
+    Iterator Last()  { return Iterator(this, (SPInt)GetSize() - 1); }
+
+    class ConstIterator
+    {
+        const SelfType* pArray;
+        SPInt           CurIndex;
+
+    public:
+        ConstIterator() : pArray(0), CurIndex(-1) {}
+        ConstIterator(const SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {}
+
+        bool operator==(const ConstIterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; }
+        bool operator!=(const ConstIterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; }
+
+        ConstIterator& operator++()
+        {
+            if (pArray)
+            {
+                if (CurIndex < (int)pArray->GetSize())
+                    ++CurIndex;
+            }
+            return *this;
+        }
+        ConstIterator operator++(int)
+        {
+            ConstIterator it(*this);
+            operator++();
+            return it;
+        }
+        ConstIterator& operator--()
+        {
+            if (pArray)
+            {
+                if (CurIndex >= 0)
+                    --CurIndex;
+            }
+            return *this;
+        }
+        ConstIterator operator--(int)
+        {
+            ConstIterator it(*this);
+            operator--();
+            return it;
+        }
+        ConstIterator operator+(int delta) const
+        {
+            return ConstIterator(pArray, CurIndex + delta);
+        }
+        ConstIterator operator-(int delta) const
+        {
+            return ConstIterator(pArray, CurIndex - delta);
+        }
+        SPInt operator-(const ConstIterator& right) const
+        {
+            OVR_ASSERT(pArray == right.pArray);
+            return CurIndex - right.CurIndex;
+        }
+        const ValueType& operator*() const  { OVR_ASSERT(pArray); return  (*pArray)[CurIndex]; }
+        const ValueType* operator->() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
+        const ValueType* GetPtr() const     { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
+
+        bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); }
+
+        SPInt GetIndex()  const { return CurIndex; }
+    };
+    ConstIterator Begin() const { return ConstIterator(this); }
+    ConstIterator End() const   { return ConstIterator(this, (SPInt)GetSize()); }
+    ConstIterator Last() const  { return ConstIterator(this, (SPInt)GetSize() - 1); }
+
+protected:
+    ArrayData   Data;
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Array
+//
+// General purpose array for movable objects that require explicit 
+// construction/destruction.
+template<class T, class SizePolicy=ArrayDefaultPolicy>
+class Array : public ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> >
+{
+public:
+    typedef T                                                           ValueType;
+    typedef ContainerAllocator<T>                                       AllocatorType;
+    typedef SizePolicy                                                  SizePolicyType;
+    typedef Array<T, SizePolicy>                                        SelfType;
+    typedef ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > BaseType;
+
+    Array() : BaseType() {}
+    Array(UPInt size) : BaseType(size) {}
+    Array(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
+    Array(const SelfType& a) : BaseType(a) {}
+    const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
+};
+
+// ***** ArrayPOD
+//
+// General purpose array for movable objects that DOES NOT require  
+// construction/destruction. Constructors and destructors are not called! 
+// Global heap is in use.
+template<class T, class SizePolicy=ArrayDefaultPolicy>
+class ArrayPOD : public ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> >
+{
+public:
+    typedef T                                                               ValueType;
+    typedef ContainerAllocator_POD<T>                                       AllocatorType;
+    typedef SizePolicy                                                      SizePolicyType;
+    typedef ArrayPOD<T, SizePolicy>                                         SelfType;
+    typedef ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > BaseType;
+
+    ArrayPOD() : BaseType() {}
+    ArrayPOD(UPInt size) : BaseType(size) {}
+    ArrayPOD(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
+    ArrayPOD(const SelfType& a) : BaseType(a) {}
+    const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
+};
+
+
+// ***** ArrayCPP
+//
+// General purpose, fully C++ compliant array. Can be used with non-movable data.
+// Global heap is in use.
+template<class T, class SizePolicy=ArrayDefaultPolicy>
+class ArrayCPP : public ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> >
+{
+public:
+    typedef T                                                               ValueType;
+    typedef ContainerAllocator_CPP<T>                                       AllocatorType;
+    typedef SizePolicy                                                      SizePolicyType;
+    typedef ArrayCPP<T, SizePolicy>                                         SelfType;
+    typedef ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > BaseType;
+
+    ArrayCPP() : BaseType() {}
+    ArrayCPP(UPInt size) : BaseType(size) {}
+    ArrayCPP(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
+    ArrayCPP(const SelfType& a) : BaseType(a) {}
+    const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
+};
+
+
+// ***** ArrayCC
+//
+// A modification of the array that uses the given default value to
+// construct the elements. The constructors and destructors are 
+// properly called, the objects must be movable.
+
+template<class T, class SizePolicy=ArrayDefaultPolicy>
+class ArrayCC : public ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> >
+{
+public:
+    typedef T                                                               ValueType;
+    typedef ContainerAllocator<T>                                           AllocatorType;
+    typedef SizePolicy                                                      SizePolicyType;
+    typedef ArrayCC<T, SizePolicy>                                          SelfType;
+    typedef ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> >   BaseType;
+
+    ArrayCC(const ValueType& defval) : BaseType(defval) {}
+    ArrayCC(const ValueType& defval, UPInt size) : BaseType(defval, size) {}
+    ArrayCC(const ValueType& defval, const SizePolicyType& p) : BaseType(defval) { SetSizePolicy(p); }
+    ArrayCC(const SelfType& a) : BaseType(a) {}
+    const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
+};
+
+} // OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_Atomic.cpp b/LibOVR/Src/Kernel/OVR_Atomic.cpp
new file mode 100644
index 0000000..9ea6e76
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Atomic.cpp
@@ -0,0 +1,162 @@
+/************************************************************************************
+
+Filename    :   OVR_Atomic.cpp
+Content     :   Contains atomic operations and inline fastest locking
+                functionality. Will contain #ifdefs for OS efficiency.
+                Have non-thread-safe implementation if not available.
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_Atomic.h"
+#include "OVR_Allocator.h"
+
+#ifdef OVR_ENABLE_THREADS
+
+// Include Windows 8-Metro compatible Synchronization API
+#if defined(OVR_OS_WIN32) && defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
+#include <synchapi.h>
+#endif
+
+
+namespace OVR {
+
+// ***** Windows Lock implementation
+
+#if defined(OVR_OS_WIN32)
+
+// ***** Standard Win32 Lock implementation
+
+// Constructors
+Lock::Lock(unsigned spinCount)
+{
+#if defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
+   // On Windows 8 we use InitializeCriticalSectionEx due to Metro-Compatibility
+   InitializeCriticalSectionEx(&cs, spinCount,
+                               OVR_DEBUG_SELECT(NULL, CRITICAL_SECTION_NO_DEBUG_INFO));
+#else
+    // Spin count init critical section function prototype for Window NT
+    typedef BOOL (WINAPI *Function_InitializeCriticalSectionAndSpinCount) 
+                 (LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount);
+
+
+    // Try to load function dynamically so that we don't require NT
+    // On Windows NT we will use InitializeCriticalSectionAndSpinCount
+    static  bool initTried = 0;
+    static  Function_InitializeCriticalSectionAndSpinCount pInitFn = 0;
+
+    if (!initTried)
+    {
+        HMODULE hmodule = ::LoadLibrary(OVR_STR("kernel32.dll"));
+        pInitFn     = (Function_InitializeCriticalSectionAndSpinCount)
+                      ::GetProcAddress(hmodule, "InitializeCriticalSectionAndSpinCount");
+        initTried   = true;
+    }
+
+    // Initialize the critical section
+    if (pInitFn)
+        pInitFn(&cs, spinCount);
+    else
+        ::InitializeCriticalSection(&cs);
+#endif
+   
+}
+
+
+Lock::~Lock()
+{
+    DeleteCriticalSection(&cs);
+}
+
+
+#endif
+
+
+//-------------------------------------------------------------------------------------
+// ***** SharedLock
+
+// This is a general purpose globally shared Lock implementation that should probably be
+// moved to Kernel.
+// May in theory busy spin-wait if we hit contention on first lock creation,
+// but this shouldn't matter in practice since Lock* should be cached.
+
+
+enum { LockInitMarker = 0xFFFFFFFF };
+
+Lock* SharedLock::GetLockAddRef()
+{
+    int oldUseCount;
+
+    do {
+        oldUseCount = UseCount;
+        if (oldUseCount == LockInitMarker)
+            continue;
+
+        if (oldUseCount == 0)
+        {
+            // Initialize marker
+            if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 0, LockInitMarker))
+            {
+                Construct<Lock>(Buffer);
+                do { }
+                while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 1));
+                return toLock();
+            }
+            continue;
+        }
+
+    } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount + 1));
+
+    return toLock();
+}
+
+void SharedLock::ReleaseLock(Lock* plock)
+{
+    OVR_UNUSED(plock);
+    OVR_ASSERT(plock == toLock());
+
+    int oldUseCount;
+
+    do {
+        oldUseCount = UseCount;
+        OVR_ASSERT(oldUseCount != LockInitMarker);
+
+        if (oldUseCount == 1)
+        {
+            // Initialize marker
+            if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 1, LockInitMarker))
+            {
+                Destruct<Lock>(toLock());
+
+                do { }
+                while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 0));
+
+                return;
+            }
+            continue;
+        }
+
+    } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount - 1));
+}
+
+} // OVR
+
+#endif // OVR_ENABLE_THREADS
diff --git a/LibOVR/Src/Kernel/OVR_Atomic.h b/LibOVR/Src/Kernel/OVR_Atomic.h
new file mode 100644
index 0000000..b826251
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Atomic.h
@@ -0,0 +1,890 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Atomic.h
+Content     :   Contains atomic operations and inline fastest locking
+                functionality. Will contain #ifdefs for OS efficiency.
+                Have non-thread-safe implementaion if not available.
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+#ifndef OVR_Atomic_h
+#define OVR_Atomic_h
+
+#include "OVR_Types.h"
+
+// Include System thread functionality.
+#if defined(OVR_OS_WIN32)
+#include <windows.h>
+#else
+#include <pthread.h>
+#endif
+
+
+namespace OVR {
+
+
+// ****** Declared classes
+
+// If there is NO thread support we implement AtomicOps and
+// Lock objects as no-ops. The other classes are not defined.
+template<class C> class AtomicOps;
+template<class T> class AtomicInt;
+template<class T> class AtomicPtr;
+
+class   Lock;
+
+
+//-----------------------------------------------------------------------------------
+// ***** AtomicOps
+
+// Atomic operations are provided by the AtomicOps templates class,
+// implemented through system-specific AtomicOpsRaw specializations.
+// It provides several fundamental operations such as Exchange, ExchangeAdd
+// CompareAndSet, and Store_Release. Each function includes several memory
+// synchronization versions, important for multiprocessing CPUs with weak
+// memory consistency. The following memory fencing strategies are supported:
+//
+//  - NoSync.  No memory synchronization is done for atomic op.
+//  - Release. All other memory writes are completed before atomic op
+//             writes its results.
+//  - Acquire. Further memory reads are forced to wait until atomic op
+//             executes, guaranteeing that the right values will be seen.
+//  - Sync.    A combination of Release and Acquire.
+
+
+// *** AtomicOpsRaw
+
+// AtomicOpsRaw is a specialized template that provides atomic operations 
+// used by AtomicOps. This class has two fundamental qualities: (1) it
+// defines a type T of correct size, and (2) provides operations that work
+// atomically, such as Exchange_Sync and CompareAndSet_Release.
+
+// AtomicOpsRawBase class contains shared constants/classes for AtomicOpsRaw.
+// The primary thing is does is define sync class objects, whose destructor and
+// constructor provide places to insert appropriate synchronization calls, on 
+// systems where such calls are necessary. So far, the breakdown is as follows:
+// 
+//  - X86 systems don't need custom syncs, since their exchange/atomic
+//    instructions are implicitly synchronized.
+//  - PowerPC requires lwsync/isync instructions that can use this mechanism.
+//  - If some other systems require a mechanism where syncing type is associated
+//    with a particular instruction, the default implementation (which implements
+//    all Sync, Acquire, and Release modes in terms of NoSync and fence) may not
+//    work. Ii that case it will need to be #ifdef-ed conditionally.
+
+struct AtomicOpsRawBase
+{
+#if !defined(OVR_ENABLE_THREADS) || defined(OVR_CPU_X86) || defined(OVR_OS_WIN32) || defined(OVR_OS_IPHONE)
+    // Need to have empty constructor to avoid class 'unused' variable warning.
+    struct FullSync { inline FullSync() { } };
+    struct AcquireSync { inline AcquireSync() { } };
+    struct ReleaseSync { inline ReleaseSync() { } };
+
+#elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC)
+    struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("isync\n"); } };
+    struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("isync\n"); } };
+    struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } };
+
+#elif defined(OVR_CPU_MIPS)
+    struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("sync\n"); } };
+    struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("sync\n"); } };
+    struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } };
+
+#elif defined(OVR_CPU_ARM)
+    struct FullSync { inline FullSync() { asm volatile("dmb\n"); } ~FullSync() { asm volatile("dmb\n"); } };
+    struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("dmb\n"); } };
+    struct ReleaseSync { inline ReleaseSync() { asm volatile("dmb\n"); } };
+
+
+#elif defined(OVR_CC_GNU) && (__GNUC__ >= 4)
+    // __sync functions are already full sync
+    struct FullSync { inline FullSync() { } };
+    struct AcquireSync { inline AcquireSync() { } };
+    struct ReleaseSync { inline ReleaseSync() { } };
+#endif
+};
+
+
+// 4-Byte raw data atomic op implementation class.
+struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase
+{
+#if !defined(OVR_ENABLE_THREADS)
+
+    // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl.
+    typedef UInt32 T;   
+
+    // *** Thread - Safe Atomic Versions.
+
+#elif defined(OVR_OS_WIN32)
+
+    // Use special defined for VC6, where volatile is not used and
+    // InterlockedCompareExchange is declared incorrectly.
+    typedef LONG T;      
+#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC < 1300)
+    typedef T* InterlockTPtr;
+    typedef LPVOID ET;
+    typedef ET* InterlockETPtr;
+#else
+    typedef volatile T* InterlockTPtr;
+    typedef T ET;
+    typedef InterlockTPtr InterlockETPtr;
+#endif
+    inline static T     Exchange_NoSync(volatile T* p, T val)            { return InterlockedExchange((InterlockTPtr)p, val); }
+    inline static T     ExchangeAdd_NoSync(volatile T* p, T val)         { return InterlockedExchangeAdd((InterlockTPtr)p, val); }
+    inline static bool  CompareAndSet_NoSync(volatile T* p, T c, T val)  { return InterlockedCompareExchange((InterlockETPtr)p, (ET)val, (ET)c) == (ET)c; }
+
+#elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC)
+    typedef UInt32 T;
+    static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        UInt32 ret;
+
+        asm volatile("1:\n\t"
+                     "lwarx  %[r],0,%[i]\n\t"
+                     "stwcx. %[j],0,%[i]\n\t"
+                     "bne-   1b\n"
+                     : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [j] "b" (j) : "cc", "memory");
+
+        return ret;
+    }
+
+    static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        UInt32 dummy, ret;
+
+        asm volatile("1:\n\t"
+                     "lwarx  %[r],0,%[i]\n\t"
+                     "add    %[o],%[r],%[j]\n\t"
+                     "stwcx. %[o],0,%[i]\n\t"
+                     "bne-   1b\n"
+                     : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc", "memory");
+
+        return ret;
+    }
+
+    static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
+    {
+        UInt32 ret;
+
+        asm volatile("1:\n\t"
+                     "lwarx  %[r],0,%[i]\n\t"
+                     "cmpw   0,%[r],%[cmp]\n\t"
+                     "mfcr   %[r]\n\t"
+                     "bne-   2f\n\t"
+                     "stwcx. %[val],0,%[i]\n\t"
+                     "bne-   1b\n\t"
+                     "2:\n"
+                     : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc", "memory");
+
+        return (ret & 0x20000000) ? 1 : 0;
+    }
+
+#elif defined(OVR_CPU_MIPS)
+    typedef UInt32 T;
+
+    static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        UInt32 ret;
+
+        asm volatile("1:\n\t"
+                     "ll     %[r],0(%[i])\n\t"
+                     "sc     %[j],0(%[i])\n\t"
+                     "beq    %[j],$0,1b\n\t"
+                     "nop    \n"
+                     : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory");
+
+        return ret;
+    }
+
+    static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        UInt32 ret;
+
+        asm volatile("1:\n\t"
+                     "ll     %[r],0(%[i])\n\t"
+                     "addu   %[j],%[r],%[j]\n\t"
+                     "sc     %[j],0(%[i])\n\t"
+                     "beq    %[j],$0,1b\n\t"
+                     "nop    \n"
+                     : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory");
+
+        return ret;
+    }
+
+    static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
+    {
+        UInt32 ret, dummy;
+
+        asm volatile("1:\n\t"
+                     "move   %[r],$0\n\t"
+                     "ll     %[o],0(%[i])\n\t"
+                     "bne    %[o],%[c],2f\n\t"
+                     "move   %[r],%[v]\n\t"
+                     "sc     %[r],0(%[i])\n\t"
+                     "beq    %[r],$0,1b\n\t"
+                     "nop    \n\t"
+                     "2:\n"
+                     : "+m" (*i),[r] "=&d" (ret), [o] "=&d" (dummy) : [i] "d" (i), [c] "d" (c), [v] "d" (value)
+                     : "cc", "memory");
+
+        return ret;
+    }
+
+#elif defined(OVR_CPU_ARM) && defined(OVR_CC_ARM)
+    typedef UInt32 T;
+
+    static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        for(;;)
+        {
+            T r = __ldrex(i);
+            if (__strex(j, i) == 0)
+                return r;
+        }
+    }
+    static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        for(;;)
+        {
+            T r = __ldrex(i);
+            if (__strex(r + j, i) == 0)
+                return r;
+        }
+    }
+
+    static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
+    {
+        for(;;)
+        {
+            T r = __ldrex(i);
+            if (r != c)
+                return 0;
+            if (__strex(value, i) == 0)
+                return 1;
+        }
+    }
+
+#elif defined(OVR_CPU_ARM)
+    typedef UInt32 T;
+
+    static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        UInt32 ret, dummy;
+
+        asm volatile("1:\n\t"
+            "ldrex  %[r],[%[i]]\n\t"
+            "strex  %[t],%[j],[%[i]]\n\t"
+            "cmp    %[t],#0\n\t"
+            "bne    1b\n\t"
+            : "+m" (*i), [r] "=&r" (ret), [t] "=&r" (dummy) : [i] "r" (i), [j] "r" (j) : "cc", "memory");
+
+        return ret;
+    }
+
+    static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        UInt32 ret, dummy, test;
+
+        asm volatile("1:\n\t"
+            "ldrex  %[r],[%[i]]\n\t"
+            "add    %[o],%[r],%[j]\n\t"
+            "strex  %[t],%[o],[%[i]]\n\t"
+            "cmp    %[t],#0\n\t"
+            "bne    1b\n\t"
+            : "+m" (*i), [r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test)  : [i] "r" (i), [j] "r" (j) : "cc", "memory");
+
+        return ret;
+    }
+
+    static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
+    {
+        UInt32 ret = 1, dummy, test;
+
+        asm volatile("1:\n\t"
+            "ldrex  %[o],[%[i]]\n\t"
+            "cmp    %[o],%[c]\n\t"
+            "bne    2f\n\t"
+            "strex  %[r],%[v],[%[i]]\n\t"
+            "cmp    %[r],#0\n\t"
+            "bne    1b\n\t"
+            "2:\n"
+            : "+m" (*i),[r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test) : [i] "r" (i), [c] "r" (c), [v] "r" (value)
+            : "cc", "memory");
+
+        return !ret;
+    }
+
+#elif defined(OVR_CPU_X86)
+    typedef UInt32 T;
+
+    static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        asm volatile("xchgl %1,%[i]\n"
+                     : "+m" (*i), "=q" (j) : [i] "m" (*i), "1" (j) : "cc", "memory");
+
+        return j;
+    }
+
+    static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
+    {
+        asm volatile("lock; xaddl %1,%[i]\n"
+                     : "+m" (*i), "+q" (j) : [i] "m" (*i) : "cc", "memory");
+
+        return j;
+    }
+
+    static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
+    {
+        UInt32 ret;
+
+        asm volatile("lock; cmpxchgl %[v],%[i]\n"
+                     : "+m" (*i), "=a" (ret) : [i] "m" (*i), "1" (c), [v] "q" (value) : "cc", "memory");
+
+        return (ret == c);
+    }
+
+#elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
+
+    typedef UInt32 T;
+
+    static inline T   Exchange_NoSync(volatile T *i, T j)
+    {
+        T v;
+        do {
+            v = *i;
+        } while (!__sync_bool_compare_and_swap(i, v, j));
+        return v;
+    }
+
+    static inline T   ExchangeAdd_NoSync(volatile T *i, T j)
+    {
+        return __sync_fetch_and_add(i, j);
+    }
+
+    static inline bool     CompareAndSet_NoSync(volatile T *i, T c, T value)
+    {
+        return __sync_bool_compare_and_swap(i, c, value);
+    }
+
+#endif // OS
+};
+
+
+// 8-Byte raw data data atomic op implementation class.
+// Currently implementation is provided only on systems with 64-bit pointers.
+struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase
+{    
+#if !defined(OVR_64BIT_POINTERS) || !defined(OVR_ENABLE_THREADS)
+
+    // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl.
+    typedef UInt64 T;
+
+    // *** Thread - Safe OS specific versions.
+#elif defined(OVR_OS_WIN32)
+
+    // This is only for 64-bit systems.
+    typedef LONG64      T;
+    typedef volatile T* InterlockTPtr;    
+    inline static T     Exchange_NoSync(volatile T* p, T val)            { return InterlockedExchange64((InterlockTPtr)p, val); }
+    inline static T     ExchangeAdd_NoSync(volatile T* p, T val)         { return InterlockedExchangeAdd64((InterlockTPtr)p, val); }
+    inline static bool  CompareAndSet_NoSync(volatile T* p, T c, T val)  { return InterlockedCompareExchange64((InterlockTPtr)p, val, c) == c; }
+
+#elif defined(OVR_CPU_PPC64)
+ 
+    typedef UInt64 T;
+
+    static inline UInt64   Exchange_NoSync(volatile UInt64 *i, UInt64 j)
+    {
+        UInt64 dummy, ret;
+
+        asm volatile("1:\n\t"
+                     "ldarx  %[r],0,%[i]\n\t"
+                     "mr     %[o],%[j]\n\t"
+                     "stdcx. %[o],0,%[i]\n\t"
+                     "bne-   1b\n"
+                     : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc");
+
+        return ret;
+    }
+
+    static inline UInt64   ExchangeAdd_NoSync(volatile UInt64 *i, UInt64 j)
+    {
+        UInt64 dummy, ret;
+
+        asm volatile("1:\n\t"
+                     "ldarx  %[r],0,%[i]\n\t"
+                     "add    %[o],%[r],%[j]\n\t"
+                     "stdcx. %[o],0,%[i]\n\t"
+                     "bne-   1b\n"
+                     : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc");
+
+        return ret;
+    }
+
+    static inline bool     CompareAndSet_NoSync(volatile UInt64 *i, UInt64 c, UInt64 value)
+    {
+        UInt64 ret, dummy;
+
+        asm volatile("1:\n\t"
+                     "ldarx  %[r],0,%[i]\n\t"
+                     "cmpw   0,%[r],%[cmp]\n\t"
+                     "mfcr   %[r]\n\t"
+                     "bne-   2f\n\t"
+                     "stdcx. %[val],0,%[i]\n\t"
+                     "bne-   1b\n\t"
+                     "2:\n"
+                     : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc");
+
+        return (ret & 0x20000000) ? 1 : 0;
+    }
+
+#elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
+
+    typedef UInt64 T;
+
+    static inline T   Exchange_NoSync(volatile T *i, T j)
+    {
+        T v;
+        do {
+            v = *i;
+        } while (!__sync_bool_compare_and_swap(i, v, j));
+        return v;
+    }
+
+    static inline T   ExchangeAdd_NoSync(volatile T *i, T j)
+    {
+        return __sync_fetch_and_add(i, j);
+    }
+
+    static inline bool     CompareAndSet_NoSync(volatile T *i, T c, T value)
+    {
+        return __sync_bool_compare_and_swap(i, c, value);
+    }
+
+#endif // OS
+};
+
+
+// Default implementation for AtomicOpsRaw; provides implementation of mem-fenced
+// atomic operations where fencing is done with a sync object wrapped around a NoSync
+// operation implemented in the base class. If such implementation is not possible
+// on a given platform, #ifdefs can be used to disable it and then op functions can be
+// implemented individually in the appropriate AtomicOpsRaw<size> class.
+
+template<class O>
+struct AtomicOpsRaw_DefImpl : public O
+{
+    typedef typename O::T O_T;
+    typedef typename O::FullSync    O_FullSync;
+    typedef typename O::AcquireSync O_AcquireSync;
+    typedef typename O::ReleaseSync O_ReleaseSync;
+
+    // If there is no thread support, provide the default implementation. In this case,
+    // the base class (0) must still provide the T declaration.
+#ifndef OVR_ENABLE_THREADS
+
+    // Atomic exchange of val with argument. Returns old val.
+    inline static O_T   Exchange_NoSync(volatile O_T* p, O_T val)           { O_T old = *p; *p = val; return old; }
+    // Adds a new val to argument; returns its old val.
+    inline static O_T   ExchangeAdd_NoSync(volatile O_T* p, O_T val)        { O_T old = *p; *p += val; return old; }
+    // Compares the argument data with 'c' val.
+    // If succeeded, stores val int '*p' and returns true; otherwise returns false.
+    inline static bool  CompareAndSet_NoSync(volatile O_T* p, O_T c, O_T val) { if (*p==c) { *p = val; return 1; } return 0; }
+
+#endif
+
+    // If NoSync wrapped implementation may not be possible, it this block should be
+    //  replaced with per-function implementation in O.
+    // "AtomicOpsRaw_DefImpl<O>::" prefix in calls below.
+    inline static O_T   Exchange_Sync(volatile O_T* p, O_T val)                { O_FullSync    sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); }
+    inline static O_T   Exchange_Release(volatile O_T* p, O_T val)             { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); }
+    inline static O_T   Exchange_Acquire(volatile O_T* p, O_T val)             { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::Exchange_NoSync(p, val); }  
+    inline static O_T   ExchangeAdd_Sync(volatile O_T* p, O_T val)             { O_FullSync    sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); }
+    inline static O_T   ExchangeAdd_Release(volatile O_T* p, O_T val)          { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); }
+    inline static O_T   ExchangeAdd_Acquire(volatile O_T* p, O_T val)          { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::ExchangeAdd_NoSync(p, val); }
+    inline static bool  CompareAndSet_Sync(volatile O_T* p, O_T c, O_T val)    { O_FullSync    sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); }
+    inline static bool  CompareAndSet_Release(volatile O_T* p, O_T c, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); }
+    inline static bool  CompareAndSet_Acquire(volatile O_T* p, O_T c, O_T val) { O_AcquireSync sync; OVR_UNUSED(sync); return AtomicOpsRaw_DefImpl<O>::CompareAndSet_NoSync(p,c,val); }
+
+    // Loads and stores with memory fence. These have only the relevant versions.
+#ifdef OVR_CPU_X86
+    // On X86, Store_Release is implemented as exchange. Note that we can also
+    // consider 'sfence' in the future, although it is not as compatible with older CPUs.
+    inline static void  Store_Release(volatile O_T* p, O_T val)  { Exchange_Release(p, val); }
+#else
+    inline static void  Store_Release(volatile O_T* p, O_T val)  { O_ReleaseSync sync; OVR_UNUSED(sync); *p = val; }
+#endif
+    inline static O_T   Load_Acquire(const volatile O_T* p)      { O_AcquireSync sync; OVR_UNUSED(sync); return *p; }
+};
+
+
+template<int size>
+struct AtomicOpsRaw : public AtomicOpsRawBase { };
+
+template<>
+struct AtomicOpsRaw<4> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl>
+{   
+    // Ensure that assigned type size is correct.
+    AtomicOpsRaw()
+    { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl>::T) == 4); }
+};
+template<>
+struct AtomicOpsRaw<8> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl>
+{
+    AtomicOpsRaw()
+    { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl>::T) == 8); }
+};
+
+
+// *** AtomicOps - implementation of atomic Ops for specified class
+
+// Implements atomic ops on a class, provided that the object is either
+// 4 or 8 bytes in size (depending on the AtomicOpsRaw specializations
+// available). Relies on AtomicOpsRaw for much of implementation.
+
+template<class C>
+class AtomicOps
+{
+    typedef AtomicOpsRaw<sizeof(C)>       Ops;
+    typedef typename Ops::T               T;
+    typedef volatile typename Ops::T*     PT;
+    // We cast through unions to (1) avoid pointer size compiler warnings
+    // and (2) ensure that there are no problems with strict pointer aliasing.
+    union C2T_union { C c; T t; };
+
+public:
+    // General purpose implementation for standard syncs.    
+    inline static C     Exchange_Sync(volatile C* p, C val)             { C2T_union u; u.c = val; u.t = Ops::Exchange_Sync((PT)p, u.t); return u.c; }
+    inline static C     Exchange_Release(volatile C* p, C val)          { C2T_union u; u.c = val; u.t = Ops::Exchange_Release((PT)p, u.t); return u.c; }
+    inline static C     Exchange_Acquire(volatile C* p, C val)          { C2T_union u; u.c = val; u.t = Ops::Exchange_Acquire((PT)p, u.t); return u.c; }
+    inline static C     Exchange_NoSync(volatile C* p, C val)           { C2T_union u; u.c = val; u.t = Ops::Exchange_NoSync((PT)p, u.t); return u.c; }
+    inline static C     ExchangeAdd_Sync(volatile C* p, C val)          { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Sync((PT)p, u.t); return u.c; }
+    inline static C     ExchangeAdd_Release(volatile C* p, C val)       { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Release((PT)p, u.t); return u.c; }
+    inline static C     ExchangeAdd_Acquire(volatile C* p, C val)       { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_Acquire((PT)p, u.t); return u.c; }
+    inline static C     ExchangeAdd_NoSync(volatile C* p, C val)        { C2T_union u; u.c = val; u.t = Ops::ExchangeAdd_NoSync((PT)p, u.t); return u.c; }
+    inline static bool  CompareAndSet_Sync(volatile C* p, C c, C val)   { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Sync((PT)p, cu.t, u.t); }
+    inline static bool  CompareAndSet_Release(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Release((PT)p, cu.t, u.t); }
+    inline static bool  CompareAndSet_Relse(volatile C* p, C c, C val){ C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_Acquire((PT)p, cu.t, u.t); }
+    inline static bool  CompareAndSet_NoSync(volatile C* p, C c, C val) { C2T_union u,cu; u.c = val; cu.c = c; return Ops::CompareAndSet_NoSync((PT)p, cu.t, u.t); }
+    // Loads and stores with memory fence. These have only the relevant versions.    
+    inline static void  Store_Release(volatile C* p, C val)             { C2T_union u; u.c = val; Ops::Store_Release((PT)p, u.t); }    
+    inline static C     Load_Acquire(const volatile C* p)               { C2T_union u; u.t = Ops::Load_Acquire((PT)p); return u.c; }
+};
+
+
+
+// Atomic value base class - implements operations shared for integers and pointers.
+template<class T>
+class AtomicValueBase
+{
+protected:
+    typedef AtomicOps<T> Ops;
+public:
+
+    volatile T  Value;
+
+    inline AtomicValueBase()                  { }
+    explicit inline AtomicValueBase(T val)    { Ops::Store_Release(&Value, val); }
+
+    // Most libraries (TBB and Joshua Scholar's) library do not do Load_Acquire
+    // here, since most algorithms do not require atomic loads. Needs some research.    
+    inline operator T() const { return Value; }
+
+    // *** Standard Atomic inlines
+    inline T     Exchange_Sync(T val)               { return Ops::Exchange_Sync(&Value,  val); }
+    inline T     Exchange_Release(T val)            { return Ops::Exchange_Release(&Value, val); }
+    inline T     Exchange_Acquire(T val)            { return Ops::Exchange_Acquire(&Value, val); }
+    inline T     Exchange_NoSync(T val)             { return Ops::Exchange_NoSync(&Value, val); }
+    inline bool  CompareAndSet_Sync(T c, T val)     { return Ops::CompareAndSet_Sync(&Value, c, val); }
+    inline bool  CompareAndSet_Release(T c, T val)  { return Ops::CompareAndSet_Release(&Value, c, val); }
+    inline bool  CompareAndSet_Acquire(T c, T val)  { return Ops::CompareAndSet_Relse(&Value, c, val); }
+    inline bool  CompareAndSet_NoSync(T c, T val)   { return Ops::CompareAndSet_NoSync(&Value, c, val); }
+    // Load & Store.
+    inline void  Store_Release(T val)               { Ops::Store_Release(&Value, val); }
+    inline T     Load_Acquire() const               { return Ops::Load_Acquire(&Value);  }
+};
+
+
+// ***** AtomicPtr - Atomic pointer template
+
+// This pointer class supports atomic assignments with release,
+// increment / decrement operations, and conditional compare + set.
+
+template<class T>
+class AtomicPtr : public AtomicValueBase<T*>
+{
+    typedef typename AtomicValueBase<T*>::Ops Ops;
+
+public:
+    // Initialize pointer value to 0 by default; use Store_Release only with explicit constructor.
+    inline AtomicPtr() : AtomicValueBase<T*>()                     { this->Value = 0; }
+    explicit inline AtomicPtr(T* val) : AtomicValueBase<T*>(val)   { }
+        
+    // Pointer access.
+    inline T* operator -> () const     { return this->Load_Acquire(); }
+
+    // It looks like it is convenient to have Load_Acquire characteristics
+    // for this, since that is convenient for algorithms such as linked
+    // list traversals that can be added to bu another thread.
+    inline operator T* () const        { return this->Load_Acquire(); }
+
+
+    // *** Standard Atomic inlines (applicable to pointers)
+
+    // ExhangeAdd considers pointer size for pointers.
+    template<class I>
+    inline T*     ExchangeAdd_Sync(I incr)      { return Ops::ExchangeAdd_Sync(&this->Value, ((T*)0) + incr); }
+    template<class I>
+    inline T*     ExchangeAdd_Release(I incr)   { return Ops::ExchangeAdd_Release(&this->Value, ((T*)0) + incr); }
+    template<class I>
+    inline T*     ExchangeAdd_Acquire(I incr)   { return Ops::ExchangeAdd_Acquire(&this->Value, ((T*)0) + incr); }
+    template<class I>
+    inline T*     ExchangeAdd_NoSync(I incr)    { return Ops::ExchangeAdd_NoSync(&this->Value, ((T*)0) + incr); }
+
+    // *** Atomic Operators
+
+    inline T* operator = (T* val)  { this->Store_Release(val); return val; }
+
+    template<class I>
+    inline T* operator += (I val) { return ExchangeAdd_Sync(val) + val; }
+    template<class I>
+    inline T* operator -= (I val) { return operator += (-val); }
+
+    inline T* operator ++ ()      { return ExchangeAdd_Sync(1) + 1; }
+    inline T* operator -- ()      { return ExchangeAdd_Sync(-1) - 1; }
+    inline T* operator ++ (int)   { return ExchangeAdd_Sync(1); }
+    inline T* operator -- (int)   { return ExchangeAdd_Sync(-1); }
+};
+
+
+// ***** AtomicInt - Atomic integer template
+
+// Implements an atomic integer type; the exact type to use is provided 
+// as an argument. Supports atomic Acquire / Release semantics, atomic
+// arithmetic operations, and atomic conditional compare + set.
+
+template<class T>
+class AtomicInt : public AtomicValueBase<T>
+{
+    typedef typename AtomicValueBase<T>::Ops Ops;
+
+public:
+    inline AtomicInt() : AtomicValueBase<T>()                     { }
+    explicit inline AtomicInt(T val) : AtomicValueBase<T>(val)    { }
+
+
+    // *** Standard Atomic inlines (applicable to int)   
+    inline T     ExchangeAdd_Sync(T val)            { return Ops::ExchangeAdd_Sync(&this->Value, val); }
+    inline T     ExchangeAdd_Release(T val)         { return Ops::ExchangeAdd_Release(&this->Value, val); }
+    inline T     ExchangeAdd_Acquire(T val)         { return Ops::ExchangeAdd_Acquire(&this->Value, val); }
+    inline T     ExchangeAdd_NoSync(T val)          { return Ops::ExchangeAdd_NoSync(&this->Value, val); }
+    // These increments could be more efficient because they don't return a value.
+    inline void  Increment_Sync()                   { ExchangeAdd_Sync((T)1); }
+    inline void  Increment_Release()                { ExchangeAdd_Release((T)1); }
+    inline void  Increment_Acquire()                { ExchangeAdd_Acquire((T)1); }    
+    inline void  Increment_NoSync()                 { ExchangeAdd_NoSync((T)1); }
+
+    // *** Atomic Operators
+
+    inline T operator = (T val)  { this->Store_Release(val); return val; }
+    inline T operator += (T val) { return ExchangeAdd_Sync(val) + val; }
+    inline T operator -= (T val) { return ExchangeAdd_Sync(0 - val) - val; }
+
+    inline T operator ++ ()      { return ExchangeAdd_Sync((T)1) + 1; }
+    inline T operator -- ()      { return ExchangeAdd_Sync(((T)0)-1) - 1; }
+    inline T operator ++ (int)   { return ExchangeAdd_Sync((T)1); }
+    inline T operator -- (int)   { return ExchangeAdd_Sync(((T)0)-1); }
+
+    // More complex atomic operations. Leave it to compiler whether to optimize them or not.
+    T operator &= (T arg)
+    {
+        T comp, newVal;
+        do {
+            comp   = this->Value;
+            newVal = comp & arg;
+        } while(!this->CompareAndSet_Sync(comp, newVal));
+        return newVal;
+    }
+
+    T operator |= (T arg)
+    {
+        T comp, newVal;
+        do {
+            comp   = this->Value;
+            newVal = comp | arg;
+        } while(!this->CompareAndSet_Sync(comp, newVal));
+        return newVal;
+    }
+
+    T operator ^= (T arg)
+    {
+        T comp, newVal;
+        do {
+            comp   = this->Value;
+            newVal = comp ^ arg;
+        } while(!this->CompareAndSet_Sync(comp, newVal));
+        return newVal;
+    }
+
+    T operator *= (T arg)
+    {
+        T comp, newVal;
+        do {
+            comp   = this->Value;
+            newVal = comp * arg;
+        } while(!this->CompareAndSet_Sync(comp, newVal));
+        return newVal;
+    }
+
+    T operator /= (T arg)
+    {
+        T comp, newVal;
+        do {
+            comp   = this->Value;
+            newVal = comp / arg;
+        } while(!CompareAndSet_Sync(comp, newVal));
+        return newVal;
+    }
+
+    T operator >>= (unsigned bits)
+    {
+        T comp, newVal;
+        do {
+            comp   = this->Value;
+            newVal = comp >> bits;
+        } while(!CompareAndSet_Sync(comp, newVal));
+        return newVal;
+    }
+
+    T operator <<= (unsigned bits)
+    {
+        T comp, newVal;
+        do {
+            comp   = this->Value;
+            newVal = comp << bits;
+        } while(!this->CompareAndSet_Sync(comp, newVal));
+        return newVal;
+    }
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Lock
+
+// Lock is a simplest and most efficient mutual-exclusion lock class.
+// Unlike Mutex, it cannot be waited on.
+
+class Lock
+{
+    // NOTE: Locks are not allocatable and they themselves should not allocate 
+    // memory by standard means. This is the case because StandardAllocator
+    // relies on this class.
+    // Make 'delete' private. Don't do this for 'new' since it can be redefined.  
+    void    operator delete(void*) {}
+
+
+    // *** Lock implementation for various platforms.
+    
+#if !defined(OVR_ENABLE_THREADS)
+
+public:
+    // With no thread support, lock does nothing.
+    inline Lock() { }
+    inline Lock(unsigned) { }
+    inline ~Lock() { }    
+    inline void DoLock() { }
+    inline void Unlock() { }
+
+   // Windows.   
+#elif defined(OVR_OS_WIN32)
+
+    CRITICAL_SECTION cs;
+public:   
+    Lock(unsigned spinCount = 0);      
+    ~Lock();
+    // Locking functions.
+    inline void DoLock()    { ::EnterCriticalSection(&cs); }
+    inline void Unlock()    { ::LeaveCriticalSection(&cs); }
+
+#else
+    pthread_mutex_t mutex;
+
+public:
+    static pthread_mutexattr_t RecursiveAttr;
+    static bool                RecursiveAttrInit;
+
+    Lock (unsigned dummy = 0)
+    {
+        OVR_UNUSED(dummy);
+        if (!RecursiveAttrInit)
+        {
+            pthread_mutexattr_init(&RecursiveAttr);
+            pthread_mutexattr_settype(&RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
+            RecursiveAttrInit = 1;
+        }
+        pthread_mutex_init(&mutex,&RecursiveAttr);
+    }
+    ~Lock ()                { pthread_mutex_destroy(&mutex); }
+    inline void DoLock()    { pthread_mutex_lock(&mutex); }
+    inline void Unlock()    { pthread_mutex_unlock(&mutex); }
+
+#endif // OVR_ENABLE_THREDS
+
+
+public:
+    // Locker class, used for automatic locking
+    class Locker
+    {
+    public:     
+        Lock *pLock;
+        inline Locker(Lock *plock)
+        { pLock = plock; pLock->DoLock(); }
+        inline ~Locker()
+        { pLock->Unlock();  }
+    };
+};
+
+
+//-------------------------------------------------------------------------------------
+// Globally shared Lock implementation used for MessageHandlers, etc.
+
+class SharedLock
+{    
+public:
+    SharedLock() : UseCount(0) {}
+
+    Lock* GetLockAddRef();
+    void  ReleaseLock(Lock* plock);
+   
+private:
+    Lock* toLock() { return (Lock*)Buffer; }
+
+    // UseCount and max alignment.
+    volatile int    UseCount;
+    UInt64          Buffer[(sizeof(Lock)+sizeof(UInt64)-1)/sizeof(UInt64)];
+};
+
+
+} // OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_Color.h b/LibOVR/Src/Kernel/OVR_Color.h
new file mode 100644
index 0000000..cf536da
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Color.h
@@ -0,0 +1,66 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Color.h
+Content     :   Contains color struct.
+Created     :   February 7, 2013
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+#ifndef OVR_Color_h
+#define OVR_Color_h
+
+#include "OVR_Types.h"
+
+namespace OVR {
+
+struct Color
+{
+    UByte R,G,B,A;
+
+    Color() {}
+
+    // Constructs color by channel. Alpha is set to 0xFF (fully visible)
+    // if not specified.
+    Color(unsigned char r,unsigned char g,unsigned char b, unsigned char a = 0xFF)
+        : R(r), G(g), B(b), A(a) { }
+
+    // 0xAARRGGBB - Common HTML color Hex layout
+    Color(unsigned c)
+        : R((unsigned char)(c>>16)), G((unsigned char)(c>>8)),
+        B((unsigned char)c), A((unsigned char)(c>>24)) { }
+
+    bool operator==(const Color& b) const
+    {
+        return R == b.R && G == b.G && B == b.B && A == b.A;
+    }
+
+    void  GetRGBA(float *r, float *g, float *b, float* a) const
+    {
+        *r = R / 255.0f;
+        *g = G / 255.0f;
+        *b = B / 255.0f;
+        *a = A / 255.0f;
+    }
+};
+
+}
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_ContainerAllocator.h b/LibOVR/Src/Kernel/OVR_ContainerAllocator.h
new file mode 100644
index 0000000..afc0e6a
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_ContainerAllocator.h
@@ -0,0 +1,267 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_ContainerAllocator.h
+Content     :   Template allocators and constructors for containers.
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_ContainerAllocator_h
+#define OVR_ContainerAllocator_h
+
+#include "OVR_Allocator.h"
+#include <string.h>
+
+
+namespace OVR {
+
+
+//-----------------------------------------------------------------------------------
+// ***** Container Allocator
+
+// ContainerAllocator serves as a template argument for allocations done by
+// containers, such as Array and Hash; replacing it could allow allocator
+// substitution in containers.
+
+class ContainerAllocatorBase
+{
+public:
+    static void* Alloc(UPInt size)                { return OVR_ALLOC(size); }
+    static void* Realloc(void* p, UPInt newSize)  { return OVR_REALLOC(p, newSize); }
+    static void  Free(void *p)                    { OVR_FREE(p); }
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Constructors, Destructors, Copiers
+
+// Plain Old Data - movable, no special constructors/destructor.
+template<class T> 
+class ConstructorPOD
+{
+public:
+    static void Construct(void *) {}
+    static void Construct(void *p, const T& source) 
+    { 
+        *(T*)p = source;
+    }
+
+    // Same as above, but allows for a different type of constructor.
+    template <class S> 
+    static void ConstructAlt(void *p, const S& source)
+    {
+        *(T*)p = source;
+    }
+
+    static void ConstructArray(void*, UPInt) {}
+
+    static void ConstructArray(void* p, UPInt count, const T& source)
+    {
+        UByte *pdata = (UByte*)p;
+        for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
+            *(T*)pdata = source;
+    }
+
+    static void ConstructArray(void* p, UPInt count, const T* psource)
+    {
+        memcpy(p, psource, sizeof(T) * count);
+    }
+
+    static void Destruct(T*) {}
+    static void DestructArray(T*, UPInt) {}
+
+    static void CopyArrayForward(T* dst, const T* src, UPInt count)
+    {
+        memmove(dst, src, count * sizeof(T));
+    }
+
+    static void CopyArrayBackward(T* dst, const T* src, UPInt count)
+    {
+        memmove(dst, src, count * sizeof(T));
+    }
+
+    static bool IsMovable() { return true; }
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** ConstructorMov
+//
+// Correct C++ construction and destruction for movable objects
+template<class T> 
+class ConstructorMov
+{
+public:
+    static void Construct(void* p) 
+    { 
+        OVR::Construct<T>(p);
+    }
+
+    static void Construct(void* p, const T& source) 
+    { 
+        OVR::Construct<T>(p, source);
+    }
+
+    // Same as above, but allows for a different type of constructor.
+    template <class S> 
+    static void ConstructAlt(void* p, const S& source)
+    {
+        OVR::ConstructAlt<T,S>(p, source);
+    }
+
+    static void ConstructArray(void* p, UPInt count)
+    {
+        UByte* pdata = (UByte*)p;
+        for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
+            Construct(pdata);
+    }
+
+    static void ConstructArray(void* p, UPInt count, const T& source)
+    {
+        UByte* pdata = (UByte*)p;
+        for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
+            Construct(pdata, source);
+    }
+
+    static void ConstructArray(void* p, UPInt count, const T* psource)
+    {
+        UByte* pdata = (UByte*)p;
+        for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
+            Construct(pdata, *psource++);
+    }
+
+    static void Destruct(T* p)
+    {
+        p->~T();
+        OVR_UNUSED(p); // Suppress silly MSVC warning
+    }
+
+    static void DestructArray(T* p, UPInt count)
+    {   
+        p += count - 1;
+        for (UPInt i=0; i<count; ++i, --p)
+            p->~T();
+    }
+
+    static void CopyArrayForward(T* dst, const T* src, UPInt count)
+    {
+        memmove(dst, src, count * sizeof(T));
+    }
+
+    static void CopyArrayBackward(T* dst, const T* src, UPInt count)
+    {
+        memmove(dst, src, count * sizeof(T));
+    }
+
+    static bool IsMovable() { return true; }
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** ConstructorCPP
+//
+// Correct C++ construction and destruction for movable objects
+template<class T> 
+class ConstructorCPP
+{
+public:
+    static void Construct(void* p) 
+    { 
+        OVR::Construct<T>(p);        
+    }
+
+    static void Construct(void* p, const T& source) 
+    { 
+        OVR::Construct<T>(p, source);        
+    }
+
+    // Same as above, but allows for a different type of constructor.
+    template <class S> 
+    static void ConstructAlt(void* p, const S& source)
+    {
+        OVR::ConstructAlt<T,S>(p, source);        
+    }
+
+    static void ConstructArray(void* p, UPInt count)
+    {
+        UByte* pdata = (UByte*)p;
+        for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
+            Construct(pdata);
+    }
+
+    static void ConstructArray(void* p, UPInt count, const T& source)
+    {
+        UByte* pdata = (UByte*)p;
+        for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
+            Construct(pdata, source);
+    }
+
+    static void ConstructArray(void* p, UPInt count, const T* psource)
+    {
+        UByte* pdata = (UByte*)p;
+        for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
+            Construct(pdata, *psource++);
+    }
+
+    static void Destruct(T* p)
+    {
+        p->~T();
+        OVR_UNUSED(p); // Suppress silly MSVC warning
+    }
+
+    static void DestructArray(T* p, UPInt count)
+    {   
+        p += count - 1;
+        for (UPInt i=0; i<count; ++i, --p)
+            p->~T();
+    }
+
+    static void CopyArrayForward(T* dst, const T* src, UPInt count)
+    {
+        for(UPInt i = 0; i < count; ++i)
+            dst[i] = src[i];
+    }
+
+    static void CopyArrayBackward(T* dst, const T* src, UPInt count)
+    {
+        for(UPInt i = count; i; --i)
+            dst[i-1] = src[i-1];
+    }
+
+    static bool IsMovable() { return false; }
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** Container Allocator with movement policy
+//
+// Simple wraps as specialized allocators
+template<class T> struct ContainerAllocator_POD : ContainerAllocatorBase, ConstructorPOD<T> {};
+template<class T> struct ContainerAllocator     : ContainerAllocatorBase, ConstructorMov<T> {};
+template<class T> struct ContainerAllocator_CPP : ContainerAllocatorBase, ConstructorCPP<T> {};
+
+
+} // OVR
+
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_Deque.h b/LibOVR/Src/Kernel/OVR_Deque.h
new file mode 100644
index 0000000..ca242ad
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Deque.h
@@ -0,0 +1,296 @@
+/************************************************************************************
+
+Filename    :   OVR_Deque.h
+Content     :   Deque container
+Created     :   Nov. 15, 2013
+Authors     :   Dov Katz
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Deque_h
+#define OVR_Deque_h
+
+namespace OVR{ 
+
+template <class Elem>
+class Deque
+{
+public:
+    enum
+    {
+        DefaultCapacity = 500
+    };
+
+    Deque(int capacity = DefaultCapacity);
+    virtual ~Deque(void);
+
+    virtual void         PushBack   (const Elem &Item);    // Adds Item to the end
+    virtual void         PushFront  (const Elem &Item);    // Adds Item to the beginning
+    virtual Elem         PopBack    (void);                // Removes Item from the end
+    virtual Elem         PopFront   (void);                // Removes Item from the beginning
+    virtual const Elem&  PeekBack   (int count = 0) const; // Returns count-th Item from the end
+    virtual const Elem&  PeekFront  (int count = 0) const; // Returns count-th Item from the beginning
+
+	virtual inline UPInt GetSize    (void)          const; // Returns Number of Elements
+    virtual inline UPInt GetCapacity(void)          const; // Returns the maximum possible number of elements
+    virtual void         Clear      (void);				   // Remove all elements
+    virtual inline bool  IsEmpty    ()              const;
+    virtual inline bool  IsFull     ()              const;
+
+protected:
+    Elem        *Data;          // The actual Data array
+    const int   Capacity;       // Deque capacity
+    int         Beginning;      // Index of the first element
+    int         End;            // Index of the next after last element
+
+    // Instead of calculating the number of elements, using this variable
+    // is much more convenient.
+    int         ElemCount;
+
+private:
+    Deque&      operator= (const Deque& q) { }; // forbidden
+    Deque(const Deque<Elem> &OtherDeque) { };
+};
+
+template <class Elem>
+class InPlaceMutableDeque : public Deque<Elem>
+{
+public:
+    InPlaceMutableDeque( int capacity = Deque<Elem>::DefaultCapacity ) : Deque<Elem>( capacity ) {}
+	virtual ~InPlaceMutableDeque() {};
+
+    using Deque<Elem>::PeekBack;
+    using Deque<Elem>::PeekFront;
+	virtual Elem& PeekBack  (int count = 0); // Returns count-th Item from the end
+	virtual Elem& PeekFront (int count = 0); // Returns count-th Item from the beginning
+};
+
+// Same as Deque, but allows to write more elements than maximum capacity
+// Old elements are lost as they are overwritten with the new ones
+template <class Elem>
+class CircularBuffer : public InPlaceMutableDeque<Elem>
+{
+public:
+    CircularBuffer(int MaxSize = Deque<Elem>::DefaultCapacity) : InPlaceMutableDeque<Elem>(MaxSize) { };
+
+    // The following methods are inline as a workaround for a VS bug causing erroneous C4505 warnings
+    // See: http://stackoverflow.com/questions/3051992/compiler-warning-at-c-template-base-class
+    inline virtual void PushBack  (const Elem &Item);    // Adds Item to the end, overwriting the oldest element at the beginning if necessary
+    inline virtual void PushFront (const Elem &Item);    // Adds Item to the beginning, overwriting the oldest element at the end if necessary
+};
+
+//----------------------------------------------------------------------------------
+
+// Deque Constructor function
+template <class Elem>
+Deque<Elem>::Deque(int capacity) :
+Capacity( capacity ), Beginning(0), End(0), ElemCount(0)
+{
+    Data = (Elem*) OVR_ALLOC(Capacity * sizeof(Elem));
+    ConstructArray<Elem>(Data, Capacity);
+}
+
+// Deque Destructor function
+template <class Elem>
+Deque<Elem>::~Deque(void)
+{
+    DestructArray<Elem>(Data, Capacity);
+    OVR_FREE(Data);
+}
+
+template <class Elem>
+void Deque<Elem>::Clear()
+{
+    Beginning = 0;
+    End       = 0;
+    ElemCount = 0;
+
+    DestructArray<Elem>(Data, Capacity);
+    ConstructArray<Elem>(Data, Capacity);
+}
+
+// Push functions
+template <class Elem>
+void Deque<Elem>::PushBack(const Elem &Item)
+{
+    // Error Check: Make sure we aren't  
+    // exceeding our maximum storage space
+    OVR_ASSERT( ElemCount < Capacity );
+
+    Data[ End++ ] = Item;
+    ++ElemCount;
+
+    // Check for wrap-around
+    if (End >= Capacity)
+        End -= Capacity;
+}
+
+template <class Elem>
+void Deque<Elem>::PushFront(const Elem &Item)
+{
+    // Error Check: Make sure we aren't  
+    // exceeding our maximum storage space
+    OVR_ASSERT( ElemCount < Capacity );
+
+    Beginning--;
+    // Check for wrap-around
+    if (Beginning < 0)
+        Beginning += Capacity;
+
+    Data[ Beginning ] = Item;
+    ++ElemCount;
+}
+
+// Pop functions
+template <class Elem>
+Elem Deque<Elem>::PopFront(void)
+{
+    // Error Check: Make sure we aren't reading from an empty Deque
+    OVR_ASSERT( ElemCount > 0 );
+
+	Elem ReturnValue = Data[ Beginning ];
+    Destruct<Elem>(&Data[ Beginning ]);
+    Construct<Elem>(&Data[ Beginning ]);
+
+	++Beginning;
+    --ElemCount;
+
+    // Check for wrap-around
+    if (Beginning >= Capacity)
+        Beginning -= Capacity;
+
+    return ReturnValue;
+}
+
+template <class Elem>
+Elem Deque<Elem>::PopBack(void)
+{
+    // Error Check: Make sure we aren't reading from an empty Deque
+    OVR_ASSERT( ElemCount > 0 );
+
+    End--;
+    --ElemCount;
+
+    // Check for wrap-around
+    if (End < 0)
+        End += Capacity;
+
+    Elem ReturnValue = Data[ End ];
+    Destruct<Elem>(&Data[ End ]);
+    Construct<Elem>(&Data[ End ]);
+
+    return ReturnValue;
+}
+
+// Peek functions
+template <class Elem>
+const Elem& Deque<Elem>::PeekFront(int count) const
+{
+    // Error Check: Make sure we aren't reading from an empty Deque
+    OVR_ASSERT( ElemCount > count );
+
+    int idx = Beginning + count;
+    if (idx >= Capacity)
+        idx -= Capacity;
+    return Data[ idx ];
+}
+
+template <class Elem>
+const Elem& Deque<Elem>::PeekBack(int count) const
+{
+    // Error Check: Make sure we aren't reading from an empty Deque
+    OVR_ASSERT( ElemCount > count );
+
+    int idx = End - count - 1;
+    if (idx < 0)
+        idx += Capacity;
+    return Data[ idx ];
+}
+
+// Mutable Peek functions
+template <class Elem>
+Elem& InPlaceMutableDeque<Elem>::PeekFront(int count)
+{
+    // Error Check: Make sure we aren't reading from an empty Deque
+    OVR_ASSERT( Deque<Elem>::ElemCount > count );
+
+    int idx = Deque<Elem>::Beginning + count;
+    if (idx >= Deque<Elem>::Capacity)
+        idx -= Deque<Elem>::Capacity;
+    return Deque<Elem>::Data[ idx ];
+}
+
+template <class Elem>
+Elem& InPlaceMutableDeque<Elem>::PeekBack(int count)
+{
+    // Error Check: Make sure we aren't reading from an empty Deque
+    OVR_ASSERT( Deque<Elem>::ElemCount > count );
+
+    int idx = Deque<Elem>::End - count - 1;
+    if (idx < 0)
+        idx += Deque<Elem>::Capacity;
+    return Deque<Elem>::Data[ idx ];
+}
+
+template <class Elem>
+inline UPInt Deque<Elem>::GetCapacity(void) const
+{
+    return Deque<Elem>::Capacity;
+}
+
+template <class Elem>
+inline UPInt Deque<Elem>::GetSize(void) const
+{
+    return Deque<Elem>::ElemCount;
+}
+
+template <class Elem>
+inline bool Deque<Elem>::IsEmpty(void) const
+{
+    return Deque<Elem>::ElemCount==0;
+}
+
+template <class Elem>
+inline bool Deque<Elem>::IsFull(void) const
+{
+    return Deque<Elem>::ElemCount==Deque<Elem>::Capacity;
+}
+
+// ******* CircularBuffer<Elem> *******
+// Push functions
+template <class Elem>
+void CircularBuffer<Elem>::PushBack(const Elem &Item)
+{
+    if (this->IsFull())
+        this->PopFront();
+    Deque<Elem>::PushBack(Item);
+}
+
+template <class Elem>
+void CircularBuffer<Elem>::PushFront(const Elem &Item)
+{
+    if (this->IsFull())
+        this->PopBack();
+    Deque<Elem>::PushFront(Item);
+}
+
+};   
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_File.cpp b/LibOVR/Src/Kernel/OVR_File.cpp
new file mode 100644
index 0000000..31ab516
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_File.cpp
@@ -0,0 +1,582 @@
+/**************************************************************************
+
+Filename    :   OVR_File.cpp
+Content     :   File wrapper class implementation (Win32)
+
+Created     :   April 5, 1999
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+**************************************************************************/
+
+#define  GFILE_CXX
+
+// Standard C library (Captain Obvious guarantees!)
+#include <stdio.h>
+
+#include "OVR_File.h"
+
+namespace OVR {
+
+// Buffered file adds buffering to an existing file
+// FILEBUFFER_SIZE defines the size of internal buffer, while
+// FILEBUFFER_TOLERANCE controls the amount of data we'll effectively try to buffer
+#define FILEBUFFER_SIZE         (8192-8)
+#define FILEBUFFER_TOLERANCE    4096
+
+// ** Constructor/Destructor
+
+// Hidden constructor
+// Not supposed to be used
+BufferedFile::BufferedFile() : DelegatedFile(0)
+{
+    pBuffer     = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE);
+    BufferMode  = NoBuffer;
+    FilePos     = 0;
+    Pos         = 0;
+    DataSize    = 0;
+}
+
+// Takes another file as source
+BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile)
+{
+    pBuffer     = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE);
+    BufferMode  = NoBuffer;
+    FilePos     = pfile->LTell();
+    Pos         = 0;
+    DataSize    = 0;
+}
+
+
+// Destructor
+BufferedFile::~BufferedFile()
+{
+    // Flush in case there's data
+    if (pFile)
+        FlushBuffer();
+    // Get rid of buffer
+    if (pBuffer)
+        OVR_FREE(pBuffer);
+}
+
+/*
+bool    BufferedFile::VCopy(const Object &source)
+{
+    if (!DelegatedFile::VCopy(source))
+        return 0;
+
+    // Data members
+    BufferedFile *psource = (BufferedFile*)&source;
+
+    // Buffer & the mode it's in
+    pBuffer         = psource->pBuffer;
+    BufferMode      = psource->BufferMode;
+    Pos             = psource->Pos;
+    DataSize        = psource->DataSize;
+    return 1;
+}
+*/
+
+// Initializes buffering to a certain mode
+bool    BufferedFile::SetBufferMode(BufferModeType mode)
+{
+    if (!pBuffer)
+        return false;
+    if (mode == BufferMode)
+        return true;
+     
+    FlushBuffer();
+
+    // Can't set write mode if we can't write
+    if ((mode==WriteBuffer) && (!pFile || !pFile->IsWritable()) )
+        return 0;
+
+    // And SetMode
+    BufferMode = mode;
+    Pos        = 0;
+    DataSize   = 0;
+    return 1;
+}
+
+// Flushes buffer
+void    BufferedFile::FlushBuffer()
+{
+    switch(BufferMode)
+    {
+        case WriteBuffer:
+            // Write data in buffer
+            FilePos += pFile->Write(pBuffer,Pos);
+            Pos = 0;
+            break;
+
+        case ReadBuffer:
+            // Seek back & reset buffer data
+            if ((DataSize-Pos)>0)
+                FilePos = pFile->LSeek(-(int)(DataSize-Pos), Seek_Cur);
+            DataSize = 0;
+            Pos      = 0;
+            break;
+        default:
+            // not handled!
+            break;
+    }
+}
+
+// Reloads data for ReadBuffer
+void    BufferedFile::LoadBuffer()
+{
+    if (BufferMode == ReadBuffer)
+    {
+        // We should only reload once all of pre-loaded buffer is consumed.
+        OVR_ASSERT(Pos == DataSize);
+
+        // WARNING: Right now LoadBuffer() assumes the buffer's empty
+        int sz   = pFile->Read(pBuffer,FILEBUFFER_SIZE);
+        DataSize = sz<0 ? 0 : (unsigned)sz;
+        Pos      = 0;
+        FilePos  += DataSize;
+    }
+}
+
+
+// ** Overridden functions
+
+// We override all the functions that can possibly
+// require buffer mode switch, flush, or extra calculations
+
+// Tell() requires buffer adjustment
+int     BufferedFile::Tell()
+{
+    if (BufferMode == ReadBuffer)
+        return int (FilePos - DataSize + Pos);
+
+    int pos = pFile->Tell();
+    // Adjust position based on buffer mode & data
+    if (pos!=-1)
+    {
+        OVR_ASSERT(BufferMode != ReadBuffer);
+        if (BufferMode == WriteBuffer)
+            pos += Pos;
+    }
+    return pos;
+}
+
+SInt64  BufferedFile::LTell()
+{
+    if (BufferMode == ReadBuffer)
+        return FilePos - DataSize + Pos;
+
+    SInt64 pos = pFile->LTell();
+    if (pos!=-1)
+    {
+        OVR_ASSERT(BufferMode != ReadBuffer);
+        if (BufferMode == WriteBuffer)
+            pos += Pos;
+    }
+    return pos;
+}
+
+int     BufferedFile::GetLength()
+{
+    int len = pFile->GetLength();
+    // If writing through buffer, file length may actually be bigger
+    if ((len!=-1) && (BufferMode==WriteBuffer))
+    {
+        int currPos = pFile->Tell() + Pos;
+        if (currPos>len)
+            len = currPos;
+    }
+    return len;
+}
+SInt64  BufferedFile::LGetLength()
+{
+    SInt64 len = pFile->LGetLength();
+    // If writing through buffer, file length may actually be bigger
+    if ((len!=-1) && (BufferMode==WriteBuffer))
+    {
+        SInt64 currPos = pFile->LTell() + Pos;
+        if (currPos>len)
+            len = currPos;
+    }
+    return len;
+}
+
+/*
+bool    BufferedFile::Stat(FileStats *pfs)
+{
+    // Have to fix up length is stat
+    if (pFile->Stat(pfs))
+    {
+        if (BufferMode==WriteBuffer)
+        {
+            SInt64 currPos = pFile->LTell() + Pos;
+            if (currPos > pfs->Size)
+            {
+                pfs->Size   = currPos;
+                // ??
+                pfs->Blocks = (pfs->Size+511) >> 9;
+            }
+        }
+        return 1;
+    }
+    return 0;
+}
+*/
+
+int     BufferedFile::Write(const UByte *psourceBuffer, int numBytes)
+{
+    if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer))
+    {
+        // If not data space in buffer, flush
+        if ((FILEBUFFER_SIZE-(int)Pos)<numBytes)
+        {
+            FlushBuffer();
+            // If bigger then tolerance, just write directly
+            if (numBytes>FILEBUFFER_TOLERANCE)
+            {
+                int sz = pFile->Write(psourceBuffer,numBytes);
+                if (sz > 0)
+                    FilePos += sz;
+                return sz;
+            }
+        }
+
+        // Enough space in buffer.. so copy to it
+        memcpy(pBuffer+Pos, psourceBuffer, numBytes);
+        Pos += numBytes;
+        return numBytes;
+    }
+    int sz = pFile->Write(psourceBuffer,numBytes);
+    if (sz > 0)
+        FilePos += sz;
+    return sz;
+}
+
+int     BufferedFile::Read(UByte *pdestBuffer, int numBytes)
+{
+    if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer))
+    {
+        // Data in buffer... copy it
+        if ((int)(DataSize-Pos) >= numBytes)
+        {
+            memcpy(pdestBuffer, pBuffer+Pos, numBytes);
+            Pos += numBytes;
+            return numBytes;
+        }
+
+        // Not enough data in buffer, copy buffer
+        int     readBytes = DataSize-Pos;
+        memcpy(pdestBuffer, pBuffer+Pos, readBytes);
+        numBytes    -= readBytes;
+        pdestBuffer += readBytes;
+        Pos = DataSize;
+
+        // Don't reload buffer if more then tolerance
+        // (No major advantage, and we don't want to write a loop)
+        if (numBytes>FILEBUFFER_TOLERANCE)
+        {
+            numBytes = pFile->Read(pdestBuffer,numBytes);
+            if (numBytes > 0)
+            {
+                FilePos += numBytes;
+                Pos = DataSize = 0;
+            }
+            return readBytes + ((numBytes==-1) ? 0 : numBytes);
+        }
+
+        // Reload the buffer
+        // WARNING: Right now LoadBuffer() assumes the buffer's empty
+        LoadBuffer();
+        if ((int)(DataSize-Pos) < numBytes)
+            numBytes = (int)DataSize-Pos;
+
+        memcpy(pdestBuffer, pBuffer+Pos, numBytes);
+        Pos += numBytes;
+        return numBytes + readBytes;
+        
+        /*
+        // Alternative Read implementation. The one above is probably better
+        // due to FILEBUFFER_TOLERANCE.
+        int     total = 0;
+
+        do {
+            int     bufferBytes = (int)(DataSize-Pos);
+            int     copyBytes = (bufferBytes > numBytes) ? numBytes : bufferBytes;
+
+            memcpy(pdestBuffer, pBuffer+Pos, copyBytes);
+            numBytes    -= copyBytes;
+            pdestBuffer += copyBytes;
+            Pos         += copyBytes;
+            total       += copyBytes;
+
+            if (numBytes == 0)
+                break;
+            LoadBuffer();
+
+        } while (DataSize > 0);
+
+        return total;
+        */     
+    }
+    int sz = pFile->Read(pdestBuffer,numBytes);
+    if (sz > 0)
+        FilePos += sz;
+    return sz;
+}
+
+
+int     BufferedFile::SkipBytes(int numBytes)
+{
+    int skippedBytes = 0;
+
+    // Special case for skipping a little data in read buffer
+    if (BufferMode==ReadBuffer)
+    {
+        skippedBytes = (((int)DataSize-(int)Pos) >= numBytes) ? numBytes : (DataSize-Pos);
+        Pos          += skippedBytes;
+        numBytes     -= skippedBytes;
+    }
+
+    if (numBytes)
+    {
+        numBytes = pFile->SkipBytes(numBytes);
+        // Make sure we return the actual number skipped, or error
+        if (numBytes!=-1)
+        {
+            skippedBytes += numBytes;
+            FilePos += numBytes;
+            Pos = DataSize = 0;
+        }
+        else if (skippedBytes <= 0)
+            skippedBytes = -1;
+    }
+    return skippedBytes;
+}
+
+int     BufferedFile::BytesAvailable()
+{
+    int available = pFile->BytesAvailable();
+    // Adjust available size based on buffers
+    switch(BufferMode)
+    {
+        case ReadBuffer:
+            available += DataSize-Pos;
+            break;
+        case WriteBuffer:
+            available -= Pos;
+            if (available<0)
+                available= 0;
+            break;
+        default:
+            break;
+    }
+    return available;
+}
+
+bool    BufferedFile::Flush()
+{
+    FlushBuffer();
+    return pFile->Flush();
+}
+
+// Seeking could be optimized better..
+int     BufferedFile::Seek(int offset, int origin)
+{    
+    if (BufferMode == ReadBuffer)
+    {
+        if (origin == Seek_Cur)
+        {
+            // Seek can fall either before or after Pos in the buffer,
+            // but it must be within bounds.
+            if (((unsigned(offset) + Pos)) <= DataSize)
+            {
+                Pos += offset;
+                return int (FilePos - DataSize + Pos);
+            }
+
+            // Lightweight buffer "Flush". We do this to avoid an extra seek
+            // back operation which would take place if we called FlushBuffer directly.
+            origin = Seek_Set;
+            OVR_ASSERT(((FilePos - DataSize + Pos) + (UInt64)offset) < ~(UInt64)0);
+            offset = (int)(FilePos - DataSize + Pos) + offset;
+            Pos = DataSize = 0;
+        }
+        else if (origin == Seek_Set)
+        {
+            if (((unsigned)offset - (FilePos-DataSize)) <= DataSize)
+            {
+                OVR_ASSERT((FilePos-DataSize) < ~(UInt64)0);
+                Pos = (unsigned)offset - (unsigned)(FilePos-DataSize);
+                return offset;
+            }
+            Pos = DataSize = 0;
+        }
+        else
+        {
+            FlushBuffer();
+        }
+    }
+    else
+    {
+        FlushBuffer();
+    }    
+
+    /*
+    // Old Seek Logic
+    if (origin == Seek_Cur && offset + Pos < DataSize)
+    {
+        //OVR_ASSERT((FilePos - DataSize) >= (FilePos - DataSize + Pos + offset));
+        Pos += offset;
+        OVR_ASSERT(int (Pos) >= 0);
+        return int (FilePos - DataSize + Pos);
+    }
+    else if (origin == Seek_Set && unsigned(offset) >= FilePos - DataSize && unsigned(offset) < FilePos)
+    {
+        Pos = unsigned(offset - FilePos + DataSize);
+        OVR_ASSERT(int (Pos) >= 0);
+        return int (FilePos - DataSize + Pos);
+    }   
+    
+    FlushBuffer();
+    */
+
+
+    FilePos = pFile->Seek(offset,origin);
+    return int (FilePos);
+}
+
+SInt64  BufferedFile::LSeek(SInt64 offset, int origin)
+{
+    if (BufferMode == ReadBuffer)
+    {
+        if (origin == Seek_Cur)
+        {
+            // Seek can fall either before or after Pos in the buffer,
+            // but it must be within bounds.
+            if (((unsigned(offset) + Pos)) <= DataSize)
+            {
+                Pos += (unsigned)offset;
+                return SInt64(FilePos - DataSize + Pos);
+            }
+
+            // Lightweight buffer "Flush". We do this to avoid an extra seek
+            // back operation which would take place if we called FlushBuffer directly.
+            origin = Seek_Set;            
+            offset = (SInt64)(FilePos - DataSize + Pos) + offset;
+            Pos = DataSize = 0;
+        }
+        else if (origin == Seek_Set)
+        {
+            if (((UInt64)offset - (FilePos-DataSize)) <= DataSize)
+            {                
+                Pos = (unsigned)((UInt64)offset - (FilePos-DataSize));
+                return offset;
+            }
+            Pos = DataSize = 0;
+        }
+        else
+        {
+            FlushBuffer();
+        }
+    }
+    else
+    {
+        FlushBuffer();
+    }
+
+/*
+    OVR_ASSERT(BufferMode != NoBuffer);
+
+    if (origin == Seek_Cur && offset + Pos < DataSize)
+    {
+        Pos += int (offset);
+        return FilePos - DataSize + Pos;
+    }
+    else if (origin == Seek_Set && offset >= SInt64(FilePos - DataSize) && offset < SInt64(FilePos))
+    {
+        Pos = unsigned(offset - FilePos + DataSize);
+        return FilePos - DataSize + Pos;
+    }
+
+    FlushBuffer();
+    */
+
+    FilePos = pFile->LSeek(offset,origin);
+    return FilePos;
+}
+
+int     BufferedFile::CopyFromStream(File *pstream, int byteSize)
+{
+    // We can't rely on overridden Write()
+    // because delegation doesn't override virtual pointers
+    // So, just re-implement
+    UByte   buff[0x4000];
+    int     count = 0;
+    int     szRequest, szRead, szWritten;
+
+    while(byteSize)
+    {
+        szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
+
+        szRead    = pstream->Read(buff,szRequest);
+        szWritten = 0;
+        if (szRead > 0)
+            szWritten = Write(buff,szRead);
+
+        count   +=szWritten;
+        byteSize-=szWritten;
+        if (szWritten < szRequest)
+            break;
+    }
+    return count;
+}
+
+// Closing files
+bool    BufferedFile::Close()
+{
+    switch(BufferMode)
+    {
+        case WriteBuffer:
+            FlushBuffer();
+            break;
+        case ReadBuffer:
+            // No need to seek back on close
+            BufferMode = NoBuffer;
+            break;
+        default:
+            break;
+    }
+    return pFile->Close();
+}
+
+
+// ***** Global path helpers
+
+// Find trailing short filename in a path.
+const char* OVR_CDECL GetShortFilename(const char* purl)
+{    
+    UPInt len = OVR_strlen(purl);
+    for (UPInt i=len; i>0; i--) 
+        if (purl[i]=='\\' || purl[i]=='/')
+            return purl+i+1;
+    return purl;
+}
+
+} // OVR
+
diff --git a/LibOVR/Src/Kernel/OVR_File.h b/LibOVR/Src/Kernel/OVR_File.h
new file mode 100644
index 0000000..a8dc615
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_File.h
@@ -0,0 +1,529 @@
+/************************************************************************************
+
+PublicHeader:   Kernel
+Filename    :   OVR_File.h
+Content     :   Header for all internal file management - functions and structures
+                to be inherited by OS specific subclasses.
+Created     :   September 19, 2012
+Notes       : 
+
+Notes       :   errno may not be preserved across use of BaseFile member functions
+            :   Directories cannot be deleted while files opened from them are in use
+                (For the GetFullName function)
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_File_h
+#define OVR_File_h
+
+#include "OVR_RefCount.h"
+#include "OVR_Std.h"
+#include "OVR_Alg.h"
+
+#include <stdio.h>
+#include "OVR_String.h"
+
+namespace OVR {
+
+// ***** Declared classes
+class   FileConstants;
+class   File;
+class   DelegatedFile;
+class   BufferedFile;
+
+
+// ***** Flags for File & Directory accesses
+
+class FileConstants
+{
+public:
+
+    // *** File open flags
+    enum OpenFlags
+    {
+        Open_Read       = 1,
+        Open_Write      = 2,
+        Open_ReadWrite  = 3,
+
+        // Opens file and truncates it to zero length
+        // - file must have write permission
+        // - when used with Create, it opens an existing 
+        //   file and empties it or creates a new file
+        Open_Truncate   = 4,
+
+        // Creates and opens new file 
+        // - does not erase contents if file already
+        //   exists unless combined with Truncate
+        Open_Create     = 8,
+
+         // Returns an error value if the file already exists
+        Open_CreateOnly = 24,
+
+        // Open file with buffering
+        Open_Buffered    = 32
+    };
+
+    // *** File Mode flags
+    enum Modes
+    {
+        Mode_Read       = 0444,
+        Mode_Write      = 0222,
+        Mode_Execute    = 0111,
+
+        Mode_ReadWrite  = 0666
+    };
+
+    // *** Seek operations
+    enum SeekOps
+    {
+        Seek_Set        = 0,
+        Seek_Cur        = 1,
+        Seek_End        = 2
+    };
+
+    // *** Errors
+    enum Errors
+    {
+        Error_FileNotFound  = 0x1001,
+        Error_Access        = 0x1002,
+        Error_IOError       = 0x1003,
+        Error_DiskFull      = 0x1004
+    };
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** File Class
+
+// The pure virtual base random-access file
+// This is a base class to all files
+
+class File : public RefCountBase<File>, public FileConstants
+{   
+public:
+    File() { }
+    // ** Location Information
+
+    // Returns a file name path relative to the 'reference' directory
+    // This is often a path that was used to create a file
+    // (this is not a global path, global path can be obtained with help of directory)
+    virtual const char* GetFilePath() = 0;
+                                                                                        
+
+    // ** File Information
+
+    // Return 1 if file's usable (open)
+    virtual bool        IsValid() = 0;
+    // Return 1 if file's writable, otherwise 0                                         
+    virtual bool        IsWritable() = 0;
+                                                                                        
+    // Return position
+    virtual int         Tell() = 0;
+    virtual SInt64      LTell() = 0;
+    
+    // File size                                                                        
+    virtual int         GetLength() = 0;
+    virtual SInt64      LGetLength() = 0;
+                                                                                        
+    // Returns file stats                                                               
+    // 0 for failure                                                                    
+    //virtual bool      Stat(FileStats *pfs) = 0;
+                                                                                        
+    // Return errno-based error code                                                    
+    // Useful if any other function failed                                              
+    virtual int         GetErrorCode() = 0;
+                                                                                        
+                                                                                        
+    // ** Stream implementation & I/O
+
+    // Blocking write, will write in the given number of bytes to the stream
+    // Returns : -1 for error
+    //           Otherwise number of bytes read 
+    virtual int         Write(const UByte *pbufer, int numBytes) = 0;
+    // Blocking read, will read in the given number of bytes or less from the stream
+    // Returns : -1 for error
+    //           Otherwise number of bytes read,
+    //           if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed
+    virtual int         Read(UByte *pbufer, int numBytes) = 0;
+
+    // Skips (ignores) a given # of bytes
+    // Same return values as Read
+    virtual int         SkipBytes(int numBytes) = 0;
+        
+    // Returns the number of bytes available to read from a stream without blocking
+    // For a file, this should generally be number of bytes to the end
+    virtual int         BytesAvailable() = 0;
+
+    // Causes any implementation's buffered data to be delivered to destination
+    // Return 0 for error
+    virtual bool        Flush() = 0;
+                                                                                            
+
+    // Need to provide a more optimized implementation that doe snot necessarily involve a lot of seeking
+    inline bool         IsEOF() { return !BytesAvailable(); }
+    
+
+    // Seeking                                                                              
+    // Returns new position, -1 for error                                                   
+    virtual int         Seek(int offset, int origin=Seek_Set) = 0;
+    virtual SInt64      LSeek(SInt64 offset, int origin=Seek_Set) = 0;
+    // Seek simplification
+    int                 SeekToBegin()           {return Seek(0); }
+    int                 SeekToEnd()             {return Seek(0,Seek_End); }
+    int                 Skip(int numBytes)     {return Seek(numBytes,Seek_Cur); }
+                        
+
+    // Appends other file data from a stream
+    // Return -1 for error, else # of bytes written
+    virtual int         CopyFromStream(File *pstream, int byteSize) = 0;
+
+    // Closes the file
+    // After close, file cannot be accessed 
+    virtual bool        Close() = 0;
+
+
+    // ***** Inlines for convenient primitive type serialization
+
+    // Read/Write helpers
+private:
+    UInt64  PRead64()           { UInt64 v = 0; Read((UByte*)&v, 8); return v; }
+    UInt32  PRead32()           { UInt32 v = 0; Read((UByte*)&v, 4); return v; }
+    UInt16  PRead16()           { UInt16 v = 0; Read((UByte*)&v, 2); return v; }
+    UByte   PRead8()            { UByte  v = 0; Read((UByte*)&v, 1); return v; }
+    void    PWrite64(UInt64 v)  { Write((UByte*)&v, 8); }
+    void    PWrite32(UInt32 v)  { Write((UByte*)&v, 4); }
+    void    PWrite16(UInt16 v)  { Write((UByte*)&v, 2); }
+    void    PWrite8(UByte v)    { Write((UByte*)&v, 1); }
+
+public:
+
+    // Writing primitive types - Little Endian
+    inline void    WriteUByte(UByte v)         { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v));     }
+    inline void    WriteSByte(SByte v)         { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v));     }
+    inline void    WriteUInt8(UByte v)         { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v));     }
+    inline void    WriteSInt8(SByte v)         { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v));     }
+    inline void    WriteUInt16(UInt16 v)       { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v));   }
+    inline void    WriteSInt16(SInt16 v)       { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v));   }
+    inline void    WriteUInt32(UInt32 v)       { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v));   }
+    inline void    WriteSInt32(SInt32 v)       { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v));   }
+    inline void    WriteUInt64(UInt64 v)       { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v));   }
+    inline void    WriteSInt64(SInt64 v)       { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v));   }
+    inline void    WriteFloat(float v)         { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 4); } 
+    inline void    WriteDouble(double v)       { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 8); }
+    // Writing primitive types - Big Endian
+    inline void    WriteUByteBE(UByte v)       { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v));     }
+    inline void    WriteSByteBE(SByte v)       { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v));     }
+    inline void    WriteUInt8BE(UInt16 v)      { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v));     }
+    inline void    WriteSInt8BE(SInt16 v)      { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v));     }
+    inline void    WriteUInt16BE(UInt16 v)     { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v));   }
+    inline void    WriteSInt16BE(UInt16 v)     { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v));   }
+    inline void    WriteUInt32BE(UInt32 v)     { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v));   }
+    inline void    WriteSInt32BE(UInt32 v)     { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v));   }
+    inline void    WriteUInt64BE(UInt64 v)     { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v));   }
+    inline void    WriteSInt64BE(UInt64 v)     { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v));   }
+    inline void    WriteFloatBE(float v)       { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 4); }
+    inline void    WriteDoubleBE(double v)     { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 8); }
+        
+    // Reading primitive types - Little Endian
+    inline UByte   ReadUByte()                 { return (UByte)Alg::ByteUtil::LEToSystem(PRead8());    }
+    inline SByte   ReadSByte()                 { return (SByte)Alg::ByteUtil::LEToSystem(PRead8());    }
+    inline UByte   ReadUInt8()                 { return (UByte)Alg::ByteUtil::LEToSystem(PRead8());    }
+    inline SByte   ReadSInt8()                 { return (SByte)Alg::ByteUtil::LEToSystem(PRead8());    }
+    inline UInt16  ReadUInt16()                { return (UInt16)Alg::ByteUtil::LEToSystem(PRead16());  }
+    inline SInt16  ReadSInt16()                { return (SInt16)Alg::ByteUtil::LEToSystem(PRead16());  }
+    inline UInt32  ReadUInt32()                { return (UInt32)Alg::ByteUtil::LEToSystem(PRead32());  }
+    inline SInt32  ReadSInt32()                { return (SInt32)Alg::ByteUtil::LEToSystem(PRead32());  }
+    inline UInt64  ReadUInt64()                { return (UInt64)Alg::ByteUtil::LEToSystem(PRead64());  }
+    inline SInt64  ReadSInt64()                { return (SInt64)Alg::ByteUtil::LEToSystem(PRead64());  }
+    inline float   ReadFloat()                 { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::LEToSystem(v); }
+    inline double  ReadDouble()                { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::LEToSystem(v); }
+    // Reading primitive types - Big Endian
+    inline UByte   ReadUByteBE()               { return (UByte)Alg::ByteUtil::BEToSystem(PRead8());    }
+    inline SByte   ReadSByteBE()               { return (SByte)Alg::ByteUtil::BEToSystem(PRead8());    }
+    inline UByte   ReadUInt8BE()               { return (UByte)Alg::ByteUtil::BEToSystem(PRead8());    }
+    inline SByte   ReadSInt8BE()               { return (SByte)Alg::ByteUtil::BEToSystem(PRead8());    }
+    inline UInt16  ReadUInt16BE()              { return (UInt16)Alg::ByteUtil::BEToSystem(PRead16());  }
+    inline SInt16  ReadSInt16BE()              { return (SInt16)Alg::ByteUtil::BEToSystem(PRead16());  }
+    inline UInt32  ReadUInt32BE()              { return (UInt32)Alg::ByteUtil::BEToSystem(PRead32());  }
+    inline SInt32  ReadSInt32BE()              { return (SInt32)Alg::ByteUtil::BEToSystem(PRead32());  }
+    inline UInt64  ReadUInt64BE()              { return (UInt64)Alg::ByteUtil::BEToSystem(PRead64());  }
+    inline SInt64  ReadSInt64BE()              { return (SInt64)Alg::ByteUtil::BEToSystem(PRead64());  }
+    inline float   ReadFloatBE()               { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::BEToSystem(v); }
+    inline double  ReadDoubleBE()              { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::BEToSystem(v); }
+};
+
+
+// *** Delegated File
+
+class DelegatedFile : public File
+{
+protected:
+    // Delegating file pointer
+    Ptr<File>     pFile;
+
+    // Hidden default constructor
+    DelegatedFile() : pFile(0)                             { }
+    DelegatedFile(const DelegatedFile &source) : File()    { OVR_UNUSED(source); }
+public:
+    // Constructors
+    DelegatedFile(File *pfile) : pFile(pfile)     { }
+
+    // ** Location Information  
+    virtual const char* GetFilePath()                               { return pFile->GetFilePath(); }    
+
+    // ** File Information                                                      
+    virtual bool        IsValid()                                   { return pFile && pFile->IsValid(); }   
+    virtual bool        IsWritable()                                { return pFile->IsWritable(); }
+//  virtual bool        IsRecoverable()                             { return pFile->IsRecoverable(); }          
+                                                                    
+    virtual int         Tell()                                      { return pFile->Tell(); }
+    virtual SInt64      LTell()                                     { return pFile->LTell(); }
+    
+    virtual int         GetLength()                                 { return pFile->GetLength(); }
+    virtual SInt64      LGetLength()                                { return pFile->LGetLength(); }
+    
+    //virtual bool      Stat(FileStats *pfs)                        { return pFile->Stat(pfs); }
+    
+    virtual int         GetErrorCode()                              { return pFile->GetErrorCode(); }
+    
+    // ** Stream implementation & I/O
+    virtual int         Write(const UByte *pbuffer, int numBytes)   { return pFile->Write(pbuffer,numBytes); }  
+    virtual int         Read(UByte *pbuffer, int numBytes)          { return pFile->Read(pbuffer,numBytes); }   
+    
+    virtual int         SkipBytes(int numBytes)                     { return pFile->SkipBytes(numBytes); }      
+    
+    virtual int         BytesAvailable()                            { return pFile->BytesAvailable(); } 
+    
+    virtual bool        Flush()                                     { return pFile->Flush(); }
+                                                                    
+    // Seeking                                                      
+    virtual int         Seek(int offset, int origin=Seek_Set)       { return pFile->Seek(offset,origin); }
+    virtual SInt64      LSeek(SInt64 offset, int origin=Seek_Set)   { return pFile->LSeek(offset,origin); }
+
+    virtual int         CopyFromStream(File *pstream, int byteSize) { return pFile->CopyFromStream(pstream,byteSize); }
+                        
+    // Closing the file 
+    virtual bool        Close()                                     { return pFile->Close(); }    
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** Buffered File
+
+// This file class adds buffering to an existing file
+// Buffered file never fails by itself; if there's not
+// enough memory for buffer, no buffer's used
+
+class BufferedFile : public DelegatedFile
+{   
+protected:  
+    enum BufferModeType
+    {
+        NoBuffer,
+        ReadBuffer,
+        WriteBuffer
+    };
+
+    // Buffer & the mode it's in
+    UByte*          pBuffer;
+    BufferModeType  BufferMode;
+    // Position in buffer
+    unsigned        Pos;
+    // Data in buffer if reading
+    unsigned        DataSize;
+    // Underlying file position 
+    UInt64          FilePos;
+
+    // Initializes buffering to a certain mode
+    bool    SetBufferMode(BufferModeType mode);
+    // Flushes buffer
+    // WriteBuffer - write data to disk, ReadBuffer - reset buffer & fix file position  
+    void    FlushBuffer();
+    // Loads data into ReadBuffer
+    // WARNING: Right now LoadBuffer() assumes the buffer's empty
+    void    LoadBuffer();
+
+    // Hidden constructor
+    BufferedFile();
+    inline BufferedFile(const BufferedFile &source) : DelegatedFile() { OVR_UNUSED(source); }
+public:
+
+    // Constructor
+    // - takes another file as source
+    BufferedFile(File *pfile);
+    ~BufferedFile();
+    
+    
+    // ** Overridden functions
+
+    // We override all the functions that can possibly
+    // require buffer mode switch, flush, or extra calculations
+    virtual int         Tell();
+    virtual SInt64      LTell();
+
+    virtual int         GetLength();
+    virtual SInt64      LGetLength();
+
+//  virtual bool        Stat(GFileStats *pfs);  
+
+    virtual int         Write(const UByte *pbufer, int numBytes);
+    virtual int         Read(UByte *pbufer, int numBytes);
+
+    virtual int         SkipBytes(int numBytes);
+
+    virtual int         BytesAvailable();
+
+    virtual bool        Flush();
+
+    virtual int         Seek(int offset, int origin=Seek_Set);
+    virtual SInt64      LSeek(SInt64 offset, int origin=Seek_Set);
+
+    virtual int         CopyFromStream(File *pstream, int byteSize);
+    
+    virtual bool        Close();    
+};                          
+
+
+//-----------------------------------------------------------------------------------
+// ***** Memory File
+
+class MemoryFile : public File
+{
+public:
+
+    const char* GetFilePath()       { return FilePath.ToCStr(); }
+
+    bool        IsValid()           { return Valid; }
+    bool        IsWritable()        { return false; }
+
+    bool        Flush()             { return true; }
+    int         GetErrorCode()      { return 0; }
+
+    int         Tell()              { return FileIndex; }
+    SInt64      LTell()             { return (SInt64) FileIndex; }
+
+    int         GetLength()         { return FileSize; }
+    SInt64      LGetLength()        { return (SInt64) FileSize; }
+
+    bool        Close()
+    {
+        Valid = false;
+        return false;
+    }
+
+    int         CopyFromStream(File *pstream, int byteSize)
+    {   OVR_UNUSED2(pstream, byteSize);
+        return 0;
+    }
+
+    int         Write(const UByte *pbuffer, int numBytes)
+    {   OVR_UNUSED2(pbuffer, numBytes);
+        return 0;
+    }
+
+    int         Read(UByte *pbufer, int numBytes)
+    {
+        if (FileIndex + numBytes > FileSize)
+        {
+            numBytes = FileSize - FileIndex;
+        }
+
+        if (numBytes > 0)
+        {
+            ::memcpy (pbufer, &FileData [FileIndex], numBytes);
+
+            FileIndex += numBytes;
+        }
+
+        return numBytes;
+    }
+
+    int         SkipBytes(int numBytes)
+    {
+        if (FileIndex + numBytes > FileSize)
+        {
+            numBytes = FileSize - FileIndex;
+        }
+
+        FileIndex += numBytes;
+
+        return numBytes;
+    }
+
+    int         BytesAvailable()
+    {
+        return (FileSize - FileIndex);
+    }
+
+    int         Seek(int offset, int origin = Seek_Set)
+    {
+        switch (origin)
+        {
+        case Seek_Set : FileIndex  = offset;               break;
+        case Seek_Cur : FileIndex += offset;               break;
+        case Seek_End : FileIndex  = FileSize - offset;  break;
+        }
+
+        return FileIndex;
+    }
+
+    SInt64      LSeek(SInt64 offset, int origin = Seek_Set)
+    {
+        return (SInt64) Seek((int) offset, origin);
+    }
+
+public:
+
+    MemoryFile (const String& fileName, const UByte *pBuffer, int buffSize)
+        : FilePath(fileName)
+    {
+        FileData  = pBuffer;
+        FileSize  = buffSize;
+        FileIndex = 0;
+        Valid     = (!fileName.IsEmpty() && pBuffer && buffSize > 0) ? true : false;
+    }
+
+    // pfileName should be encoded as UTF-8 to support international file names.
+    MemoryFile (const char* pfileName, const UByte *pBuffer, int buffSize)
+        : FilePath(pfileName)
+    {
+        FileData  = pBuffer;
+        FileSize  = buffSize;
+        FileIndex = 0;
+        Valid     = (pfileName && pBuffer && buffSize > 0) ? true : false;
+    }
+private:
+
+    String       FilePath;
+    const UByte *FileData;
+    int          FileSize;
+    int          FileIndex;
+    bool         Valid;
+};
+
+
+// ***** Global path helpers
+
+// Find trailing short filename in a path.
+const char* OVR_CDECL GetShortFilename(const char* purl);
+
+} // OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_FileFILE.cpp b/LibOVR/Src/Kernel/OVR_FileFILE.cpp
new file mode 100644
index 0000000..8478086
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_FileFILE.cpp
@@ -0,0 +1,595 @@
+/**************************************************************************
+
+Filename    :   OVR_FileFILE.cpp
+Content     :   File wrapper class implementation (Win32)
+
+Created     :   April 5, 1999
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+**************************************************************************/
+
+#define  GFILE_CXX
+
+#include "OVR_Types.h"
+#include "OVR_Log.h"
+
+// Standard C library (Captain Obvious guarantees!)
+#include <stdio.h>
+#ifndef OVR_OS_WINCE
+#include <sys/stat.h>
+#endif
+
+#include "OVR_SysFile.h"
+
+#ifndef OVR_OS_WINCE
+#include <errno.h>
+#endif
+
+namespace OVR {
+
+// ***** File interface
+
+// ***** FILEFile - C streams file
+
+static int SFerror ()
+{
+    if (errno == ENOENT)
+        return FileConstants::Error_FileNotFound;
+    else if (errno == EACCES || errno == EPERM)
+        return FileConstants::Error_Access;
+    else if (errno == ENOSPC)
+        return FileConstants::Error_DiskFull;
+    else
+        return FileConstants::Error_IOError;
+};
+
+#ifdef OVR_OS_WIN32
+#include "windows.h"
+// A simple helper class to disable/enable system error mode, if necessary
+// Disabling happens conditionally only if a drive name is involved
+class SysErrorModeDisabler
+{
+    BOOL    Disabled;
+    UINT    OldMode;
+public:
+    SysErrorModeDisabler(const char* pfileName)
+    {
+        if (pfileName && (pfileName[0]!=0) && pfileName[1]==':')
+        {
+            Disabled = 1;
+            OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
+        }
+        else
+            Disabled = 0;
+    }
+
+    ~SysErrorModeDisabler()
+    {
+        if (Disabled) ::SetErrorMode(OldMode);
+    }
+};
+#else
+class SysErrorModeDisabler
+{
+public:
+    SysErrorModeDisabler(const char* pfileName) { OVR_UNUSED(pfileName); }
+};
+#endif // OVR_OS_WIN32
+
+
+// This macro enables verification of I/O results after seeks against a pre-loaded
+// full file buffer copy. This is generally not necessary, but can been used to debug
+// memory corruptions; we've seen this fail due to EAX2/DirectSound corrupting memory
+// under FMOD with XP64 (32-bit) and Realtek HA Audio driver.
+//#define GFILE_VERIFY_SEEK_ERRORS
+
+
+// This is the simplest possible file implementation, it wraps around the descriptor
+// This file is delegated to by SysFile.
+
+class FILEFile : public File
+{
+protected:
+
+    // Allocated filename
+    String      FileName;
+
+    // File handle & open mode
+    bool        Opened;
+    FILE*       fs;
+    int         OpenFlags;
+    // Error code for last request
+    int         ErrorCode;
+
+    int         LastOp;
+
+#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
+    UByte*      pFileTestBuffer;
+    unsigned    FileTestLength;
+    unsigned    TestPos; // File pointer position during tests.
+#endif
+
+public:
+
+    FILEFile()
+    {
+        Opened = 0; FileName = "";
+
+#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
+        pFileTestBuffer =0;
+        FileTestLength  =0;
+        TestPos         =0;
+#endif
+    }
+    // Initialize file by opening it
+    FILEFile(const String& fileName, int flags, int Mode);
+    // The 'pfileName' should be encoded as UTF-8 to support international file names.
+    FILEFile(const char* pfileName, int flags, int Mode);
+
+    ~FILEFile()
+    {
+        if (Opened)
+            Close();
+    }
+
+    virtual const char* GetFilePath();
+
+    // ** File Information
+    virtual bool        IsValid();
+    virtual bool        IsWritable();
+
+    // Return position / file size
+    virtual int         Tell();
+    virtual SInt64      LTell();
+    virtual int         GetLength();
+    virtual SInt64      LGetLength();
+
+//  virtual bool        Stat(FileStats *pfs);
+    virtual int         GetErrorCode();
+
+    // ** Stream implementation & I/O
+    virtual int         Write(const UByte *pbuffer, int numBytes);
+    virtual int         Read(UByte *pbuffer, int numBytes);
+    virtual int         SkipBytes(int numBytes);
+    virtual int         BytesAvailable();
+    virtual bool        Flush();
+    virtual int         Seek(int offset, int origin);
+    virtual SInt64      LSeek(SInt64 offset, int origin);
+    
+    virtual int         CopyFromStream(File *pStream, int byteSize);
+    virtual bool        Close();    
+private:
+    void                init();
+};
+
+
+// Initialize file by opening it
+FILEFile::FILEFile(const String& fileName, int flags, int mode)
+  : FileName(fileName), OpenFlags(flags)
+{
+    OVR_UNUSED(mode);
+    init();
+}
+
+// The 'pfileName' should be encoded as UTF-8 to support international file names.
+FILEFile::FILEFile(const char* pfileName, int flags, int mode)
+  : FileName(pfileName), OpenFlags(flags)
+{
+    OVR_UNUSED(mode);
+    init();
+}
+
+void FILEFile::init()
+{
+    // Open mode for file's open
+    const char *omode = "rb";
+
+    if (OpenFlags & Open_Truncate)
+    {
+        if (OpenFlags & Open_Read)
+            omode = "w+b";
+        else
+            omode = "wb";
+    }
+    else if (OpenFlags & Open_Create)
+    {
+        if (OpenFlags & Open_Read)
+            omode = "a+b";
+        else
+            omode = "ab";
+    }
+    else if (OpenFlags & Open_Write)
+        omode = "r+b";
+
+#ifdef OVR_OS_WIN32
+    SysErrorModeDisabler disabler(FileName.ToCStr());
+#endif
+
+#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
+    wchar_t womode[16];
+    wchar_t *pwFileName = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(FileName.ToCStr())+1) * sizeof(wchar_t));
+    UTF8Util::DecodeString(pwFileName, FileName.ToCStr());
+    OVR_ASSERT(strlen(omode) < sizeof(womode)/sizeof(womode[0]));
+    UTF8Util::DecodeString(womode, omode);
+    _wfopen_s(&fs, pwFileName, womode);
+    OVR_FREE(pwFileName);
+#else
+    fs = fopen(FileName.ToCStr(), omode);
+#endif
+    if (fs)
+        rewind (fs);
+    Opened = (fs != NULL);
+    // Set error code
+    if (!Opened)
+        ErrorCode = SFerror();
+    else
+    {
+        // If we are testing file seek correctness, pre-load the entire file so
+        // that we can do comparison tests later.
+#ifdef OVR_FILE_VERIFY_SEEK_ERRORS        
+        TestPos         = 0;
+        fseek(fs, 0, SEEK_END);
+        FileTestLength  = ftell(fs);
+        fseek(fs, 0, SEEK_SET);
+        pFileTestBuffer = (UByte*)OVR_ALLOC(FileTestLength);
+        if (pFileTestBuffer)
+        {
+            OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength));
+            Seek(0, Seek_Set);
+        }        
+#endif
+
+        ErrorCode = 0;
+    }
+    LastOp = 0;
+}
+
+
+const char* FILEFile::GetFilePath()
+{
+    return FileName.ToCStr();
+}
+
+
+// ** File Information
+bool    FILEFile::IsValid()
+{
+    return Opened;
+}
+bool    FILEFile::IsWritable()
+{
+    return IsValid() && (OpenFlags&Open_Write);
+}
+/*
+bool    FILEFile::IsRecoverable()
+{
+    return IsValid() && ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC);
+}
+*/
+
+// Return position / file size
+int     FILEFile::Tell()
+{
+    int pos = (int)ftell (fs);
+    if (pos < 0)
+        ErrorCode = SFerror();
+    return pos;
+}
+
+SInt64  FILEFile::LTell()
+{
+    SInt64 pos = ftell(fs);
+    if (pos < 0)
+        ErrorCode = SFerror();
+    return pos;
+}
+
+int     FILEFile::GetLength()
+{
+    int pos = Tell();
+    if (pos >= 0)
+    {
+        Seek (0, Seek_End);
+        int size = Tell();
+        Seek (pos, Seek_Set);
+        return size;
+    }
+    return -1;
+}
+SInt64  FILEFile::LGetLength()
+{
+    SInt64 pos = LTell();
+    if (pos >= 0)
+    {
+        LSeek (0, Seek_End);
+        SInt64 size = LTell();
+        LSeek (pos, Seek_Set);
+        return size;
+    }
+    return -1;
+}
+
+int     FILEFile::GetErrorCode()
+{
+    return ErrorCode;
+}
+
+// ** Stream implementation & I/O
+int     FILEFile::Write(const UByte *pbuffer, int numBytes)
+{
+    if (LastOp && LastOp != Open_Write)
+        fflush(fs);
+    LastOp = Open_Write;
+    int written = (int) fwrite(pbuffer, 1, numBytes, fs);
+    if (written < numBytes)
+        ErrorCode = SFerror();
+
+#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
+    if (written > 0)
+        TestPos += written;
+#endif
+
+    return written;
+}
+
+int     FILEFile::Read(UByte *pbuffer, int numBytes)
+{
+    if (LastOp && LastOp != Open_Read)
+        fflush(fs);
+    LastOp = Open_Read;
+    int read = (int) fread(pbuffer, 1, numBytes, fs);
+    if (read < numBytes)
+        ErrorCode = SFerror();
+
+#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
+    if (read > 0)
+    {
+        // Read-in data must match our pre-loaded buffer data!
+        UByte* pcompareBuffer = pFileTestBuffer + TestPos;
+        for (int i=0; i< read; i++)
+        {
+            OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]);
+        }
+
+        //OVR_ASSERT(!memcmp(pFileTestBuffer + TestPos, pbuffer, read));
+        TestPos += read;
+        OVR_ASSERT(ftell(fs) == (int)TestPos);
+    }
+#endif
+
+    return read;
+}
+
+// Seeks ahead to skip bytes
+int     FILEFile::SkipBytes(int numBytes)
+{
+    SInt64 pos    = LTell();
+    SInt64 newPos = LSeek(numBytes, Seek_Cur);
+
+    // Return -1 for major error
+    if ((pos==-1) || (newPos==-1))
+    {
+        return -1;
+    }
+    //ErrorCode = ((NewPos-Pos)<numBytes) ? errno : 0;
+
+    return int (newPos-(int)pos);
+}
+
+// Return # of bytes till EOF
+int     FILEFile::BytesAvailable()
+{
+    SInt64 pos    = LTell();
+    SInt64 endPos = LGetLength();
+
+    // Return -1 for major error
+    if ((pos==-1) || (endPos==-1))
+    {
+        ErrorCode = SFerror();
+        return 0;
+    }
+    else
+        ErrorCode = 0;
+
+    return int (endPos-(int)pos);
+}
+
+// Flush file contents
+bool    FILEFile::Flush()
+{
+    return !fflush(fs);
+}
+
+int     FILEFile::Seek(int offset, int origin)
+{
+    int newOrigin = 0;
+    switch(origin)
+    {
+    case Seek_Set: newOrigin = SEEK_SET; break;
+    case Seek_Cur: newOrigin = SEEK_CUR; break;
+    case Seek_End: newOrigin = SEEK_END; break;
+    }
+
+    if (newOrigin == SEEK_SET && offset == Tell())
+        return Tell();
+
+    if (fseek (fs, offset, newOrigin))
+    {
+#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
+        OVR_ASSERT(0);
+#endif
+        return -1;
+    }
+    
+#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
+    // Track file position after seeks for read verification later.
+    switch(origin)
+    {
+    case Seek_Set:  TestPos = offset;       break;
+    case Seek_Cur:  TestPos += offset;      break;    
+    case Seek_End:  TestPos = FileTestLength + offset; break;
+    }
+    OVR_ASSERT((int)TestPos == Tell());
+#endif
+
+    return (int)Tell();
+}
+
+SInt64  FILEFile::LSeek(SInt64 offset, int origin)
+{
+    return Seek((int)offset,origin);
+}
+
+int FILEFile::CopyFromStream(File *pstream, int byteSize)
+{
+    UByte   buff[0x4000];
+    int     count = 0;
+    int     szRequest, szRead, szWritten;
+
+    while (byteSize)
+    {
+        szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
+
+        szRead    = pstream->Read(buff, szRequest);
+        szWritten = 0;
+        if (szRead > 0)
+            szWritten = Write(buff, szRead);
+
+        count    += szWritten;
+        byteSize -= szWritten;
+        if (szWritten < szRequest)
+            break;
+    }
+    return count;
+}
+
+
+bool FILEFile::Close()
+{
+#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
+    if (pFileTestBuffer)
+    {
+        OVR_FREE(pFileTestBuffer);
+        pFileTestBuffer = 0;
+        FileTestLength  = 0;
+    }
+#endif
+
+    bool closeRet = !fclose(fs);
+
+    if (!closeRet)
+    {
+        ErrorCode = SFerror();
+        return 0;
+    }
+    else
+    {
+        Opened    = 0;
+        fs        = 0;
+        ErrorCode = 0;
+    }
+
+    // Handle safe truncate
+    /*
+    if ((OpenFlags & OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
+    {
+        // Delete original file (if it existed)
+        DWORD oldAttributes = FileUtilWin32::GetFileAttributes(FileName);
+        if (oldAttributes!=0xFFFFFFFF)
+            if (!FileUtilWin32::DeleteFile(FileName))
+            {
+                // Try to remove the readonly attribute
+                FileUtilWin32::SetFileAttributes(FileName, oldAttributes & (~FILE_ATTRIBUTE_READONLY) );
+                // And delete the file again
+                if (!FileUtilWin32::DeleteFile(FileName))
+                    return 0;
+            }
+
+        // Rename temp file to real filename
+        if (!FileUtilWin32::MoveFile(TempName, FileName))
+        {
+            //ErrorCode = errno;
+            return 0;
+        }
+    }
+    */
+    return 1;
+}
+
+/*
+bool    FILEFile::CloseCancel()
+{
+    bool closeRet = (bool)::CloseHandle(fd);
+
+    if (!closeRet)
+    {
+        //ErrorCode = errno;
+        return 0;
+    }
+    else
+    {
+        Opened    = 0;
+        fd        = INVALID_HANDLE_VALUE;
+        ErrorCode = 0;
+    }
+
+    // Handle safe truncate (delete tmp file, leave original unchanged)
+    if ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
+        if (!FileUtilWin32::DeleteFile(TempName))
+        {
+            //ErrorCode = errno;
+            return 0;
+        }
+    return 1;
+}
+*/
+
+Ptr<File> FileFILEOpen(const String& path, int flags, int mode)
+{
+    Ptr<File> result = *new FILEFile(path, flags, mode);
+	return result;
+}
+
+// Helper function: obtain file information time.
+bool    SysFile::GetFileStat(FileStat* pfileStat, const String& path)
+{
+#if defined(OVR_OS_WIN32)
+    // 64-bit implementation on Windows.
+    struct __stat64 fileStat;
+    // Stat returns 0 for success.
+    wchar_t *pwpath = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(path.ToCStr())+1)*sizeof(wchar_t));
+    UTF8Util::DecodeString(pwpath, path.ToCStr());
+
+    int ret = _wstat64(pwpath, &fileStat);
+    OVR_FREE(pwpath);
+    if (ret) return false;
+#else
+    struct stat fileStat;
+    // Stat returns 0 for success.
+    if (stat(path, &fileStat) != 0)
+        return false;
+#endif
+    pfileStat->AccessTime = fileStat.st_atime;
+    pfileStat->ModifyTime = fileStat.st_mtime;
+    pfileStat->FileSize   = fileStat.st_size;
+    return true;
+}
+
+} // Namespace OVR
diff --git a/LibOVR/Src/Kernel/OVR_Hash.h b/LibOVR/Src/Kernel/OVR_Hash.h
new file mode 100644
index 0000000..04c4db8
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Hash.h
@@ -0,0 +1,1302 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_Hash.h
+Content     :   Template hash-table/set implementation
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Hash_h
+#define OVR_Hash_h
+
+#include "OVR_ContainerAllocator.h"
+#include "OVR_Alg.h"
+
+// 'new' operator is redefined/used in this file.
+#undef new
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** Hash Table Implementation
+
+// HastSet and Hash.
+//
+// Hash table, linear probing, internal chaining.  One  interesting/nice thing
+// about this implementation is that the table itself is a flat chunk of memory
+// containing no pointers, only relative indices. If the key and value types
+// of the Hash contain no pointers, then the Hash can be serialized using raw IO.
+//
+// Never shrinks, unless you explicitly Clear() it.  Expands on
+// demand, though.  For best results, if you know roughly how big your
+// table will be, default it to that size when you create it.
+//
+// Key usability feature:
+//
+//   1. Allows node hash values to either be cached or not.
+//
+//   2. Allows for alternative keys with methods such as GetAlt(). Handy
+//      if you need to search nodes by their components; no need to create
+//      temporary nodes.
+//
+
+
+// *** Hash functors:
+//
+//  IdentityHash  - use when the key is already a good hash
+//  HFixedSizeHash - general hash based on object's in-memory representation.
+
+
+// Hash is just the input value; can use this for integer-indexed hash tables.
+template<class C>
+class IdentityHash
+{
+public:
+    UPInt operator()(const C& data) const
+    { return (UPInt) data; }
+};
+
+// Computes a hash of an object's representation.
+template<class C>
+class FixedSizeHash
+{
+public:
+    // Alternative: "sdbm" hash function, suggested at same web page
+    // above, http::/www.cs.yorku.ca/~oz/hash.html
+    // This is somewhat slower then Bernstein, but it works way better than the above
+    // hash function for hashing large numbers of 32-bit ints.
+    static OVR_FORCE_INLINE UPInt SDBM_Hash(const void* data_in, UPInt size, UPInt seed = 5381)     
+    {
+        const UByte* data = (const UByte*) data_in;
+        UPInt        h = seed;
+        while (size > 0)
+        {
+            size--;
+            h = (h << 16) + (h << 6) - h + (UPInt)data[size];
+        }   
+        return h;
+    }
+
+    UPInt operator()(const C& data) const
+    {
+        unsigned char*  p = (unsigned char*) &data;
+        int size = sizeof(C);
+
+        return SDBM_Hash(p, size);
+    }
+};
+
+
+
+// *** HashsetEntry Entry types. 
+
+// Compact hash table Entry type that re-computes hash keys during hash traversal.
+// Good to use if the hash function is cheap or the hash value is already cached in C.
+template<class C, class HashF>
+class HashsetEntry
+{
+public:
+    // Internal chaining for collisions.
+    SPInt       NextInChain;
+    C           Value;
+
+    HashsetEntry()
+        : NextInChain(-2) { }
+    HashsetEntry(const HashsetEntry& e)
+        : NextInChain(e.NextInChain), Value(e.Value) { }
+    HashsetEntry(const C& key, SPInt next)
+        : NextInChain(next), Value(key) { }
+
+    bool    IsEmpty() const          { return NextInChain == -2;  }
+    bool    IsEndOfChain() const     { return NextInChain == -1;  }
+
+    // Cached hash value access - can be optimized bu storing hash locally.
+    // Mask value only needs to be used if SetCachedHash is not implemented.
+    UPInt   GetCachedHash(UPInt maskValue) const  { return HashF()(Value) & maskValue; }
+    void    SetCachedHash(UPInt)                  {}
+
+    void    Clear()
+    {        
+        Value.~C(); // placement delete
+        NextInChain = -2;
+    }
+    // Free is only used from dtor of hash; Clear is used during regular operations:
+    // assignment, hash reallocations, value reassignments, so on.
+    void    Free() { Clear(); }
+};
+
+// Hash table Entry type that caches the Entry hash value for nodes, so that it
+// does not need to be re-computed during access.
+template<class C, class HashF>
+class HashsetCachedEntry
+{
+public:
+    // Internal chaining for collisions.
+    SPInt       NextInChain;
+    UPInt       HashValue;
+    C           Value;
+
+    HashsetCachedEntry()
+        : NextInChain(-2) { }
+    HashsetCachedEntry(const HashsetCachedEntry& e)
+        : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { }
+    HashsetCachedEntry(const C& key, SPInt next)
+        : NextInChain(next), Value(key) { }
+
+    bool    IsEmpty() const          { return NextInChain == -2;  }
+    bool    IsEndOfChain() const     { return NextInChain == -1;  }
+
+    // Cached hash value access - can be optimized bu storing hash locally.
+    // Mask value only needs to be used if SetCachedHash is not implemented.
+    UPInt   GetCachedHash(UPInt maskValue) const  { OVR_UNUSED(maskValue); return HashValue; }
+    void    SetCachedHash(UPInt hashValue)        { HashValue = hashValue; }
+
+    void    Clear()
+    {
+        Value.~C();
+        NextInChain = -2;
+    }
+    // Free is only used from dtor of hash; Clear is used during regular operations:
+    // assignment, hash reallocations, value reassignments, so on.
+    void    Free() { Clear(); }
+};
+
+
+//-----------------------------------------------------------------------------------
+// *** HashSet implementation - relies on either cached or regular entries.
+//
+// Use: Entry = HashsetCachedEntry<C, HashF> if hashes are expensive to
+//              compute and thus need caching in entries.
+//      Entry = HashsetEntry<C, HashF> if hashes are already externally cached.
+//
+template<class C, class HashF = FixedSizeHash<C>,
+         class AltHashF = HashF, 
+         class Allocator = ContainerAllocator<C>,
+         class Entry = HashsetCachedEntry<C, HashF> >
+class HashSetBase
+{
+    enum { HashMinSize = 8 };
+
+public:
+    OVR_MEMORY_REDEFINE_NEW(HashSetBase)
+
+    typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry>    SelfType;
+
+    HashSetBase() : pTable(NULL)                       {   }
+    HashSetBase(int sizeHint) : pTable(NULL)           { SetCapacity(this, sizeHint);  }
+    HashSetBase(const SelfType& src) : pTable(NULL)    { Assign(this, src); }
+
+    ~HashSetBase()                                     
+    { 
+        if (pTable)
+        {
+            // Delete the entries.
+            for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++)
+            {
+                Entry*  e = &E(i);
+                if (!e->IsEmpty())             
+                    e->Free();
+            }            
+
+            Allocator::Free(pTable);
+            pTable = NULL;
+        }
+    }
+
+
+    void Assign(const SelfType& src)
+    {
+        Clear();
+        if (src.IsEmpty() == false)
+        {
+            SetCapacity(src.GetSize());
+
+            for (ConstIterator it = src.Begin(); it != src.End(); ++it)
+            {
+                Add(*it);
+            }
+        }
+    }
+
+
+    // Remove all entries from the HashSet table.
+    void Clear() 
+    {
+        if (pTable)
+        {
+            // Delete the entries.
+            for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++)
+            {
+                Entry*  e = &E(i);
+                if (!e->IsEmpty())             
+                    e->Clear();
+            }            
+                
+            Allocator::Free(pTable);
+            pTable = NULL;
+        }
+    }
+
+    // Returns true if the HashSet is empty.
+    bool IsEmpty() const
+    {
+        return pTable == NULL || pTable->EntryCount == 0;
+    }
+
+
+    // Set a new or existing value under the key, to the value.
+    // Pass a different class of 'key' so that assignment reference object
+    // can be passed instead of the actual object.
+    template<class CRef>
+    void Set(const CRef& key)
+    {
+        UPInt  hashValue = HashF()(key);
+        SPInt  index     = (SPInt)-1;
+
+        if (pTable != NULL)
+            index = findIndexCore(key, hashValue & pTable->SizeMask);
+
+        if (index >= 0)
+        {            
+            E(index).Value = key;
+        }
+        else
+        {
+            // Entry under key doesn't exist.
+            add(key, hashValue);
+        }
+    }
+
+    template<class CRef>
+    inline void Add(const CRef& key)
+    {
+        UPInt hashValue = HashF()(key);
+        add(key, hashValue);
+    }
+
+    // Remove by alternative key.
+    template<class K>
+    void RemoveAlt(const K& key)
+    {   
+        if (pTable == NULL)
+            return;
+
+        UPInt   hashValue = AltHashF()(key);
+        SPInt   index     = hashValue & pTable->SizeMask;
+
+        Entry*  e = &E(index);
+
+        // If empty node or occupied by collider, we have nothing to remove.
+        if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (UPInt)index))
+            return;        
+
+        // Save index
+        SPInt   naturalIndex = index;
+        SPInt   prevIndex    = -1;
+
+        while ((e->GetCachedHash(pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key))
+        {
+            // Keep looking through the chain.
+            prevIndex   = index;
+            index       = e->NextInChain;
+            if (index == -1)
+                return; // End of chain, item not found
+            e = &E(index);
+        }
+
+        // Found it - our item is at index
+        if (naturalIndex == index)
+        {
+            // If we have a follower, move it to us
+            if (!e->IsEndOfChain())
+            {               
+                Entry*  enext = &E(e->NextInChain);
+                e->Clear();
+                new (e) Entry(*enext);
+                // Point us to the follower's cell that will be cleared
+                e = enext;
+            }
+        }
+        else
+        {
+            // We are not at natural index, so deal with the prev items next index
+            E(prevIndex).NextInChain = e->NextInChain;
+        }
+
+        // Clear us, of the follower cell that was moved.
+        e->Clear();
+        pTable->EntryCount --;
+        // Should we check the size to condense hash? ...
+    }
+
+    // Remove by main key.
+    template<class CRef>
+    void Remove(const CRef& key)
+    {
+        RemoveAlt(key);
+    }
+
+    // Retrieve the pointer to a value under the given key.
+    //  - If there's no value under the key, then return NULL.    
+    //  - If there is a value, return the pointer.    
+    template<class K>
+    C* Get(const K& key)
+    {
+        SPInt   index = findIndex(key);
+        if (index >= 0)        
+            return &E(index).Value;        
+        return 0;
+    }   
+
+    template<class K>
+    const C* Get(const K& key) const
+    {
+        SPInt   index = findIndex(key);
+        if (index >= 0)        
+            return &E(index).Value;        
+        return 0;
+    }
+
+    // Alternative key versions of Get. Used by Hash.
+    template<class K>
+    const C* GetAlt(const K& key) const
+    {
+        SPInt   index = findIndexAlt(key);
+        if (index >= 0)        
+            return &E(index).Value;
+        return 0;
+    }
+
+    template<class K>
+    C* GetAlt(const K& key)
+    {
+        SPInt   index = findIndexAlt(key);
+        if (index >= 0)        
+            return &E(index).Value;
+        return 0;
+    }   
+
+    template<class K>
+    bool GetAlt(const K& key, C* pval) const
+    {
+        SPInt   index = findIndexAlt(key);
+        if (index >= 0)
+        {
+            if (pval)
+                *pval = E(index).Value;
+            return true;
+        }
+        return false;
+    }
+
+
+    UPInt GetSize() const
+    {
+        return pTable == NULL ? 0 : (UPInt)pTable->EntryCount;
+    }
+
+
+    // Resize the HashSet table to fit one more Entry.  Often this
+    // doesn't involve any action.
+    void CheckExpand()
+    {
+        if (pTable == NULL)
+        {
+            // Initial creation of table.  Make a minimum-sized table.
+            setRawCapacity(HashMinSize);
+        }
+        else if (pTable->EntryCount * 5 > (pTable->SizeMask + 1) * 4)
+        {
+            // pTable is more than 5/4 ths full.  Expand.
+            setRawCapacity((pTable->SizeMask + 1) * 2);
+        }
+    }
+
+    // Hint the bucket count to >= n.
+    void Resize(UPInt n)    
+    {
+        // Not really sure what this means in relation to
+        // STLport's hash_map... they say they "increase the
+        // bucket count to at least n" -- but does that mean
+        // their real capacity after Resize(n) is more like
+        // n*2 (since they do linked-list chaining within
+        // buckets?).
+        SetCapacity(n);
+    }
+
+    // Size the HashSet so that it can comfortably contain the given
+    // number of elements.  If the HashSet already contains more
+    // elements than newSize, then this may be a no-op.
+    void SetCapacity(UPInt newSize)
+    {
+        UPInt newRawSize = (newSize * 5) / 4;
+        if (newRawSize <= GetSize())
+            return;
+        setRawCapacity(newRawSize);
+    }
+
+    // Disable inappropriate 'operator ->' warning on MSVC6.
+#ifdef OVR_CC_MSVC
+#if (OVR_CC_MSVC < 1300)
+# pragma warning(disable : 4284)
+#endif
+#endif
+
+    // Iterator API, like STL.
+    struct ConstIterator
+    {   
+        const C&    operator * () const
+        {            
+            OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask);
+            return pHash->E(Index).Value;
+        }
+
+        const C*    operator -> () const
+        {
+            OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask);
+            return &pHash->E(Index).Value;
+        }
+
+        void    operator ++ ()
+        {
+            // Find next non-empty Entry.
+            if (Index <= (SPInt)pHash->pTable->SizeMask)
+            {
+                Index++;
+                while ((UPInt)Index <= pHash->pTable->SizeMask &&
+                    pHash->E(Index).IsEmpty())
+                {
+                    Index++;
+                }
+            }
+        }
+
+        bool    operator == (const ConstIterator& it) const
+        {
+            if (IsEnd() && it.IsEnd())
+            {
+                return true;
+            }
+            else
+            {
+                return (pHash == it.pHash) && (Index == it.Index);
+            }
+        }
+
+        bool    operator != (const ConstIterator& it) const
+        {
+            return ! (*this == it);
+        }
+
+
+        bool    IsEnd() const
+        {
+            return (pHash == NULL) || 
+                (pHash->pTable == NULL) || 
+                (Index > (SPInt)pHash->pTable->SizeMask);
+        }
+
+        ConstIterator()
+            : pHash(NULL), Index(0)
+        { }
+
+    public:
+        // Constructor was intentionally made public to allow create
+        // iterator with arbitrary index.
+        ConstIterator(const SelfType* h, SPInt index)
+            : pHash(h), Index(index)
+        { }
+
+        const SelfType* GetContainer() const
+        {
+            return pHash;
+        }
+        SPInt GetIndex() const
+        {
+            return Index;
+        }
+
+    protected:
+        friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
+
+        const SelfType* pHash;
+        SPInt           Index;
+    };
+
+    friend struct ConstIterator;
+
+
+    // Non-const Iterator; Get most of it from ConstIterator.
+    struct Iterator : public ConstIterator
+    {      
+        // Allow non-const access to entries.
+        C&  operator*() const
+        {            
+            OVR_ASSERT(ConstIterator::Index >= 0 && ConstIterator::Index <= (SPInt)ConstIterator::pHash->pTable->SizeMask);
+            return const_cast<SelfType*>(ConstIterator::pHash)->E(ConstIterator::Index).Value;
+        }    
+
+        C*  operator->() const 
+        {
+            return &(operator*());
+        }
+
+        Iterator()
+            : ConstIterator(NULL, 0)
+        { }
+
+        // Removes current element from Hash
+        void Remove()
+        {
+            RemoveAlt(operator*());
+        }
+
+        template <class K>
+        void RemoveAlt(const K& key)
+        {
+            SelfType*   phash = const_cast<SelfType*>(ConstIterator::pHash);
+            //Entry*      ee = &phash->E(ConstIterator::Index);
+            //const C&    key = ee->Value;
+
+            UPInt       hashValue = AltHashF()(key);
+            SPInt       index     = hashValue & phash->pTable->SizeMask;
+
+            Entry*      e = &phash->E(index);
+
+            // If empty node or occupied by collider, we have nothing to remove.
+            if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)index))
+                return;        
+
+            // Save index
+            SPInt   naturalIndex = index;
+            SPInt   prevIndex    = -1;
+
+            while ((e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key))
+            {
+                // Keep looking through the chain.
+                prevIndex   = index;
+                index       = e->NextInChain;
+                if (index == -1)
+                    return; // End of chain, item not found
+                e = &phash->E(index);
+            }
+
+            if (index == (SPInt)ConstIterator::Index)
+            {
+                // Found it - our item is at index
+                if (naturalIndex == index)
+                {
+                    // If we have a follower, move it to us
+                    if (!e->IsEndOfChain())
+                    {               
+                        Entry*  enext = &phash->E(e->NextInChain);
+                        e->Clear();
+                        new (e) Entry(*enext);
+                        // Point us to the follower's cell that will be cleared
+                        e = enext;
+                        --ConstIterator::Index;
+                    }
+                }
+                else
+                {
+                    // We are not at natural index, so deal with the prev items next index
+                    phash->E(prevIndex).NextInChain = e->NextInChain;
+                }
+
+                // Clear us, of the follower cell that was moved.
+                e->Clear();
+                phash->pTable->EntryCount --;
+            }
+            else 
+                OVR_ASSERT(0); //?
+        }
+
+    private:
+        friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
+
+        Iterator(SelfType* h, SPInt i0)
+            : ConstIterator(h, i0)
+        { }
+    };
+
+    friend struct Iterator;
+
+    Iterator    Begin()
+    {
+        if (pTable == 0)
+            return Iterator(NULL, 0);
+
+        // Scan till we hit the First valid Entry.
+        UPInt  i0 = 0;
+        while (i0 <= pTable->SizeMask && E(i0).IsEmpty())
+        {
+            i0++;
+        }
+        return Iterator(this, i0);
+    }
+    Iterator        End()           { return Iterator(NULL, 0); }
+
+    ConstIterator   Begin() const   { return const_cast<SelfType*>(this)->Begin();     }
+    ConstIterator   End() const     { return const_cast<SelfType*>(this)->End();   }
+
+    template<class K>
+    Iterator Find(const K& key)
+    {
+        SPInt index = findIndex(key);
+        if (index >= 0)        
+            return Iterator(this, index);        
+        return Iterator(NULL, 0);
+    }
+
+    template<class K>
+    Iterator FindAlt(const K& key)
+    {
+        SPInt index = findIndexAlt(key);
+        if (index >= 0)        
+            return Iterator(this, index);        
+        return Iterator(NULL, 0);
+    }
+
+    template<class K>
+    ConstIterator Find(const K& key) const       { return const_cast<SelfType*>(this)->Find(key); }
+
+    template<class K>
+    ConstIterator FindAlt(const K& key) const    { return const_cast<SelfType*>(this)->FindAlt(key); }
+
+private:
+    // Find the index of the matching Entry.  If no match, then return -1.
+    template<class K>
+    SPInt findIndex(const K& key) const
+    {
+        if (pTable == NULL)
+            return -1;
+        UPInt hashValue = HashF()(key) & pTable->SizeMask;
+        return findIndexCore(key, hashValue);
+    }
+
+    template<class K>
+    SPInt findIndexAlt(const K& key) const
+    {
+        if (pTable == NULL)
+            return -1;
+        UPInt hashValue = AltHashF()(key) & pTable->SizeMask;
+        return findIndexCore(key, hashValue);
+    }
+
+    // Find the index of the matching Entry.  If no match, then return -1.
+    template<class K>
+    SPInt findIndexCore(const K& key, UPInt hashValue) const
+    {
+        // Table must exist.
+        OVR_ASSERT(pTable != 0);
+        // Hash key must be 'and-ed' by the caller.
+        OVR_ASSERT((hashValue & ~pTable->SizeMask) == 0);
+
+        UPInt           index = hashValue;
+        const Entry*    e     = &E(index);
+
+        // If empty or occupied by a collider, not found.
+        if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != index))
+            return -1;
+
+        while(1)
+        {
+            OVR_ASSERT(e->GetCachedHash(pTable->SizeMask) == hashValue);
+
+            if (e->GetCachedHash(pTable->SizeMask) == hashValue && e->Value == key)
+            {
+                // Found it.
+                return index;
+            }
+            // Values can not be equal at this point.
+            // That would mean that the hash key for the same value differs.
+            OVR_ASSERT(!(e->Value == key));
+
+            // Keep looking through the chain.
+            index = e->NextInChain;
+            if (index == (UPInt)-1)
+                break; // end of chain
+
+            e = &E(index);
+            OVR_ASSERT(!e->IsEmpty());
+        }
+        return -1;
+    }
+
+
+    // Add a new value to the HashSet table, under the specified key.
+    template<class CRef>
+    void add(const CRef& key, UPInt hashValue)
+    {
+        CheckExpand();
+        hashValue &= pTable->SizeMask;
+
+        pTable->EntryCount++;
+
+        SPInt   index        = hashValue;
+        Entry*  naturalEntry = &(E(index));
+
+        if (naturalEntry->IsEmpty())
+        {
+            // Put the new Entry in.
+            new (naturalEntry) Entry(key, -1);
+        }
+        else
+        {
+            // Find a blank spot.
+            SPInt blankIndex = index;
+            do {
+                blankIndex = (blankIndex + 1) & pTable->SizeMask;
+            } while(!E(blankIndex).IsEmpty());
+
+            Entry*  blankEntry = &E(blankIndex);
+
+            if (naturalEntry->GetCachedHash(pTable->SizeMask) == (UPInt)index)
+            {
+                // Collision.  Link into this chain.
+
+                // Move existing list head.
+                new (blankEntry) Entry(*naturalEntry);    // placement new, copy ctor
+
+                // Put the new info in the natural Entry.
+                naturalEntry->Value       = key;
+                naturalEntry->NextInChain = blankIndex;
+            }
+            else
+            {
+                // Existing Entry does not naturally
+                // belong in this slot.  Existing
+                // Entry must be moved.
+
+                // Find natural location of collided element (i.e. root of chain)
+                SPInt collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask);
+                OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask);
+                for (;;)
+                {
+                    Entry*  e = &E(collidedIndex);
+                    if (e->NextInChain == index)
+                    {
+                        // Here's where we need to splice.
+                        new (blankEntry) Entry(*naturalEntry);
+                        e->NextInChain = blankIndex;
+                        break;
+                    }
+                    collidedIndex = e->NextInChain;
+                    OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask);
+                }
+
+                // Put the new data in the natural Entry.
+                naturalEntry->Value       = key;
+                naturalEntry->NextInChain = -1;                
+            }            
+        }
+
+        // Record hash value: has effect only if cached node is used.
+        naturalEntry->SetCachedHash(hashValue);
+    }
+
+    // Index access helpers.
+    Entry& E(UPInt index)
+    {
+        // Must have pTable and access needs to be within bounds.
+        OVR_ASSERT(index <= pTable->SizeMask);
+        return *(((Entry*) (pTable + 1)) + index);
+    }
+    const Entry& E(UPInt index) const
+    {        
+        OVR_ASSERT(index <= pTable->SizeMask);
+        return *(((Entry*) (pTable + 1)) + index);
+    }
+
+
+    // Resize the HashSet table to the given size (Rehash the
+    // contents of the current table).  The arg is the number of
+    // HashSet table entries, not the number of elements we should
+    // actually contain (which will be less than this).
+    void    setRawCapacity(UPInt newSize)    
+    {
+        if (newSize == 0)
+        {
+            // Special case.
+            Clear();
+            return;
+        }
+
+        // Minimum size; don't incur rehashing cost when expanding
+        // very small tables. Not that we perform this check before 
+        // 'log2f' call to avoid fp exception with newSize == 1.
+        if (newSize < HashMinSize)        
+            newSize = HashMinSize;       
+        else
+        {
+            // Force newSize to be a power of two.
+            int bits = Alg::UpperBit(newSize-1) + 1; // Chop( Log2f((float)(newSize-1)) + 1);
+            OVR_ASSERT((UPInt(1) << bits) >= newSize);
+            newSize = UPInt(1) << bits;
+        }
+
+        SelfType  newHash;
+        newHash.pTable = (TableType*)
+            Allocator::Alloc(                
+                sizeof(TableType) + sizeof(Entry) * newSize);
+        // Need to do something on alloc failure!
+        OVR_ASSERT(newHash.pTable);
+
+        newHash.pTable->EntryCount = 0;
+        newHash.pTable->SizeMask = newSize - 1;
+        UPInt i, n;
+
+        // Mark all entries as empty.
+        for (i = 0; i < newSize; i++)
+            newHash.E(i).NextInChain = -2;
+
+        // Copy stuff to newHash
+        if (pTable)
+        {            
+            for (i = 0, n = pTable->SizeMask; i <= n; i++)
+            {
+                Entry*  e = &E(i);
+                if (e->IsEmpty() == false)
+                {
+                    // Insert old Entry into new HashSet.
+                    newHash.Add(e->Value);
+                    // placement delete of old element
+                    e->Clear();
+                }
+            }
+
+            // Delete our old data buffer.
+            Allocator::Free(pTable);
+        }
+
+        // Steal newHash's data.
+        pTable = newHash.pTable;
+        newHash.pTable = NULL;
+    }
+
+    struct TableType
+    {
+        UPInt EntryCount;
+        UPInt SizeMask;
+        // Entry array follows this structure
+        // in memory.
+    };
+    TableType*  pTable;
+};
+
+
+
+//-----------------------------------------------------------------------------------
+template<class C, class HashF = FixedSizeHash<C>,
+         class AltHashF = HashF, 
+         class Allocator = ContainerAllocator<C>,
+         class Entry = HashsetCachedEntry<C, HashF> >
+class HashSet : public HashSetBase<C, HashF, AltHashF, Allocator, Entry>
+{
+public:
+    typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> BaseType;
+    typedef HashSet<C, HashF, AltHashF, Allocator, Entry>     SelfType;
+
+    HashSet()                                      {   }
+    HashSet(int sizeHint) : BaseType(sizeHint)     {   }
+    HashSet(const SelfType& src) : BaseType(src)   {   }
+    ~HashSet()                                     {   }
+
+    void operator = (const SelfType& src)   { BaseType::Assign(src); }
+
+    // Set a new or existing value under the key, to the value.
+    // Pass a different class of 'key' so that assignment reference object
+    // can be passed instead of the actual object.
+    template<class CRef>
+    void Set(const CRef& key)
+    {
+        BaseType::Set(key);
+    }
+
+    template<class CRef>
+    inline void Add(const CRef& key)
+    {
+        BaseType::Add(key);
+    }
+
+    // Hint the bucket count to >= n.
+    void Resize(UPInt n)    
+    {
+        BaseType::SetCapacity(n);
+    }
+
+    // Size the HashSet so that it can comfortably contain the given
+    // number of elements.  If the HashSet already contains more
+    // elements than newSize, then this may be a no-op.
+    void SetCapacity(UPInt newSize)
+    {
+        BaseType::SetCapacity(newSize);
+    }
+
+};
+
+// HashSet with uncached hash code; declared for convenience.
+template<class C, class HashF = FixedSizeHash<C>,
+                  class AltHashF = HashF,
+                  class Allocator = ContainerAllocator<C> >
+class HashSetUncached : public HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> >
+{
+public:
+    
+    typedef HashSetUncached<C, HashF, AltHashF, Allocator>                  SelfType;
+    typedef HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> > BaseType;
+
+    // Delegated constructors.
+    HashSetUncached()                                        { }
+    HashSetUncached(int sizeHint) : BaseType(sizeHint)       { }
+    HashSetUncached(const SelfType& src) : BaseType(src)     { }
+    ~HashSetUncached()                                       { }
+    
+    void    operator = (const SelfType& src)
+    {
+        BaseType::operator = (src);
+    }
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** Hash hash table implementation
+
+// Node for Hash - necessary so that Hash can delegate its implementation
+// to HashSet.
+template<class C, class U, class HashF>
+struct HashNode
+{
+    typedef HashNode<C, U, HashF>   SelfType;
+    typedef C                       FirstType;
+    typedef U                       SecondType;
+
+    C   First;
+    U   Second;
+
+    // NodeRef is used to allow passing of elements into HashSet
+    // without using a temporary object.
+    struct NodeRef
+    {
+        const C*   pFirst;
+        const U*   pSecond;
+
+        NodeRef(const C& f, const U& s) : pFirst(&f), pSecond(&s) { }
+        NodeRef(const NodeRef& src)     : pFirst(src.pFirst), pSecond(src.pSecond) { }
+
+        // Enable computation of ghash_node_hashf.
+        inline UPInt GetHash() const            { return HashF()(*pFirst); } 
+        // Necessary conversion to allow HashNode::operator == to work.
+        operator const C& () const              { return *pFirst; }
+    };
+
+    // Note: No default constructor is necessary.
+     HashNode(const HashNode& src) : First(src.First), Second(src.Second)    { }
+     HashNode(const NodeRef& src) : First(*src.pFirst), Second(*src.pSecond)  { }
+    void operator = (const NodeRef& src)  { First  = *src.pFirst; Second = *src.pSecond; }
+
+    template<class K>
+    bool operator == (const K& src) const   { return (First == src); }
+
+    template<class K>
+    static UPInt CalcHash(const K& data)   { return HashF()(data); }
+    inline UPInt GetHash() const           { return HashF()(First); }
+
+    // Hash functors used with this node. A separate functor is used for alternative
+    // key lookup so that it does not need to access the '.First' element.    
+    struct NodeHashF
+    {    
+        template<class K>
+        UPInt operator()(const K& data) const { return data.GetHash(); } 
+    };    
+    struct NodeAltHashF
+    {
+        template<class K>
+        UPInt operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); }
+    };
+};
+
+
+
+// **** Extra hashset_entry types to allow NodeRef construction.
+
+// The big difference between the below types and the ones used in hash_set is that
+// these allow initializing the node with 'typename C::NodeRef& keyRef', which
+// is critical to avoid temporary node allocation on stack when using placement new.
+
+// Compact hash table Entry type that re-computes hash keys during hash traversal.
+// Good to use if the hash function is cheap or the hash value is already cached in C.
+template<class C, class HashF>
+class HashsetNodeEntry
+{
+public:
+    // Internal chaining for collisions.
+    SPInt NextInChain;
+    C     Value;
+
+    HashsetNodeEntry()
+        : NextInChain(-2) { }
+    HashsetNodeEntry(const HashsetNodeEntry& e)
+        : NextInChain(e.NextInChain), Value(e.Value) { }
+    HashsetNodeEntry(const C& key, SPInt next)
+        : NextInChain(next), Value(key) { }    
+    HashsetNodeEntry(const typename C::NodeRef& keyRef, SPInt next)
+        : NextInChain(next), Value(keyRef) { }
+
+    bool    IsEmpty() const             { return NextInChain == -2;  }
+    bool    IsEndOfChain() const        { return NextInChain == -1;  }
+    UPInt   GetCachedHash(UPInt maskValue) const  { return HashF()(Value) & maskValue; }
+    void    SetCachedHash(UPInt hashValue)        { OVR_UNUSED(hashValue); }
+
+    void    Clear()
+    {        
+        Value.~C(); // placement delete
+        NextInChain = -2;
+    }
+    // Free is only used from dtor of hash; Clear is used during regular operations:
+    // assignment, hash reallocations, value reassignments, so on.
+    void    Free() { Clear(); }
+};
+
+// Hash table Entry type that caches the Entry hash value for nodes, so that it
+// does not need to be re-computed during access.
+template<class C, class HashF>
+class HashsetCachedNodeEntry
+{
+public:
+    // Internal chaining for collisions.
+    SPInt NextInChain;
+    UPInt HashValue;
+    C     Value;
+
+    HashsetCachedNodeEntry()
+        : NextInChain(-2) { }
+    HashsetCachedNodeEntry(const HashsetCachedNodeEntry& e)
+        : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { }
+    HashsetCachedNodeEntry(const C& key, SPInt next)
+        : NextInChain(next), Value(key) { }
+    HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, SPInt next)
+        : NextInChain(next), Value(keyRef) { }
+
+    bool    IsEmpty() const            { return NextInChain == -2;  }
+    bool    IsEndOfChain() const       { return NextInChain == -1;  }
+    UPInt   GetCachedHash(UPInt maskValue) const  { OVR_UNUSED(maskValue); return HashValue; }
+    void    SetCachedHash(UPInt hashValue)        { HashValue = hashValue; }
+
+    void    Clear()
+    {
+        Value.~C();
+        NextInChain = -2;
+    }
+    // Free is only used from dtor of hash; Clear is used during regular operations:
+    // assignment, hash reallocations, value reassignments, so on.
+    void    Free() { Clear(); }
+};
+
+
+//-----------------------------------------------------------------------------------
+template<class C, class U,
+         class HashF = FixedSizeHash<C>,
+         class Allocator = ContainerAllocator<C>,
+         class HashNode = OVR::HashNode<C,U,HashF>,
+         class Entry = HashsetCachedNodeEntry<HashNode, typename HashNode::NodeHashF>,
+         class Container =  HashSet<HashNode, typename HashNode::NodeHashF,
+             typename HashNode::NodeAltHashF, Allocator,
+             Entry> >
+class Hash
+{
+public:
+    OVR_MEMORY_REDEFINE_NEW(Hash)
+
+    // Types used for hash_set.
+    typedef U                                                           ValueType;
+    typedef Hash<C, U, HashF, Allocator, HashNode, Entry, Container>    SelfType;
+
+    // Actual hash table itself, implemented as hash_set.
+    Container   mHash;
+
+public:
+    Hash()     {  }
+    Hash(int sizeHint) : mHash(sizeHint)                        { }
+    Hash(const SelfType& src) : mHash(src.mHash)                { }
+    ~Hash()                                                     { }
+
+    void    operator = (const SelfType& src)    { mHash = src.mHash; }
+
+    // Remove all entries from the Hash table.
+    inline void    Clear() { mHash.Clear(); }
+    // Returns true if the Hash is empty.
+    inline bool    IsEmpty() const { return mHash.IsEmpty(); }
+
+    // Access (set).
+    inline void    Set(const C& key, const U& value)
+    {
+        typename HashNode::NodeRef e(key, value);
+        mHash.Set(e);
+    }
+    inline void    Add(const C& key, const U& value)
+    {
+        typename HashNode::NodeRef e(key, value);
+        mHash.Add(e);
+    }
+
+    // Removes an element by clearing its Entry.
+    inline void     Remove(const C& key)
+    {   
+        mHash.RemoveAlt(key);
+    }
+    template<class K>
+    inline void     RemoveAlt(const K& key)
+    {   
+        mHash.RemoveAlt(key);
+    }
+
+    // Retrieve the value under the given key.    
+    //  - If there's no value under the key, then return false and leave *pvalue alone.
+    //  - If there is a value, return true, and Set *Pvalue to the Entry's value.
+    //  - If value == NULL, return true or false according to the presence of the key.    
+    bool    Get(const C& key, U* pvalue) const   
+    {
+        const HashNode* p = mHash.GetAlt(key);
+        if (p)
+        {
+            if (pvalue)
+                *pvalue = p->Second;
+            return true;
+        }
+        return false;
+    }
+
+    template<class K>
+    bool    GetAlt(const K& key, U* pvalue) const   
+    {
+        const HashNode* p = mHash.GetAlt(key);
+        if (p)
+        {
+            if (pvalue)
+                *pvalue = p->Second;
+            return true;
+        }
+        return false;
+    }
+
+    // Retrieve the pointer to a value under the given key.    
+    //  - If there's no value under the key, then return NULL.    
+    //  - If there is a value, return the pointer.    
+    inline U*  Get(const C& key)
+    {
+        HashNode* p = mHash.GetAlt(key);
+        return p ? &p->Second : 0;
+    }
+    inline const U* Get(const C& key) const
+    {
+        const HashNode* p = mHash.GetAlt(key);
+        return p ? &p->Second : 0;
+    }
+
+    template<class K>
+    inline U*  GetAlt(const K& key)
+    {
+        HashNode* p = mHash.GetAlt(key);
+        return p ? &p->Second : 0;
+    }
+    template<class K>
+    inline const U* GetAlt(const K& key) const
+    {
+        const HashNode* p = mHash.GetAlt(key);
+        return p ? &p->Second : 0;
+    }
+
+    // Sizing methods - delegate to Hash.
+    inline UPInt   GetSize() const              { return mHash.GetSize(); }    
+    inline void    Resize(UPInt n)              { mHash.Resize(n); }
+    inline void    SetCapacity(UPInt newSize)   { mHash.SetCapacity(newSize); }
+
+    // Iterator API, like STL.
+    typedef typename Container::ConstIterator   ConstIterator;
+    typedef typename Container::Iterator        Iterator;
+
+    inline Iterator        Begin()              { return mHash.Begin(); }
+    inline Iterator        End()                { return mHash.End(); }
+    inline ConstIterator   Begin() const        { return mHash.Begin(); }
+    inline ConstIterator   End() const          { return mHash.End();   }
+
+    Iterator        Find(const C& key)          { return mHash.FindAlt(key);  }
+    ConstIterator   Find(const C& key) const    { return mHash.FindAlt(key);  }
+
+    template<class K>
+    Iterator        FindAlt(const K& key)       { return mHash.FindAlt(key);  }
+    template<class K>
+    ConstIterator   FindAlt(const K& key) const { return mHash.FindAlt(key);  }
+};
+
+
+
+// Hash with uncached hash code; declared for convenience.
+template<class C, class U, class HashF = FixedSizeHash<C>, class Allocator = ContainerAllocator<C> >
+class HashUncached
+    : public Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>,
+                   HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> >
+{
+public:
+    typedef HashUncached<C, U, HashF, Allocator>                SelfType;
+    typedef Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>,
+                 HashsetNodeEntry<HashNode<C,U,HashF>,
+                 typename HashNode<C,U,HashF>::NodeHashF> >     BaseType;
+
+    // Delegated constructors.
+    HashUncached()                                        { }
+    HashUncached(int sizeHint) : BaseType(sizeHint)       { }
+    HashUncached(const SelfType& src) : BaseType(src)     { }
+    ~HashUncached()                                       { }
+    void operator = (const SelfType& src)                 { BaseType::operator = (src); }
+};
+
+
+
+// And identity hash in which keys serve as hash value. Can be uncached,
+// since hash computation is assumed cheap.
+template<class C, class U, class Allocator = ContainerAllocator<C>, class HashF = IdentityHash<C> >
+class HashIdentity
+    : public HashUncached<C, U, HashF, Allocator>
+{
+public:
+    typedef HashIdentity<C, U, Allocator, HashF> SelfType;
+    typedef HashUncached<C, U, HashF, Allocator> BaseType;
+
+    // Delegated constructors.
+    HashIdentity()                                        { }
+    HashIdentity(int sizeHint) : BaseType(sizeHint)       { }
+    HashIdentity(const SelfType& src) : BaseType(src)     { }
+    ~HashIdentity()                                       { }
+    void operator = (const SelfType& src)                 { BaseType::operator = (src); }
+};
+
+
+} // OVR
+
+
+#ifdef OVR_DEFINE_NEW
+#define new OVR_DEFINE_NEW
+#endif
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_KeyCodes.h b/LibOVR/Src/Kernel/OVR_KeyCodes.h
new file mode 100644
index 0000000..b5c5930
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_KeyCodes.h
@@ -0,0 +1,251 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_KeyCodes.h
+Content     :   Common keyboard constants
+Created     :   September 19, 2012
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_KeyCodes_h
+#define OVR_KeyCodes_h
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** KeyCode
+
+// KeyCode enumeration defines platform-independent keyboard key constants.
+// Note that Key_A through Key_Z are mapped to capital ascii constants.
+
+enum KeyCode
+{
+    // Key_None indicates that no key was specified.
+    Key_None            = 0, 
+
+    // A through Z and numbers 0 through 9.
+    Key_A               = 65,
+    Key_B,
+    Key_C,
+    Key_D,
+    Key_E,
+    Key_F,
+    Key_G,
+    Key_H,
+    Key_I,
+    Key_J,
+    Key_K,
+    Key_L,
+    Key_M,
+    Key_N,
+    Key_O,
+    Key_P,
+    Key_Q,
+    Key_R,
+    Key_S,
+    Key_T,
+    Key_U,
+    Key_V,
+    Key_W,
+    Key_X,
+    Key_Y,
+    Key_Z,
+    Key_Num0            = 48,
+    Key_Num1,
+    Key_Num2,
+    Key_Num3,
+    Key_Num4,
+    Key_Num5,
+    Key_Num6,
+    Key_Num7,
+    Key_Num8,
+    Key_Num9,
+
+    // Numeric keypad.
+    Key_KP_0            = 0xa0,
+    Key_KP_1,
+    Key_KP_2,
+    Key_KP_3,
+    Key_KP_4,
+    Key_KP_5,
+    Key_KP_6,
+    Key_KP_7,
+    Key_KP_8,
+    Key_KP_9,
+    Key_KP_Multiply,
+    Key_KP_Add,
+    Key_KP_Enter,
+    Key_KP_Subtract,
+    Key_KP_Decimal,
+    Key_KP_Divide,
+    
+    // Function keys.
+    Key_F1              = 0xb0,
+    Key_F2,
+    Key_F3,
+    Key_F4,
+    Key_F5,
+    Key_F6,
+    Key_F7,
+    Key_F8,
+    Key_F9,
+    Key_F10,
+    Key_F11,
+    Key_F12,
+    Key_F13,
+    Key_F14,
+    Key_F15,
+    
+    // Other keys.
+    Key_Backspace       = 8,
+    Key_Tab,
+    Key_Clear           = 12,
+    Key_Return,
+    Key_Shift           = 16,
+    Key_Control,
+    Key_Alt,
+    Key_Pause,
+    Key_CapsLock        = 20, // Toggle
+    Key_Escape          = 27,
+    Key_Space           = 32,
+    Key_Quote           = 39,
+    Key_PageUp          = 0xc0,
+    Key_PageDown,
+    Key_End,
+    Key_Home,
+    Key_Left,
+    Key_Up,
+    Key_Right,
+    Key_Down,
+    Key_Insert,
+    Key_Delete,
+    Key_Help,
+    
+    Key_Comma           = 44,
+    Key_Minus,
+    Key_Slash           = 47,
+    Key_Period,
+    Key_NumLock         = 144, // Toggle
+    Key_ScrollLock      = 145, // Toggle
+    
+    Key_Semicolon       = 59,
+    Key_Equal           = 61,
+    Key_Backtick        = 96,   // ` and tilda~ when shifted (US keyboard)
+    Key_BracketLeft     = 91,
+    Key_Backslash,
+    Key_BracketRight,
+
+    Key_OEM_AX          = 0xE1,  //  'AX' key on Japanese AX keyboard
+    Key_OEM_102         = 0xE2,  //  "<>" or "\|" on RT 102-key keyboard.
+    Key_ICO_HELP        = 0xE3,  //  Help key on ICO
+    Key_ICO_00          = 0xE4,  //  00 key on ICO
+
+    Key_Meta,
+
+    // Total number of keys.
+    Key_CodeCount
+};
+
+
+//-----------------------------------------------------------------------------------
+
+class KeyModifiers 
+{
+public:
+    enum
+    {
+        Key_ShiftPressed    = 0x01,
+        Key_CtrlPressed     = 0x02,
+        Key_AltPressed      = 0x04,
+        Key_MetaPressed     = 0x08,
+        Key_CapsToggled     = 0x10,
+        Key_NumToggled      = 0x20,
+        Key_ScrollToggled   = 0x40,
+
+        Initialized_Bit     = 0x80,
+        Initialized_Mask    = 0xFF
+    };
+    unsigned char States;
+
+    KeyModifiers() : States(0) { }
+        KeyModifiers(unsigned char st) : States((unsigned char)(st | Initialized_Bit)) { }
+
+    void Reset() { States = 0; }
+
+    bool IsShiftPressed() const { return (States & Key_ShiftPressed) != 0; }
+    bool IsCtrlPressed() const  { return (States & Key_CtrlPressed) != 0; }
+    bool IsAltPressed() const   { return (States & Key_AltPressed) != 0; }
+    bool IsMetaPressed() const  { return (States & Key_MetaPressed) != 0; }
+    bool IsCapsToggled() const  { return (States & Key_CapsToggled) != 0; }
+    bool IsNumToggled() const   { return (States & Key_NumToggled) != 0; }
+    bool IsScrollToggled() const{ return (States & Key_ScrollToggled) != 0; }
+
+    void SetShiftPressed(bool v = true)  { (v) ? States |= Key_ShiftPressed : States &= ~Key_ShiftPressed; }
+    void SetCtrlPressed(bool v = true)   { (v) ? States |= Key_CtrlPressed  : States &= ~Key_CtrlPressed; }
+    void SetAltPressed(bool v = true)    { (v) ? States |= Key_AltPressed   : States &= ~Key_AltPressed; }
+    void SetMetaPressed(bool v = true)   { (v) ? States |= Key_MetaPressed  : States &= ~Key_MetaPressed; }
+    void SetCapsToggled(bool v = true)   { (v) ? States |= Key_CapsToggled  : States &= ~Key_CapsToggled; }
+    void SetNumToggled(bool v = true)    { (v) ? States |= Key_NumToggled   : States &= ~Key_NumToggled; }
+    void SetScrollToggled(bool v = true) { (v) ? States |= Key_ScrollToggled: States &= ~Key_ScrollToggled; }
+
+    bool IsInitialized() const { return (States & Initialized_Mask) != 0; }
+};
+
+
+//-----------------------------------------------------------------------------------
+
+/*
+enum PadKeyCode
+{
+    Pad_None, // Indicates absence of key code.
+    Pad_Back,
+    Pad_Start,
+    Pad_A,
+    Pad_B,
+    Pad_X,
+    Pad_Y,
+    Pad_R1,  // RightShoulder;
+    Pad_L1,  // LeftShoulder;
+    Pad_R2,  // RightTrigger;
+    Pad_L2,  // LeftTrigger;
+    Pad_Up,
+    Pad_Down,
+    Pad_Right,
+    Pad_Left,
+    Pad_Plus,
+    Pad_Minus,
+    Pad_1,
+    Pad_2,
+    Pad_H,
+    Pad_C,
+    Pad_Z,
+    Pad_O,
+    Pad_T,
+    Pad_S,
+    Pad_Select,
+    Pad_Home,
+    Pad_RT,  // RightThumb;
+    Pad_LT   // LeftThumb;
+};
+*/
+
+} // OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_List.h b/LibOVR/Src/Kernel/OVR_List.h
new file mode 100644
index 0000000..6b49f37
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_List.h
@@ -0,0 +1,336 @@
+/************************************************************************************
+
+PublicHeader:   OVR
+Filename    :   OVR_List.h
+Content     :   Template implementation for doubly-connected linked List
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_List_h
+#define OVR_List_h
+
+#include "OVR_Types.h"
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** ListNode
+//
+// Base class for the elements of the intrusive linked list.
+// To store elements in the List do:
+//
+// struct MyData : ListNode<MyData>
+// {
+//     . . .
+// };
+
+template<class T>
+struct ListNode
+{
+    union {
+        T*    pPrev;
+        void* pVoidPrev;
+    };
+    union {
+        T*    pNext;
+        void* pVoidNext;
+    };
+
+    void    RemoveNode()
+    {
+        pPrev->pNext = pNext;
+        pNext->pPrev = pPrev;
+    }
+
+    // Removes us from the list and inserts pnew there instead.
+    void    ReplaceNodeWith(T* pnew)
+    {
+        pPrev->pNext = pnew;
+        pNext->pPrev = pnew;
+        pnew->pPrev = pPrev;
+        pnew->pNext = pNext;
+    }
+       
+    // Inserts the argument linked list node after us in the list.
+    void    InsertNodeAfter(T* p)
+    {
+        p->pPrev          = pNext->pPrev; // this
+        p->pNext          = pNext;
+        pNext->pPrev      = p;
+        pNext             = p;
+    }
+    // Inserts the argument linked list node before us in the list.
+    void    InsertNodeBefore(T* p)
+    {
+        p->pNext          = pNext->pPrev; // this
+        p->pPrev          = pPrev;
+        pPrev->pNext      = p;
+        pPrev             = p;
+    }
+
+    void    Alloc_MoveTo(ListNode<T>* pdest)
+    {
+        pdest->pNext = pNext;
+        pdest->pPrev = pPrev;
+        pPrev->pNext = (T*)pdest;
+        pNext->pPrev = (T*)pdest;
+    }
+};
+
+
+//------------------------------------------------------------------------
+// ***** List
+//
+// Doubly linked intrusive list. 
+// The data type must be derived from ListNode.
+// 
+// Adding:   PushFront(), PushBack().
+// Removing: Remove() - the element must be in the list!
+// Moving:   BringToFront(), SendToBack() - the element must be in the list!
+//
+// Iterating:
+//    MyData* data = MyList.GetFirst();
+//    while (!MyList.IsNull(data))
+//    {
+//        . . .
+//        data = MyList.GetNext(data);
+//    }
+//
+// Removing:
+//    MyData* data = MyList.GetFirst();
+//    while (!MyList.IsNull(data))
+//    {
+//        MyData* next = MyList.GetNext(data);
+//        if (ToBeRemoved(data))
+//             MyList.Remove(data);
+//        data = next;
+//    }
+//
+
+// List<> represents a doubly-linked list of T, where each T must derive
+// from ListNode<B>. B specifies the base class that was directly
+// derived from ListNode, and is only necessary if there is an intermediate
+// inheritance chain.
+
+template<class T, class B = T> class List
+{
+public:
+    typedef T ValueType;
+
+    List()
+    {
+        Root.pNext = Root.pPrev = (ValueType*)&Root;
+    }
+
+    void Clear()
+    {
+        Root.pNext = Root.pPrev = (ValueType*)&Root;
+    }
+
+    const ValueType* GetFirst() const { return (const ValueType*)Root.pNext; }
+    const ValueType* GetLast () const { return (const ValueType*)Root.pPrev; }
+          ValueType* GetFirst()       { return (ValueType*)Root.pNext; }
+          ValueType* GetLast ()       { return (ValueType*)Root.pPrev; }
+
+    // Determine if list is empty (i.e.) points to itself.
+    // Go through void* access to avoid issues with strict-aliasing optimizing out the
+    // access after RemoveNode(), etc.
+    bool IsEmpty()                   const { return Root.pVoidNext == (const T*)(const B*)&Root; }
+    bool IsFirst(const ValueType* p) const { return p == Root.pNext; }
+    bool IsLast (const ValueType* p) const { return p == Root.pPrev; }
+    bool IsNull (const ValueType* p) const { return p == (const T*)(const B*)&Root; }
+
+    inline static const ValueType* GetPrev(const ValueType* p) { return (const ValueType*)p->pPrev; }
+    inline static const ValueType* GetNext(const ValueType* p) { return (const ValueType*)p->pNext; }
+    inline static       ValueType* GetPrev(      ValueType* p) { return (ValueType*)p->pPrev; }
+    inline static       ValueType* GetNext(      ValueType* p) { return (ValueType*)p->pNext; }
+
+    void PushFront(ValueType* p)
+    {
+        p->pNext          =  Root.pNext;
+        p->pPrev          = (ValueType*)&Root;
+        Root.pNext->pPrev =  p;
+        Root.pNext        =  p;
+    }
+
+    void PushBack(ValueType* p)
+    {
+        p->pPrev          =  Root.pPrev;
+        p->pNext          = (ValueType*)&Root;
+        Root.pPrev->pNext =  p;
+        Root.pPrev        =  p;
+    }
+
+    static void Remove(ValueType* p)
+    {
+        p->pPrev->pNext = p->pNext;
+        p->pNext->pPrev = p->pPrev;
+    }
+
+    void BringToFront(ValueType* p)
+    {
+        Remove(p);
+        PushFront(p);
+    }
+
+    void SendToBack(ValueType* p)
+    {
+        Remove(p);
+        PushBack(p);
+    }
+
+    // Appends the contents of the argument list to the front of this list;
+    // items are removed from the argument list.
+    void PushListToFront(List<T>& src)
+    {
+        if (!src.IsEmpty())
+        {
+            ValueType* pfirst = src.GetFirst();
+            ValueType* plast  = src.GetLast();
+            src.Clear();
+            plast->pNext   = Root.pNext;
+            pfirst->pPrev  = (ValueType*)&Root;
+            Root.pNext->pPrev = plast;
+            Root.pNext        = pfirst;
+        }
+    }
+
+    void PushListToBack(List<T>& src)
+    {
+        if (!src.IsEmpty())
+        {
+            ValueType* pfirst = src.GetFirst();
+            ValueType* plast  = src.GetLast();
+            src.Clear();
+            plast->pNext   = (ValueType*)&Root;
+            pfirst->pPrev  = Root.pPrev;
+            Root.pPrev->pNext = pfirst;
+            Root.pPrev        = plast;
+        }
+    }
+
+    // Removes all source list items after (and including) the 'pfirst' node from the 
+    // source list and adds them to out list.
+    void    PushFollowingListItemsToFront(List<T>& src, ValueType *pfirst)
+    {
+        if (pfirst != &src.Root)
+        {
+            ValueType *plast = src.Root.pPrev;
+
+            // Remove list remainder from source.
+            pfirst->pPrev->pNext = (ValueType*)&src.Root;
+            src.Root.pPrev      = pfirst->pPrev;
+            // Add the rest of the items to list.
+            plast->pNext      = Root.pNext;
+            pfirst->pPrev     = (ValueType*)&Root;
+            Root.pNext->pPrev = plast;
+            Root.pNext        = pfirst;
+        }
+    }
+
+    // Removes all source list items up to but NOT including the 'pend' node from the 
+    // source list and adds them to out list.
+    void    PushPrecedingListItemsToFront(List<T>& src, ValueType *ptail)
+    {
+        if (src.GetFirst() != ptail)
+        {
+            ValueType *pfirst = src.Root.pNext;
+            ValueType *plast  = ptail->pPrev;
+
+            // Remove list remainder from source.
+            ptail->pPrev      = (ValueType*)&src.Root;
+            src.Root.pNext    = ptail;            
+
+            // Add the rest of the items to list.
+            plast->pNext      = Root.pNext;
+            pfirst->pPrev     = (ValueType*)&Root;
+            Root.pNext->pPrev = plast;
+            Root.pNext        = pfirst;
+        }
+    }
+
+
+    // Removes a range of source list items starting at 'pfirst' and up to, but not including 'pend',
+    // and adds them to out list. Note that source items MUST already be in the list.
+    void    PushListItemsToFront(ValueType *pfirst, ValueType *pend)
+    {
+        if (pfirst != pend)
+        {
+            ValueType *plast = pend->pPrev;
+
+            // Remove list remainder from source.
+            pfirst->pPrev->pNext = pend;
+            pend->pPrev          = pfirst->pPrev;
+            // Add the rest of the items to list.
+            plast->pNext      = Root.pNext;
+            pfirst->pPrev     = (ValueType*)&Root;
+            Root.pNext->pPrev = plast;
+            Root.pNext        = pfirst;
+        }
+    }
+
+
+    void    Alloc_MoveTo(List<T>* pdest)
+    {
+        if (IsEmpty())
+            pdest->Clear();
+        else
+        {
+            pdest->Root.pNext = Root.pNext;
+            pdest->Root.pPrev = Root.pPrev;
+
+            Root.pNext->pPrev = (ValueType*)&pdest->Root;
+            Root.pPrev->pNext = (ValueType*)&pdest->Root;
+        }        
+    }
+
+
+private:
+    // Copying is prohibited
+    List(const List<T>&);
+    const List<T>& operator = (const List<T>&);
+
+    ListNode<B> Root;
+};
+
+
+//------------------------------------------------------------------------
+// ***** FreeListElements
+//
+// Remove all elements in the list and free them in the allocator
+
+template<class List, class Allocator>
+void FreeListElements(List& list, Allocator& allocator)
+{
+    typename List::ValueType* self = list.GetFirst();
+    while(!list.IsNull(self))
+    {
+        typename List::ValueType* next = list.GetNext(self);
+        allocator.Free(self);
+        self = next;
+    }
+    list.Clear();
+}
+
+} // OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_Lockless.cpp b/LibOVR/Src/Kernel/OVR_Lockless.cpp
new file mode 100644
index 0000000..0f25805
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Lockless.cpp
@@ -0,0 +1,231 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Lockless.cpp
+Content     :   Test logic for lock-less classes
+Created     :   December 27, 2013
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_Lockless.h"
+
+#ifdef OVR_LOCKLESS_TEST
+
+#include "OVR_Threads.h"
+#include "OVR_Timer.h"
+#include "OVR_Log.h"
+
+
+namespace OVR { namespace LocklessTest {
+
+
+const int TestIterations = 10000000;
+
+// Use volatile dummys to force compiler to do spinning.
+volatile int Dummy1;
+int          Unused1[32];
+volatile int Dummy2;
+int          Unused2[32];
+volatile int Dummy3;
+int          Unused3[32];
+
+
+// Data block out of 20 consecutive integers, should be internally consistent.
+struct TestData
+{
+    enum { ItemCount = 20 };
+
+    int Data[ItemCount];
+
+
+    void Set(int val)
+    {
+        for (int i=0; i<ItemCount; i++)
+        {
+            Data[i] = val*100 + i;
+        }
+    }
+
+    int ReadAndCheckConsistency(int prevValue) const
+    {
+        int val = Data[0];
+
+        for (int i=1; i<ItemCount; i++)
+        {
+            
+            if (Data[i] != (val + i))
+            {
+                // Only complain once per same-value entry
+                if (prevValue != val / 100) 
+                {
+                    LogText("LocklessTest Fail - corruption at %d inside block %d\n",
+                            i, val/100);
+                    // OVR_ASSERT(Data[i] == val + i);
+                }
+                break;
+            }
+        }
+
+        return val / 100;
+    }
+};
+
+
+
+volatile bool              FirstItemWritten = false;
+LocklessUpdater<TestData>  TestDataUpdater;
+
+// Use this lock to verify that testing algorithm is otherwise correct...
+Lock                       TestLock;   
+
+
+//-------------------------------------------------------------------------------------
+
+// Consumer thread reads values from TestDataUpdater and
+// ensures that each one is internally consistent.
+
+class Consumer : public Thread
+{
+    virtual int Run()
+    {
+        LogText("LocklessTest::Consumer::Run started.\n");
+        
+
+        while (!FirstItemWritten)
+        {
+            // spin until producer wrote first value...
+        }
+
+        TestData d;
+        int      oldValue = 0;
+        int      newValue;
+
+        do 
+        {
+            {
+                //Lock::Locker scope(&TestLock);
+                d = TestDataUpdater.GetState();
+            }
+            
+            newValue = d.ReadAndCheckConsistency(oldValue);
+            
+            // Values should increase or stay the same!
+            if (newValue < oldValue)
+            {
+                LogText("LocklessTest Fail - %d after %d;  delta = %d\n",
+                        newValue, oldValue, newValue - oldValue);
+         //       OVR_ASSERT(0);
+            }
+            
+
+            if (oldValue != newValue)
+            {
+                oldValue = newValue;
+
+                if (oldValue % (TestIterations/30) == 0)
+                {
+                    LogText("LocklessTest::Consumer - %5.2f%% done\n",
+                            100.0f * (float)oldValue/(float)TestIterations);
+                }
+            }            
+
+            // Spin a while
+            for (int j = 0; j< 300; j++)
+            {
+                Dummy3 = j;
+            }
+
+
+        } while (oldValue < (TestIterations * 99 / 100));
+
+        LogText("LocklessTest::Consumer::Run exiting.\n");
+        return 0;
+    }
+
+};
+
+
+//-------------------------------------------------------------------------------------
+
+class Producer : public Thread
+{
+
+    virtual int Run()
+    {
+        LogText("LocklessTest::Producer::Run started.\n");        
+
+        for (int testVal = 0; testVal < TestIterations; testVal++)
+        {
+            TestData d;
+            d.Set(testVal);
+
+            {
+                //Lock::Locker scope(&TestLock);
+                TestDataUpdater.SetState(d);
+            }
+
+            FirstItemWritten = true;
+
+            // Spin a bit
+            for(int j = 0; j < 1000; j++)
+            {
+                Dummy2 = j;
+            }
+
+            if (testVal % (TestIterations/30) == 0)
+            {
+                LogText("LocklessTest::Producer - %5.2f%% done\n",
+                        100.0f * (float)testVal/(float)TestIterations);
+            }
+        }
+
+        LogText("LocklessTest::Producer::Run exiting.\n");
+        return 0;
+    }
+};
+
+
+} // namespace LocklessTest
+
+
+
+void StartLocklessTest()
+{
+    // These threads will release themselves once done
+    Ptr<LocklessTest::Producer> producerThread = *new LocklessTest::Producer;
+    Ptr<LocklessTest::Consumer> consumerThread = *new LocklessTest::Consumer;
+
+    producerThread->Start();
+    consumerThread->Start();
+
+    /*
+    while (!producerThread->IsFinished() && consumerThread->IsFinished())
+    {
+        Thread::MSleep(500);
+    } */
+
+    // TBD: Cleanup
+}
+
+
+} // namespace OVR
+
+#endif // OVR_LOCKLESS_TEST
diff --git a/LibOVR/Src/Kernel/OVR_Lockless.h b/LibOVR/Src/Kernel/OVR_Lockless.h
new file mode 100644
index 0000000..a12f824
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Lockless.h
@@ -0,0 +1,107 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Lockless.h
+Content     :   Lock-less classes for producer/consumer communication
+Created     :   November 9, 2013
+Authors     :   John Carmack
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Lockless_h
+#define OVR_Lockless_h
+
+#include "OVR_Atomic.h"
+
+// Define this to compile-in Lockless test logic
+//#define OVR_LOCKLESS_TEST
+
+namespace OVR {
+
+
+// ***** LocklessUpdater
+
+// For single producer cases where you only care about the most recent update, not
+// necessarily getting every one that happens (vsync timing, SensorFusion updates).
+//
+// This is multiple consumer safe, but is currently only used with a single consumer.
+
+template<class T>
+class LocklessUpdater
+{
+public:
+	LocklessUpdater() : UpdateBegin( 0 ), UpdateEnd( 0 ) {}
+
+	T		GetState() const
+	{
+		// Copy the state out, then retry with the alternate slot
+		// if we determine that our copy may have been partially
+		// stepped on by a new update.
+		T	state;
+		int	begin, end, final;
+
+		for(;;)
+		{
+			// We are adding 0, only using these as atomic memory barriers, so it
+			// is ok to cast off the const, allowing GetState() to remain const.
+            end   = UpdateEnd.ExchangeAdd_Sync(0);
+            state = Slots[ end & 1 ];
+            begin = UpdateBegin.ExchangeAdd_Sync(0);
+			if ( begin == end ) {
+				break;
+			}
+
+			// The producer is potentially blocked while only having partially
+			// written the update, so copy out the other slot.
+            state = Slots[ (begin & 1) ^ 1 ];
+            final = UpdateBegin.ExchangeAdd_NoSync(0);
+			if ( final == begin ) {
+				break;
+			}
+
+			// The producer completed the last update and started a new one before
+			// we got it copied out, so try fetching the current buffer again.
+		}
+		return state;
+	}
+
+	void	SetState( T state )
+	{
+        const int slot = UpdateBegin.ExchangeAdd_Sync(1) & 1;
+        // Write to (slot ^ 1) because ExchangeAdd returns 'previous' value before add.
+        Slots[slot ^ 1] = state;
+        UpdateEnd.ExchangeAdd_Sync(1);
+	}
+
+    mutable AtomicInt<int> UpdateBegin;
+    mutable AtomicInt<int> UpdateEnd;
+    T		               Slots[2];
+};
+
+
+#ifdef OVR_LOCKLESS_TEST
+void StartLocklessTest();
+#endif
+
+
+} // namespace OVR
+
+#endif // OVR_Lockless_h
+
diff --git a/LibOVR/Src/Kernel/OVR_Log.cpp b/LibOVR/Src/Kernel/OVR_Log.cpp
new file mode 100644
index 0000000..d5f8a68
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Log.cpp
@@ -0,0 +1,184 @@
+/************************************************************************************
+
+Filename    :   OVR_Log.cpp
+Content     :   Logging support
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_Log.h"
+#include "OVR_Std.h"
+#include <stdarg.h>
+#include <stdio.h>
+
+#if defined(OVR_OS_WIN32)
+#include <windows.h>
+#elif defined(OVR_OS_ANDROID)
+#include <android/log.h>
+#endif
+
+namespace OVR {
+
+// Global Log pointer.
+Log* volatile OVR_GlobalLog = 0;
+
+//-----------------------------------------------------------------------------------
+// ***** Log Implementation
+
+Log::~Log()
+{
+    // Clear out global log
+    if (this == OVR_GlobalLog)
+    {
+        // TBD: perhaps we should ASSERT if this happens before system shutdown?
+        OVR_GlobalLog = 0;
+    }
+}
+
+void Log::LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList)
+{
+    if ((messageType & LoggingMask) == 0)
+        return;
+#ifndef OVR_BUILD_DEBUG
+    if (IsDebugMessage(messageType))
+        return;
+#endif
+
+    char buffer[MaxLogBufferMessageSize];
+    FormatLog(buffer, MaxLogBufferMessageSize, messageType, fmt, argList);
+    DefaultLogOutput(buffer, IsDebugMessage(messageType));
+}
+
+void OVR::Log::LogMessage(LogMessageType messageType, const char* pfmt, ...)
+{
+    va_list argList;
+    va_start(argList, pfmt);
+    LogMessageVarg(messageType, pfmt, argList);
+    va_end(argList);
+}
+
+
+void Log::FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType,
+                    const char* fmt, va_list argList)
+{    
+    bool addNewline = true;
+
+    switch(messageType)
+    {
+    case Log_Error:         OVR_strcpy(buffer, bufferSize, "Error: ");     break;
+    case Log_Debug:         OVR_strcpy(buffer, bufferSize, "Debug: ");     break;
+    case Log_Assert:        OVR_strcpy(buffer, bufferSize, "Assert: ");    break;
+    case Log_Text:       buffer[0] = 0; addNewline = false; break;
+    case Log_DebugText:  buffer[0] = 0; addNewline = false; break;
+    default:        
+        buffer[0] = 0;
+        addNewline = false;
+        break;
+    }
+
+    UPInt prefixLength = OVR_strlen(buffer);
+    char *buffer2      = buffer + prefixLength;
+    OVR_vsprintf(buffer2, bufferSize - prefixLength, fmt, argList);
+
+    if (addNewline)
+        OVR_strcat(buffer, bufferSize, "\n");
+}
+
+
+void Log::DefaultLogOutput(const char* formattedText, bool debug)
+{
+
+#if defined(OVR_OS_WIN32)
+    // Under Win32, output regular messages to console if it exists; debug window otherwise.
+    static DWORD dummyMode;
+    static bool  hasConsole = (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE) &&
+                              (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &dummyMode));
+
+    if (!hasConsole || debug)
+    {
+        ::OutputDebugStringA(formattedText);
+    }
+    else
+    {
+         fputs(formattedText, stdout);
+    }    
+
+#elif defined(OVR_OS_ANDROID)
+    __android_log_write(ANDROID_LOG_INFO, "OVR", formattedText);
+
+#else
+    fputs(formattedText, stdout);
+
+#endif
+
+    // Just in case.
+    OVR_UNUSED2(formattedText, debug);
+}
+
+
+//static
+void Log::SetGlobalLog(Log *log)
+{
+    OVR_GlobalLog = log;
+}
+//static
+Log* Log::GetGlobalLog()
+{
+// No global log by default?
+//    if (!OVR_GlobalLog)
+//        OVR_GlobalLog = GetDefaultLog();
+    return OVR_GlobalLog;
+}
+
+//static
+Log* Log::GetDefaultLog()
+{
+    // Create default log pointer statically so that it can be used
+    // even during startup.
+    static Log defaultLog;
+    return &defaultLog;
+}
+
+
+//-----------------------------------------------------------------------------------
+// ***** Global Logging functions
+
+#define OVR_LOG_FUNCTION_IMPL(Name)  \
+    void Log##Name(const char* fmt, ...) \
+    {                                                                    \
+        if (OVR_GlobalLog)                                               \
+        {                                                                \
+            va_list argList; va_start(argList, fmt);                     \
+            OVR_GlobalLog->LogMessageVarg(Log_##Name, fmt, argList);  \
+            va_end(argList);                                             \
+        }                                                                \
+    }
+
+OVR_LOG_FUNCTION_IMPL(Text)
+OVR_LOG_FUNCTION_IMPL(Error)
+
+#ifdef OVR_BUILD_DEBUG
+OVR_LOG_FUNCTION_IMPL(DebugText)
+OVR_LOG_FUNCTION_IMPL(Debug)
+OVR_LOG_FUNCTION_IMPL(Assert)
+#endif
+
+} // OVR
diff --git a/LibOVR/Src/Kernel/OVR_Log.h b/LibOVR/Src/Kernel/OVR_Log.h
new file mode 100644
index 0000000..4d9acc1
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Log.h
@@ -0,0 +1,204 @@
+/************************************************************************************
+
+PublicHeader:   OVR
+Filename    :   OVR_Log.h
+Content     :   Logging support
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Log_h
+#define OVR_Log_h
+
+#include "OVR_Types.h"
+#include <stdarg.h>
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** Logging Constants
+
+// LogMaskConstants defined bit mask constants that describe what log messages
+// should be displayed.
+enum LogMaskConstants
+{
+    LogMask_Regular = 0x100,
+    LogMask_Debug   = 0x200,
+    LogMask_None    = 0,
+    LogMask_All     = LogMask_Regular|LogMask_Debug
+};
+
+
+// LogMessageType describes the type of the log message, controls when it is
+// displayed and what prefix/suffix is given to it. Messages are subdivided into
+// regular and debug logging types. Debug logging is only generated in debug builds.
+//
+// Log_Text         - General output text displayed without prefix or new-line.
+//                    Used in OVR libraries for general log flow messages
+//                    such as "Device Initialized".
+//
+// Log_Error        - Error message output with "Error: %s\n", intended for
+//                    application/sample-level use only, in cases where an expected
+//                    operation failed. OVR libraries should not use this internally,
+//                    reporting status codes instead.
+//
+// Log_DebugText    - Message without prefix or new lines; output in Debug build only.
+//
+// Log_Debug        - Debug-build only message, formatted with "Debug: %s\n".
+//                    Intended to comment on incorrect API usage that doesn't lead
+//                    to crashes but can be avoided with proper use.
+//                    There is no Debug Error on purpose, since real errors should
+//                    be handled by API user.
+//
+// Log_Assert      -  Debug-build only message, formatted with "Assert: %s\n".
+//                    Intended for severe unrecoverable conditions in library
+//                    source code. Generated though OVR_ASSERT_MSG(c, "Text").
+
+enum LogMessageType
+{    
+    // General Logging
+    Log_Text        = LogMask_Regular | 0,    
+    Log_Error       = LogMask_Regular | 1, // "Error: %s\n".
+    
+    // Debug-only messages (not generated in release build)
+    Log_DebugText   = LogMask_Debug | 0,
+    Log_Debug       = LogMask_Debug | 1,   // "Debug: %s\n".
+    Log_Assert      = LogMask_Debug | 2,   // "Assert: %s\n".
+};
+
+
+// LOG_VAARG_ATTRIBUTE macro, enforces printf-style fromatting for message types
+#ifdef __GNUC__
+#  define OVR_LOG_VAARG_ATTRIBUTE(a,b) __attribute__((format (printf, a, b)))
+#else
+#  define OVR_LOG_VAARG_ATTRIBUTE(a,b)
+#endif
+
+
+//-----------------------------------------------------------------------------------
+// ***** Log
+
+// Log defines a base class interface that can be implemented to catch both
+// debug and runtime messages.
+// Debug logging can be overridden by calling Log::SetGlobalLog.
+
+class Log
+{
+    friend class System;
+public: 
+    Log(unsigned logMask = LogMask_Debug) : LoggingMask(logMask) { }
+    virtual ~Log();
+
+    // Log formating buffer size used by default LogMessageVarg. Longer strings are truncated.
+    enum { MaxLogBufferMessageSize = 4096 };
+
+    unsigned        GetLoggingMask() const            { return LoggingMask; }
+    void            SetLoggingMask(unsigned logMask)  { LoggingMask = logMask; }
+
+    // This virtual function receives all the messages,
+    // developers should override this function in order to do custom logging
+    virtual void    LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList);
+
+    // Call the logging function with specific message type, with no type filtering.
+    void            LogMessage(LogMessageType messageType,
+                               const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(3,4);
+
+
+    // Helper used by LogMessageVarg to format the log message, writing the resulting
+    // string into buffer. It formats text based on fmt and appends prefix/new line
+    // based on LogMessageType.
+    static void     FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType,
+                              const char* fmt, va_list argList);
+
+    // Default log output implementation used by by LogMessageVarg.
+    // Debug flag may be used to re-direct output on some platforms, but doesn't
+    // necessarily disable it in release builds; that is the job of the called.    
+    static void     DefaultLogOutput(const char* textBuffer, bool debug);
+
+    // Determines if the specified message type is for debugging only.
+    static bool     IsDebugMessage(LogMessageType messageType)
+    {
+        return (messageType & LogMask_Debug) != 0;
+    }
+
+    // *** Global APIs
+
+    // Global Log registration APIs.
+    //  - Global log is used for OVR_DEBUG messages. Set global log to null (0)
+    //    to disable all logging.
+    static void     SetGlobalLog(Log *log);
+    static Log*     GetGlobalLog();
+
+    // Returns default log singleton instance.
+    static Log*     GetDefaultLog();
+
+    // Applies logMask to the default log and returns a pointer to it.
+    // By default, only Debug logging is enabled, so to avoid SDK generating console
+    // messages in user app (those are always disabled in release build,
+    // even if the flag is set). This function is useful in System constructor.
+    static Log*     ConfigureDefaultLog(unsigned logMask = LogMask_Debug)
+    {
+        Log* log = GetDefaultLog();
+        log->SetLoggingMask(logMask);
+        return log;
+    }
+
+private:
+    // Logging mask described by LogMaskConstants.
+    unsigned    LoggingMask;
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** Global Logging Functions and Debug Macros
+
+// These functions will output text to global log with semantics described by
+// their LogMessageType.
+void LogText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
+void LogError(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
+
+#ifdef OVR_BUILD_DEBUG
+
+    // Debug build only logging.
+    void LogDebugText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
+    void LogDebug(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
+    void LogAssert(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
+
+    // Macro to do debug logging, printf-style.
+    // An extra set of set of parenthesis must be used around arguments,
+    // as in: OVR_LOG_DEBUG(("Value %d", 2)).
+    #define OVR_DEBUG_LOG(args)       do { OVR::LogDebug args; } while(0)
+    #define OVR_DEBUG_LOG_TEXT(args)  do { OVR::LogDebugText args; } while(0)
+
+    #define OVR_ASSERT_LOG(c, args)   do { if (!(c)) { OVR::LogAssert args; OVR_DEBUG_BREAK; } } while(0)
+
+#else
+
+    // If not in debug build, macros do nothing.
+    #define OVR_DEBUG_LOG(args)         ((void)0)
+    #define OVR_DEBUG_LOG_TEXT(args)    ((void)0)
+    #define OVR_ASSERT_LOG(c, args)     ((void)0)
+
+#endif
+
+} // OVR 
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_Math.cpp b/LibOVR/Src/Kernel/OVR_Math.cpp
new file mode 100644
index 0000000..396d3ff
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Math.cpp
@@ -0,0 +1,91 @@
+/************************************************************************************
+
+Filename    :   OVR_Math.h
+Content     :   Implementation of 3D primitives such as vectors, matrices.
+Created     :   September 4, 2012
+Authors     :   Andrew Reisse, Michael Antonov, Anna Yershova
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_Math.h"
+#include "OVR_Log.h"
+
+#include <float.h>
+
+
+namespace OVR {
+
+
+//-------------------------------------------------------------------------------------
+// ***** Math
+
+
+// Single-precision Math constants class.
+const float Math<float>::Pi      = 3.1415926f;
+const float Math<float>::TwoPi   = 3.1415926f * 2;
+const float Math<float>::PiOver2 = 3.1415926f / 2.0f;
+const float Math<float>::PiOver4 = 3.1415926f / 4.0f;
+const float Math<float>::E       = 2.7182818f;
+
+const float Math<float>::MaxValue			= FLT_MAX;
+const float Math<float>::MinPositiveValue	= FLT_MIN;
+
+const float Math<float>::RadToDegreeFactor	= 360.0f / Math<float>::TwoPi;
+const float Math<float>::DegreeToRadFactor	= Math<float>::TwoPi / 360.0f;
+
+const float Math<float>::Tolerance			= 0.00001f;
+const float Math<float>::SingularityRadius	= 0.0000001f; // Use for Gimbal lock numerical problems
+
+// Double-precision Math constants class.
+const double Math<double>::Pi      = 3.14159265358979;
+const double Math<double>::TwoPi   = 3.14159265358979 * 2;
+const double Math<double>::PiOver2 = 3.14159265358979 / 2.0;
+const double Math<double>::PiOver4 = 3.14159265358979 / 4.0;
+const double Math<double>::E       = 2.71828182845905;
+
+const double Math<double>::MaxValue				= DBL_MAX;
+const double Math<double>::MinPositiveValue		= DBL_MIN;
+
+const double Math<double>::RadToDegreeFactor	= 360.0 / Math<double>::TwoPi;
+const double Math<double>::DegreeToRadFactor	= Math<double>::TwoPi / 360.0;
+
+const double Math<double>::Tolerance			= 0.00001;
+const double Math<double>::SingularityRadius	= 0.000000000001; // Use for Gimbal lock numerical problems
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** Matrix4
+
+template<>
+const Matrix4<float> Matrix4<float>::IdentityValue = Matrix4<float>(1.0f, 0.0f, 0.0f, 0.0f, 
+                                                                    0.0f, 1.0f, 0.0f, 0.0f, 
+                                                                    0.0f, 0.0f, 1.0f, 0.0f,
+                                                                    0.0f, 0.0f, 0.0f, 1.0f);
+
+template<>
+const Matrix4<double> Matrix4<double>::IdentityValue = Matrix4<double>(1.0, 0.0, 0.0, 0.0, 
+                                                                       0.0, 1.0, 0.0, 0.0, 
+                                                                       0.0, 0.0, 1.0, 0.0,
+                                                                       0.0, 0.0, 0.0, 1.0);
+
+
+
+} // Namespace OVR
diff --git a/LibOVR/Src/Kernel/OVR_Math.h b/LibOVR/Src/Kernel/OVR_Math.h
new file mode 100644
index 0000000..4aa42b0
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Math.h
@@ -0,0 +1,2526 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Math.h
+Content     :   Implementation of 3D primitives such as vectors, matrices.
+Created     :   September 4, 2012
+Authors     :   Andrew Reisse, Michael Antonov, Steve LaValle, 
+				Anna Yershova, Max Katsev, Dov Katz
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Math_h
+#define OVR_Math_h
+
+#include <assert.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "OVR_Types.h"
+#include "OVR_RefCount.h"
+#include "OVR_Std.h"
+#include "OVR_Alg.h"
+
+
+namespace OVR {
+
+//-------------------------------------------------------------------------------------
+// ***** Constants for 3D world/axis definitions.
+
+// Definitions of axes for coordinate and rotation conversions.
+enum Axis
+{
+    Axis_X = 0, Axis_Y = 1, Axis_Z = 2
+};
+
+// RotateDirection describes the rotation direction around an axis, interpreted as follows:
+//  CW  - Clockwise while looking "down" from positive axis towards the origin.
+//  CCW - Counter-clockwise while looking from the positive axis towards the origin,
+//        which is in the negative axis direction.
+//  CCW is the default for the RHS coordinate system. Oculus standard RHS coordinate
+//  system defines Y up, X right, and Z back (pointing out from the screen). In this
+//  system Rotate_CCW around Z will specifies counter-clockwise rotation in XY plane.
+enum RotateDirection
+{
+    Rotate_CCW = 1,
+    Rotate_CW  = -1 
+};
+
+// Constants for right handed and left handed coordinate systems
+enum HandedSystem
+{
+    Handed_R = 1, Handed_L = -1
+};
+
+// AxisDirection describes which way the coordinate axis points. Used by WorldAxes.
+enum AxisDirection
+{
+    Axis_Up    =  2,
+    Axis_Down  = -2,
+    Axis_Right =  1,
+    Axis_Left  = -1,
+    Axis_In    =  3,
+    Axis_Out   = -3
+};
+
+struct WorldAxes
+{
+    AxisDirection XAxis, YAxis, ZAxis;
+
+    WorldAxes(AxisDirection x, AxisDirection y, AxisDirection z)
+        : XAxis(x), YAxis(y), ZAxis(z) 
+    { OVR_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));}
+};
+
+} // namespace OVR
+
+
+//------------------------------------------------------------------------------------//
+// ***** C Compatibility Types
+
+// These declarations are used to support conversion between C types used in
+// LibOVR C interfaces and their C++ versions. As an example, they allow passing
+// Vector3f into a function that expects ovrVector3f.
+
+typedef struct ovrQuatf_ ovrQuatf;
+typedef struct ovrQuatd_ ovrQuatd;
+typedef struct ovrSizei_ ovrSizei;
+typedef struct ovrSizef_ ovrSizef;
+typedef struct ovrRecti_ ovrRecti;
+typedef struct ovrVector2i_ ovrVector2i;
+typedef struct ovrVector2f_ ovrVector2f;
+typedef struct ovrVector3f_ ovrVector3f;
+typedef struct ovrVector3d_ ovrVector3d;
+typedef struct ovrMatrix3d_ ovrMatrix3d;
+typedef struct ovrMatrix4f_ ovrMatrix4f;
+typedef struct ovrPosef_ ovrPosef;
+typedef struct ovrPosed_ ovrPosed;
+typedef struct ovrPoseStatef_ ovrPoseStatef;
+typedef struct ovrPoseStated_ ovrPoseStated;
+
+namespace OVR {
+
+// Forward-declare our templates.
+template<class T> class Quat;
+template<class T> class Size;
+template<class T> class Rect;
+template<class T> class Vector2;
+template<class T> class Vector3;
+template<class T> class Matrix3;
+template<class T> class Matrix4;
+template<class T> class Transform;
+template<class T> class PoseState;
+
+// CompatibleTypes::Type is used to lookup a compatible C-version of a C++ class.
+template<class C>
+struct CompatibleTypes
+{    
+    // Declaration here seems necessary for MSVC; specializations are
+    // used instead.
+    typedef float Type;
+};
+
+// Specializations providing CompatibleTypes::Type value.
+template<> struct CompatibleTypes<Quat<float> >     { typedef ovrQuatf Type; };
+template<> struct CompatibleTypes<Quat<double> >    { typedef ovrQuatd Type; };
+template<> struct CompatibleTypes<Matrix3<double> > { typedef ovrMatrix3d Type; };
+template<> struct CompatibleTypes<Matrix4<float> >  { typedef ovrMatrix4f Type; };
+template<> struct CompatibleTypes<Size<int> >       { typedef ovrSizei Type; };
+template<> struct CompatibleTypes<Size<float> >     { typedef ovrSizef Type; };
+template<> struct CompatibleTypes<Rect<int> >       { typedef ovrRecti Type; };
+template<> struct CompatibleTypes<Vector2<int> >    { typedef ovrVector2i Type; };
+template<> struct CompatibleTypes<Vector2<float> >  { typedef ovrVector2f Type; };
+template<> struct CompatibleTypes<Vector3<float> >  { typedef ovrVector3f Type; };
+template<> struct CompatibleTypes<Vector3<double> > { typedef ovrVector3d Type; };
+
+template<> struct CompatibleTypes<Transform<float> > { typedef ovrPosef Type; };
+template<> struct CompatibleTypes<PoseState<float> > { typedef ovrPoseStatef Type; };
+
+template<> struct CompatibleTypes<Transform<double> > { typedef ovrPosed Type; };
+template<> struct CompatibleTypes<PoseState<double> > { typedef ovrPoseStated Type; };
+
+//------------------------------------------------------------------------------------//
+// ***** Math
+//
+// Math class contains constants and functions. This class is a template specialized
+// per type, with Math<float> and Math<double> being distinct.
+template<class Type>
+class Math
+{  
+public:
+    // By default, support explicit conversion to float. This allows Vector2<int> to
+    // compile, for example.
+    typedef float OtherFloatType;
+};
+
+// Single-precision Math constants class.
+template<>
+class Math<float>
+{
+public:
+    static const float Pi;
+    static const float TwoPi;
+    static const float PiOver2;
+    static const float PiOver4;
+    static const float E;
+
+    static const float MaxValue;			// Largest positive float Value
+    static const float MinPositiveValue;	// Smallest possible positive value
+
+    static const float RadToDegreeFactor;
+    static const float DegreeToRadFactor;
+
+    static const float Tolerance;			// 0.00001f;
+    static const float SingularityRadius;	// 0.0000001f for Gimbal lock numerical problems
+
+    // Used to support direct conversions in template classes.
+    typedef double OtherFloatType;
+};
+
+// Double-precision Math constants class.
+template<>
+class Math<double>
+{
+public:
+    static const double Pi;
+    static const double TwoPi;
+    static const double PiOver2;
+    static const double PiOver4;
+    static const double E;
+
+    static const double MaxValue;			// Largest positive double Value
+    static const double MinPositiveValue;	// Smallest possible positive value
+
+    static const double RadToDegreeFactor;
+    static const double DegreeToRadFactor;
+
+    static const double Tolerance;			// 0.00001;
+    static const double SingularityRadius;	// 0.000000000001 for Gimbal lock numerical problems    
+
+    typedef float OtherFloatType;
+};
+
+
+typedef Math<float>  Mathf;
+typedef Math<double> Mathd;
+
+// Conversion functions between degrees and radians
+template<class T>
+T RadToDegree(T rads) { return rads * Math<T>::RadToDegreeFactor; }
+template<class T>
+T DegreeToRad(T rads) { return rads * Math<T>::DegreeToRadFactor; }
+
+// Numerically stable acos function
+template<class T>
+T Acos(T val) { 
+		if (val > T(1))				return T(0);
+		else if (val < T(-1))		return Math<T>::Pi;
+		else						return acos(val); 
+};
+
+// Numerically stable asin function
+template<class T>
+T Asin(T val) { 
+	if (val > T(1))				return Math<T>::PiOver2;
+	else if (val < T(-1))		return Math<T>::PiOver2 * T(3);
+	else						return asin(val); 
+};
+
+#ifdef OVR_CC_MSVC
+inline int isnan(double x) { return _isnan(x); };
+#endif
+
+template<class T>
+class Quat;
+
+
+//-------------------------------------------------------------------------------------
+// ***** Vector2<>
+
+// Vector2f (Vector2d) represents a 2-dimensional vector or point in space,
+// consisting of coordinates x and y
+
+template<class T>
+class Vector2
+{
+public:
+    T x, y;
+
+    Vector2() : x(0), y(0) { }
+    Vector2(T x_, T y_) : x(x_), y(y_) { }
+    explicit Vector2(T s) : x(s), y(s) { }
+    explicit Vector2(const Vector2<typename Math<T>::OtherFloatType> &src)
+        : x((T)src.x), y((T)src.y) { }
+
+
+    // C-interop support.
+    typedef  typename CompatibleTypes<Vector2<T> >::Type CompatibleType;
+
+    Vector2(const CompatibleType& s) : x(s.x), y(s.y) {  }
+
+    operator const CompatibleType& () const
+    {
+        OVR_COMPILER_ASSERT(sizeof(Vector2<T>) == sizeof(CompatibleType));
+        return reinterpret_cast<const CompatibleType&>(*this);
+    }
+
+        
+    bool     operator== (const Vector2& b) const  { return x == b.x && y == b.y; }
+    bool     operator!= (const Vector2& b) const  { return x != b.x || y != b.y; }
+             
+    Vector2  operator+  (const Vector2& b) const  { return Vector2(x + b.x, y + b.y); }
+    Vector2& operator+= (const Vector2& b)        { x += b.x; y += b.y; return *this; }
+    Vector2  operator-  (const Vector2& b) const  { return Vector2(x - b.x, y - b.y); }
+    Vector2& operator-= (const Vector2& b)        { x -= b.x; y -= b.y; return *this; }
+    Vector2  operator- () const                   { return Vector2(-x, -y); }
+
+    // Scalar multiplication/division scales vector.
+    Vector2  operator*  (T s) const               { return Vector2(x*s, y*s); }
+    Vector2& operator*= (T s)                     { x *= s; y *= s; return *this; }
+
+    Vector2  operator/  (T s) const               { T rcp = T(1)/s;
+                                                    return Vector2(x*rcp, y*rcp); }
+    Vector2& operator/= (T s)                     { T rcp = T(1)/s;
+                                                    x *= rcp; y *= rcp;
+                                                    return *this; }
+
+    static Vector2  Min(const Vector2& a, const Vector2& b) { return Vector2((a.x < b.x) ? a.x : b.x,
+                                                                             (a.y < b.y) ? a.y : b.y); }
+    static Vector2  Max(const Vector2& a, const Vector2& b) { return Vector2((a.x > b.x) ? a.x : b.x,
+                                                                             (a.y > b.y) ? a.y : b.y); }
+
+    // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
+    bool	Compare(const Vector2&b, T tolerance = Mathf::Tolerance)
+    {
+        return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance);
+    }
+    
+    // Entrywise product of two vectors
+    Vector2	EntrywiseMultiply(const Vector2& b) const	{ return Vector2(x * b.x, y * b.y);}
+
+
+    // Multiply and divide operators do entry-wise math. Used Dot() for dot product.
+    Vector2  operator*  (const Vector2& b) const        { return Vector2(x * b.x,  y * b.y); }
+    Vector2  operator/  (const Vector2& b) const        { return Vector2(x / b.x,  y / b.y); }
+
+	// Dot product
+    // Used to calculate angle q between two vectors among other things,
+    // as (A dot B) = |a||b|cos(q).
+    T		Dot(const Vector2& b) const                 { return x*b.x + y*b.y; }
+
+    // Returns the angle from this vector to b, in radians.
+    T       Angle(const Vector2& b) const        
+	{ 
+		T div = LengthSq()*b.LengthSq();
+		OVR_ASSERT(div != T(0));
+		T result = Acos((this->Dot(b))/sqrt(div));
+		return result;
+	}
+
+    // Return Length of the vector squared.
+    T       LengthSq() const                     { return (x * x + y * y); }
+
+    // Return vector length.
+    T       Length() const                       { return sqrt(LengthSq()); }
+
+    // Returns squared distance between two points represented by vectors.
+    T       DistanceSq(Vector2& b) const         { return (*this - b).LengthSq(); }
+
+	// Returns distance between two points represented by vectors.
+    T       Distance(Vector2& b) const           { return (*this - b).Length(); }
+
+	// Determine if this a unit vector.
+    bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
+
+    // Normalize, convention vector length to 1.    
+    void    Normalize()                          
+	{
+		T l = Length();
+		OVR_ASSERT(l != T(0));
+		*this /= l; 
+	}
+    // Returns normalized (unit) version of the vector without modifying itself.
+    Vector2 Normalized() const                   
+	{ 
+		T l = Length();
+		OVR_ASSERT(l != T(0));
+		return *this / l; 
+	}
+
+    // Linearly interpolates from this vector to another.
+    // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
+    Vector2 Lerp(const Vector2& b, T f) const    { return *this*(T(1) - f) + b*f; }
+
+    // Projects this vector onto the argument; in other words,
+    // A.Project(B) returns projection of vector A onto B.
+    Vector2 ProjectTo(const Vector2& b) const    
+	{ 
+		T l2 = b.LengthSq();
+		OVR_ASSERT(l2 != T(0));
+		return b * ( Dot(b) / l2 ); 
+	}
+};
+
+
+typedef Vector2<float>  Vector2f;
+typedef Vector2<double> Vector2d;
+typedef Vector2<int>    Vector2i;
+
+//-------------------------------------------------------------------------------------
+// ***** Vector3<> - 3D vector of {x, y, z}
+
+//
+// Vector3f (Vector3d) represents a 3-dimensional vector or point in space,
+// consisting of coordinates x, y and z.
+
+template<class T>
+class Vector3
+{
+public:
+    T x, y, z;
+
+    Vector3() : x(0), y(0), z(0) { }
+    Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { }
+    explicit Vector3(T s) : x(s), y(s), z(s) { }
+    explicit Vector3(const Vector3<typename Math<T>::OtherFloatType> &src)
+        : x((T)src.x), y((T)src.y), z((T)src.z) { }
+
+
+    // C-interop support.
+    typedef  typename CompatibleTypes<Vector3<T> >::Type CompatibleType;
+
+    Vector3(const CompatibleType& s) : x(s.x), y(s.y), z(s.z) {  }
+
+    operator const CompatibleType& () const
+    {
+        OVR_COMPILER_ASSERT(sizeof(Vector3<T>) == sizeof(CompatibleType));
+        return reinterpret_cast<const CompatibleType&>(*this);
+    }
+
+    bool     operator== (const Vector3& b) const  { return x == b.x && y == b.y && z == b.z; }
+    bool     operator!= (const Vector3& b) const  { return x != b.x || y != b.y || z != b.z; }
+             
+    Vector3  operator+  (const Vector3& b) const  { return Vector3(x + b.x, y + b.y, z + b.z); }
+    Vector3& operator+= (const Vector3& b)        { x += b.x; y += b.y; z += b.z; return *this; }
+    Vector3  operator-  (const Vector3& b) const  { return Vector3(x - b.x, y - b.y, z - b.z); }
+    Vector3& operator-= (const Vector3& b)        { x -= b.x; y -= b.y; z -= b.z; return *this; }
+    Vector3  operator- () const                   { return Vector3(-x, -y, -z); }
+
+    // Scalar multiplication/division scales vector.
+    Vector3  operator*  (T s) const               { return Vector3(x*s, y*s, z*s); }
+    Vector3& operator*= (T s)                     { x *= s; y *= s; z *= s; return *this; }
+
+    Vector3  operator/  (T s) const               { T rcp = T(1)/s;
+                                                    return Vector3(x*rcp, y*rcp, z*rcp); }
+    Vector3& operator/= (T s)                     { T rcp = T(1)/s;
+                                                    x *= rcp; y *= rcp; z *= rcp;
+                                                    return *this; }
+
+    static Vector3  Min(const Vector3& a, const Vector3& b)
+    {
+        return Vector3((a.x < b.x) ? a.x : b.x,
+                       (a.y < b.y) ? a.y : b.y,
+                       (a.z < b.z) ? a.z : b.z);
+    }
+    static Vector3  Max(const Vector3& a, const Vector3& b)
+    { 
+        return Vector3((a.x > b.x) ? a.x : b.x,
+                       (a.y > b.y) ? a.y : b.y,
+                       (a.z > b.z) ? a.z : b.z);
+    }        
+
+    // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
+    bool      Compare(const Vector3&b, T tolerance = Mathf::Tolerance)
+    {
+        return (fabs(b.x-x) < tolerance) && 
+			   (fabs(b.y-y) < tolerance) && 
+			   (fabs(b.z-z) < tolerance);
+    }
+    
+    T& operator[] (int idx)
+    {
+        OVR_ASSERT(0 <= idx && idx < 3);
+        return *(&x + idx);
+    }
+
+    const T& operator[] (int idx) const
+    {
+        OVR_ASSERT(0 <= idx && idx < 3);
+        return *(&x + idx);
+    }
+
+    // Entrywise product of two vectors
+    Vector3	EntrywiseMultiply(const Vector3& b) const	{ return Vector3(x * b.x, 
+																		 y * b.y, 
+																		 z * b.z);}
+
+    // Multiply and divide operators do entry-wise math
+    Vector3  operator*  (const Vector3& b) const        { return Vector3(x * b.x, 
+																		 y * b.y, 
+																		 z * b.z); }
+
+    Vector3  operator/  (const Vector3& b) const        { return Vector3(x / b.x, 
+																		 y / b.y, 
+																		 z / b.z); }
+
+
+	// Dot product
+    // Used to calculate angle q between two vectors among other things,
+    // as (A dot B) = |a||b|cos(q).
+     T      Dot(const Vector3& b) const          { return x*b.x + y*b.y + z*b.z; }
+
+    // Compute cross product, which generates a normal vector.
+    // Direction vector can be determined by right-hand rule: Pointing index finder in
+    // direction a and middle finger in direction b, thumb will point in a.Cross(b).
+    Vector3 Cross(const Vector3& b) const        { return Vector3(y*b.z - z*b.y,
+                                                                  z*b.x - x*b.z,
+                                                                  x*b.y - y*b.x); }
+
+    // Returns the angle from this vector to b, in radians.
+    T       Angle(const Vector3& b) const 
+	{
+		T div = LengthSq()*b.LengthSq();
+		OVR_ASSERT(div != T(0));
+		T result = Acos((this->Dot(b))/sqrt(div));
+		return result;
+	}
+
+    // Return Length of the vector squared.
+    T       LengthSq() const                     { return (x * x + y * y + z * z); }
+
+    // Return vector length.
+    T       Length() const                       { return sqrt(LengthSq()); }
+
+    // Returns squared distance between two points represented by vectors.
+    T       DistanceSq(Vector3 const& b) const         { return (*this - b).LengthSq(); }
+
+    // Returns distance between two points represented by vectors.
+    T       Distance(Vector3 const& b) const     { return (*this - b).Length(); }
+    
+    // Determine if this a unit vector.
+    bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
+
+    // Normalize, convention vector length to 1.    
+    void    Normalize()                          
+	{
+		T l = Length();
+		OVR_ASSERT(l != T(0));
+		*this /= l; 
+	}
+
+    // Returns normalized (unit) version of the vector without modifying itself.
+    Vector3 Normalized() const                   
+	{ 
+		T l = Length();
+		OVR_ASSERT(l != T(0));
+		return *this / l; 
+	}
+
+    // Linearly interpolates from this vector to another.
+    // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
+    Vector3 Lerp(const Vector3& b, T f) const    { return *this*(T(1) - f) + b*f; }
+
+    // Projects this vector onto the argument; in other words,
+    // A.Project(B) returns projection of vector A onto B.
+    Vector3 ProjectTo(const Vector3& b) const    
+	{ 
+		T l2 = b.LengthSq();
+		OVR_ASSERT(l2 != T(0));
+		return b * ( Dot(b) / l2 ); 
+	}
+
+    // Projects this vector onto a plane defined by a normal vector
+    Vector3 ProjectToPlane(const Vector3& normal) const { return *this - this->ProjectTo(normal); }
+};
+
+
+typedef Vector3<float>  Vector3f;
+typedef Vector3<double> Vector3d;
+typedef Vector3<SInt32>  Vector3i;
+
+
+// JDC: this was defined in Render_Device.h, I moved it here, but it
+// needs to be fleshed out like the other Vector types.
+//
+// A vector with a dummy w component for alignment in uniform buffers (and for float colors).
+// The w component is not used in any calculations.
+
+struct Vector4f : public Vector3f
+{
+    float w;
+
+    Vector4f() : w(1) {}
+    Vector4f(const Vector3f& v) : Vector3f(v), w(1) {}
+    Vector4f(float r, float g, float b, float a) : Vector3f(r,g,b), w(a) {}
+};
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** Size
+
+// Size class represents 2D size with Width, Height components.
+// Used to describe distentions of render targets, etc.
+
+template<class T>
+class Size
+{
+public:
+    T   w, h;
+
+    Size()              : w(0), h(0)   { }
+    Size(T w_, T h_)    : w(w_), h(h_) { }
+    explicit Size(T s)  : w(s), h(s)   { }
+    explicit Size(const Size<typename Math<T>::OtherFloatType> &src)
+        : w((T)src.w), h((T)src.h) { }
+
+    // C-interop support.
+    typedef  typename CompatibleTypes<Size<T> >::Type CompatibleType;
+
+    Size(const CompatibleType& s) : w(s.w), h(s.h) {  }
+
+    operator const CompatibleType& () const
+    {
+        OVR_COMPILER_ASSERT(sizeof(Size<T>) == sizeof(CompatibleType));
+        return reinterpret_cast<const CompatibleType&>(*this);
+    }
+
+    bool     operator== (const Size& b) const  { return w == b.w && h == b.h; }
+    bool     operator!= (const Size& b) const  { return w != b.w || h != b.h; }
+             
+    Size  operator+  (const Size& b) const  { return Size(w + b.w, h + b.h); }
+    Size& operator+= (const Size& b)        { w += b.w; h += b.h; return *this; }
+    Size  operator-  (const Size& b) const  { return Size(w - b.w, h - b.h); }
+    Size& operator-= (const Size& b)        { w -= b.w; h -= b.h; return *this; }
+    Size  operator- () const                { return Size(-w, -h); }
+    Size  operator*  (const Size& b) const  { return Size(w * b.w, h * b.h); }
+    Size& operator*= (const Size& b)        { w *= b.w; h *= b.h; return *this; }
+    Size  operator/  (const Size& b) const  { return Size(w / b.w, h / b.h); }
+    Size& operator/= (const Size& b)        { w /= b.w; h /= b.h; return *this; }
+
+    // Scalar multiplication/division scales both components.
+    Size  operator*  (T s) const            { return Size(w*s, h*s); }
+    Size& operator*= (T s)                  { w *= s; h *= s; return *this; }    
+    Size  operator/  (T s) const            { return Size(w/s, h/s); }
+    Size& operator/= (T s)                  { w /= s; h /= s; return *this; }
+
+    static Size Min(const Size& a, const Size& b)  { return Size((a.w  < b.w)  ? a.w  : b.w,
+                                                                 (a.h < b.h) ? a.h : b.h); }
+    static Size Max(const Size& a, const Size& b)  { return Size((a.w  > b.w)  ? a.w  : b.w,
+                                                                 (a.h > b.h) ? a.h : b.h); }
+    
+
+    T       Area() const                    { return w * h; }
+
+    inline  Vector2<T> ToVector() const     { return Vector2<T>(w, h); }
+};
+
+
+typedef Size<int>       Sizei;
+typedef Size<unsigned>  Sizeu;
+typedef Size<float>     Sizef;
+typedef Size<double>    Sized;
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Rect
+
+// Rect describes a rectangular area for rendering, that includes position and size.
+template<class T>
+class Rect
+{
+public:
+    T x, y;
+    T w, h;
+
+    Rect() { }
+    Rect(T x1, T y1, T w1, T h1)                   : x(x1), y(y1), w(w1), h(h1) { }    
+    Rect(const Vector2<T>& pos, const Size<T>& sz) : x(pos.x), y(pos.y), w(sz.w), h(sz.h) { }
+    Rect(const Size<T>& sz)                        : x(0), y(0), w(sz.w), h(sz.h) { }
+    
+    // C-interop support.
+    typedef  typename CompatibleTypes<Rect<T> >::Type CompatibleType;
+
+    Rect(const CompatibleType& s) : x(s.Pos.x), y(s.Pos.y), w(s.Size.w), h(s.Size.h) {  }
+
+    operator const CompatibleType& () const
+    {
+        OVR_COMPILER_ASSERT(sizeof(Rect<T>) == sizeof(CompatibleType));
+        return reinterpret_cast<const CompatibleType&>(*this);
+    }
+
+    Vector2<T> GetPos() const                { return Vector2<T>(x, y); }
+    Size<T>    GetSize() const               { return Size<T>(w, h); }
+    void       SetPos(const Vector2<T>& pos) { x = pos.x; y = pos.y; }
+    void       SetSize(const Size<T>& sz)    { w = sz.w; h = sz.h; }
+
+    bool operator == (const Rect& vp) const
+    { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); }
+    bool operator != (const Rect& vp) const
+    { return !operator == (vp); }
+};
+
+typedef Rect<int> Recti;
+
+
+//-------------------------------------------------------------------------------------//
+// ***** Quat
+//
+// Quatf represents a quaternion class used for rotations.
+// 
+// Quaternion multiplications are done in right-to-left order, to match the
+// behavior of matrices.
+
+
+template<class T>
+class Quat
+{
+public:
+    // w + Xi + Yj + Zk
+    T x, y, z, w;    
+
+    Quat() : x(0), y(0), z(0), w(1) { }
+    Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) { }
+    explicit Quat(const Quat<typename Math<T>::OtherFloatType> &src)
+        : x((T)src.x), y((T)src.y), z((T)src.z), w((T)src.w) { }
+
+    // C-interop support.
+    Quat(const typename CompatibleTypes<Quat<T> >::Type& s) : x(s.x), y(s.y), z(s.z), w(s.w) { }
+
+    operator typename CompatibleTypes<Quat<T> >::Type () const
+    {
+        typename CompatibleTypes<Quat<T> >::Type result;
+        result.x = x;
+        result.y = y;
+        result.z = z;
+        result.w = w;
+        return result;
+    }
+
+    // Constructs quaternion for rotation around the axis by an angle.
+    Quat(const Vector3<T>& axis, T angle)
+    {
+        // Make sure we don't divide by zero. 
+        if (axis.LengthSq() == 0)
+        {
+            // Assert if the axis is zero, but the angle isn't
+            OVR_ASSERT(angle == 0);
+            x = 0; y = 0; z = 0; w = 1;
+            return;
+        }
+
+		Vector3<T> unitAxis = axis.Normalized();
+		T          sinHalfAngle = sin(angle * T(0.5));
+
+		w = cos(angle * T(0.5));
+		x = unitAxis.x * sinHalfAngle;
+		y = unitAxis.y * sinHalfAngle;
+		z = unitAxis.z * sinHalfAngle;
+    }
+
+    // Constructs quaternion for rotation around one of the coordinate axis by an angle.
+    Quat(Axis A, T angle, RotateDirection d = Rotate_CCW, HandedSystem s = Handed_R)
+    {
+        T sinHalfAngle = s * d *sin(angle * T(0.5));
+        T v[3];
+        v[0] = v[1] = v[2] = T(0);
+        v[A] = sinHalfAngle;
+
+        w = cos(angle * T(0.5));
+        x = v[0];
+        y = v[1];
+        z = v[2];
+    }
+
+    // Compute axis and angle from quaternion
+    void GetAxisAngle(Vector3<T>* axis, T* angle) const
+    {
+		if ( x*x + y*y + z*z > Math<T>::Tolerance * Math<T>::Tolerance ) {
+			*axis  = Vector3<T>(x, y, z).Normalized();
+			*angle = 2 * Acos(w);
+			if (*angle > Math<T>::Pi) // Reduce the magnitude of the angle, if necessary
+			{
+				*angle = Math<T>::TwoPi - *angle;
+				*axis = *axis * (-1);
+			}
+		}
+		else 
+		{
+			*axis = Vector3<T>(1, 0, 0);
+			*angle= 0;
+		}
+    }
+
+    // Constructs the quaternion from a rotation matrix
+    explicit Quat(const Matrix4<T>& m)
+    {
+        T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
+
+        // In almost all cases, the first part is executed.
+        // However, if the trace is not positive, the other
+        // cases arise.
+        if (trace > T(0)) 
+        {
+            T s = sqrt(trace + T(1)) * T(2); // s=4*qw
+            w = T(0.25) * s;
+            x = (m.M[2][1] - m.M[1][2]) / s;
+            y = (m.M[0][2] - m.M[2][0]) / s;
+            z = (m.M[1][0] - m.M[0][1]) / s; 
+        } 
+        else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2])) 
+        {
+            T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2);
+            w = (m.M[2][1] - m.M[1][2]) / s;
+            x = T(0.25) * s;
+            y = (m.M[0][1] + m.M[1][0]) / s;
+            z = (m.M[2][0] + m.M[0][2]) / s;
+        } 
+        else if (m.M[1][1] > m.M[2][2]) 
+        {
+            T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy
+            w = (m.M[0][2] - m.M[2][0]) / s;
+            x = (m.M[0][1] + m.M[1][0]) / s;
+            y = T(0.25) * s;
+            z = (m.M[1][2] + m.M[2][1]) / s;
+        } 
+        else 
+        {
+            T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz
+            w = (m.M[1][0] - m.M[0][1]) / s;
+            x = (m.M[0][2] + m.M[2][0]) / s;
+            y = (m.M[1][2] + m.M[2][1]) / s;
+            z = T(0.25) * s;
+        }
+    }
+
+	// Constructs the quaternion from a rotation matrix
+	explicit Quat(const Matrix3<T>& m)
+	{
+		T trace = m.M[0][0] + m.M[1][1] + m.M[2][2];
+
+		// In almost all cases, the first part is executed.
+		// However, if the trace is not positive, the other
+		// cases arise.
+		if (trace > T(0)) 
+		{
+			T s = sqrt(trace + T(1)) * T(2); // s=4*qw
+			w = T(0.25) * s;
+			x = (m.M[2][1] - m.M[1][2]) / s;
+			y = (m.M[0][2] - m.M[2][0]) / s;
+			z = (m.M[1][0] - m.M[0][1]) / s; 
+		} 
+		else if ((m.M[0][0] > m.M[1][1])&&(m.M[0][0] > m.M[2][2])) 
+		{
+			T s = sqrt(T(1) + m.M[0][0] - m.M[1][1] - m.M[2][2]) * T(2);
+			w = (m.M[2][1] - m.M[1][2]) / s;
+			x = T(0.25) * s;
+			y = (m.M[0][1] + m.M[1][0]) / s;
+			z = (m.M[2][0] + m.M[0][2]) / s;
+		} 
+		else if (m.M[1][1] > m.M[2][2]) 
+		{
+			T s = sqrt(T(1) + m.M[1][1] - m.M[0][0] - m.M[2][2]) * T(2); // S=4*qy
+			w = (m.M[0][2] - m.M[2][0]) / s;
+			x = (m.M[0][1] + m.M[1][0]) / s;
+			y = T(0.25) * s;
+			z = (m.M[1][2] + m.M[2][1]) / s;
+		} 
+		else 
+		{
+			T s = sqrt(T(1) + m.M[2][2] - m.M[0][0] - m.M[1][1]) * T(2); // S=4*qz
+			w = (m.M[1][0] - m.M[0][1]) / s;
+			x = (m.M[0][2] + m.M[2][0]) / s;
+			y = (m.M[1][2] + m.M[2][1]) / s;
+			z = T(0.25) * s;
+		}
+	}
+
+    bool operator== (const Quat& b) const   { return x == b.x && y == b.y && z == b.z && w == b.w; }
+    bool operator!= (const Quat& b) const   { return x != b.x || y != b.y || z != b.z || w != b.w; }
+
+    Quat  operator+  (const Quat& b) const  { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); }
+    Quat& operator+= (const Quat& b)        { w += b.w; x += b.x; y += b.y; z += b.z; return *this; }
+    Quat  operator-  (const Quat& b) const  { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); }
+    Quat& operator-= (const Quat& b)        { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; }
+
+    Quat  operator*  (T s) const            { return Quat(x * s, y * s, z * s, w * s); }
+    Quat& operator*= (T s)                  { w *= s; x *= s; y *= s; z *= s; return *this; }
+    Quat  operator/  (T s) const            { T rcp = T(1)/s; return Quat(x * rcp, y * rcp, z * rcp, w *rcp); }
+    Quat& operator/= (T s)                  { T rcp = T(1)/s; w *= rcp; x *= rcp; y *= rcp; z *= rcp; return *this; }
+
+
+    // Get Imaginary part vector
+    Vector3<T> Imag() const                 { return Vector3<T>(x,y,z); }
+
+    // Get quaternion length.
+    T       Length() const                  { return sqrt(LengthSq()); }
+
+    // Get quaternion length squared.
+    T       LengthSq() const                { return (x * x + y * y + z * z + w * w); }
+
+    // Simple Euclidean distance in R^4 (not SLERP distance, but at least respects Haar measure)
+    T       Distance(const Quat& q) const	
+	{ 
+        T d1 = (*this - q).Length();
+        T d2 = (*this + q).Length(); // Antipodal point check
+        return (d1 < d2) ? d1 : d2;
+	}
+
+    T       DistanceSq(const Quat& q) const
+    {
+        T d1 = (*this - q).LengthSq();
+        T d2 = (*this + q).LengthSq(); // Antipodal point check
+        return (d1 < d2) ? d1 : d2;
+    }
+
+    T       Dot(const Quat& q) const
+    {
+        return x * q.x + y * q.y + z * q.z + w * q.w;
+    }
+
+	// Angle between two quaternions in radians
+    T       Angle(const Quat& q) const
+	{
+		return 2 * Acos(Alg::Abs(Dot(q)));
+	}
+
+    // Normalize
+    bool    IsNormalized() const            { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
+
+    void    Normalize()                     
+	{
+ 		T l = Length();
+		OVR_ASSERT(l != T(0));
+		*this /= l; 
+	}
+
+	Quat    Normalized() const              
+	{ 
+		T l = Length();
+		OVR_ASSERT(l != T(0));
+		return *this / l; 
+	}
+
+    // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized.
+    Quat    Conj() const                    { return Quat(-x, -y, -z, w); }
+
+    // Quaternion multiplication. Combines quaternion rotations, performing the one on the 
+    // right hand side first.
+    Quat  operator* (const Quat& b) const   { return Quat(w * b.x + x * b.w + y * b.z - z * b.y,
+                                                          w * b.y - x * b.z + y * b.w + z * b.x,
+                                                          w * b.z + x * b.y - y * b.x + z * b.w,
+                                                          w * b.w - x * b.x - y * b.y - z * b.z); }
+
+    // 
+    // this^p normalized; same as rotating by this p times.
+    Quat PowNormalized(T p) const
+    {
+        Vector3<T> v;
+        T          a;
+        GetAxisAngle(&v, &a);
+        return Quat(v, a * p);
+    }
+
+    // Normalized linear interpolation of quaternions
+    Quat Nlerp(const Quat& other, T a)
+    {
+        T sign = (Dot(other) >= 0) ? 1 : -1;
+        return (*this * sign * a + other * (1-a)).Normalized();
+    }
+    
+    // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise,
+    // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. 
+    Vector3<T> Rotate(const Vector3<T>& v) const
+    {
+        return ((*this * Quat<T>(v.x, v.y, v.z, T(0))) * Inverted()).Imag();
+    }
+    
+    // Inversed quaternion rotates in the opposite direction.
+    Quat        Inverted() const
+    {
+        return Quat(-x, -y, -z, w);
+    }
+
+    // Sets this quaternion to the one rotates in the opposite direction.
+    void        Invert()
+    {
+        *this = Quat(-x, -y, -z, w);
+    }
+    
+    // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of
+    // axis rotations and the specified coordinate system. Right-handed coordinate system
+    // is the default, with CCW rotations while looking in the negative axis direction.
+    // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
+    // rotation a around axis A1
+    // is followed by rotation b around axis A2
+    // is followed by rotation c around axis A3
+    // rotations are CCW or CW (D) in LH or RH coordinate system (S)
+    template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
+    void GetEulerAngles(T *a, T *b, T *c) const
+    {
+        OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3));
+
+        T Q[3] = { x, y, z };  //Quaternion components x,y,z
+
+        T ww  = w*w;
+        T Q11 = Q[A1]*Q[A1];
+        T Q22 = Q[A2]*Q[A2];
+        T Q33 = Q[A3]*Q[A3];
+
+        T psign = T(-1);
+        // Determine whether even permutation
+        if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3))
+            psign = T(1);
+        
+        T s2 = psign * T(2) * (psign*w*Q[A2] + Q[A1]*Q[A3]);
+
+        if (s2 < T(-1) + Math<T>::SingularityRadius)
+        { // South pole singularity
+            *a = T(0);
+            *b = -S*D*Math<T>::PiOver2;
+            *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]),
+		                   ww + Q22 - Q11 - Q33 );
+        }
+        else if (s2 > T(1) - Math<T>::SingularityRadius)
+        {  // North pole singularity
+            *a = T(0);
+            *b = S*D*Math<T>::PiOver2;
+            *c = S*D*atan2(T(2)*(psign*Q[A1]*Q[A2] + w*Q[A3]),
+		                   ww + Q22 - Q11 - Q33);
+        }
+        else
+        {
+            *a = -S*D*atan2(T(-2)*(w*Q[A1] - psign*Q[A2]*Q[A3]),
+		                    ww + Q33 - Q11 - Q22);
+            *b = S*D*asin(s2);
+            *c = S*D*atan2(T(2)*(w*Q[A3] - psign*Q[A1]*Q[A2]),
+		                   ww + Q11 - Q22 - Q33);
+        }      
+        return;
+    }
+
+    template <Axis A1, Axis A2, Axis A3, RotateDirection D>
+    void GetEulerAngles(T *a, T *b, T *c) const
+    { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); }
+
+    template <Axis A1, Axis A2, Axis A3>
+    void GetEulerAngles(T *a, T *b, T *c) const
+    { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); }
+
+
+    // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of
+    // axis rotations and the specified coordinate system. Right-handed coordinate system
+    // is the default, with CCW rotations while looking in the negative axis direction.
+    // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
+    // rotation a around axis A1
+    // is followed by rotation b around axis A2
+    // is followed by rotation c around axis A1
+    // Rotations are CCW or CW (D) in LH or RH coordinate system (S)
+    template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
+    void GetEulerAnglesABA(T *a, T *b, T *c) const
+    {
+        OVR_COMPILER_ASSERT(A1 != A2);
+
+        T Q[3] = {x, y, z}; // Quaternion components
+
+        // Determine the missing axis that was not supplied
+        int m = 3 - A1 - A2;
+
+        T ww = w*w;
+        T Q11 = Q[A1]*Q[A1];
+        T Q22 = Q[A2]*Q[A2];
+        T Qmm = Q[m]*Q[m];
+
+        T psign = T(-1);
+        if ((A1 + 1) % 3 == A2) // Determine whether even permutation
+        {
+            psign = T(1);
+        }
+
+        T c2 = ww + Q11 - Q22 - Qmm;
+        if (c2 < T(-1) + Math<T>::SingularityRadius)
+        { // South pole singularity
+            *a = T(0);
+            *b = S*D*Math<T>::Pi;
+            *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]),
+		                    ww + Q22 - Q11 - Qmm);
+        }
+        else if (c2 > T(1) - Math<T>::SingularityRadius)
+        {  // North pole singularity
+            *a = T(0);
+            *b = T(0);
+            *c = S*D*atan2( T(2)*(w*Q[A1] - psign*Q[A2]*Q[m]),
+		                   ww + Q22 - Q11 - Qmm);
+        }
+        else
+        {
+            *a = S*D*atan2( psign*w*Q[m] + Q[A1]*Q[A2],
+		                   w*Q[A2] -psign*Q[A1]*Q[m]);
+            *b = S*D*acos(c2);
+            *c = S*D*atan2( -psign*w*Q[m] + Q[A1]*Q[A2],
+		                   w*Q[A2] + psign*Q[A1]*Q[m]);
+        }
+        return;
+    }
+};
+
+typedef Quat<float>  Quatf;
+typedef Quat<double> Quatd;
+
+//-------------------------------------------------------------------------------------
+// ***** Pose
+
+// Position and orientation combined.
+
+template<class T>
+class Transform
+{
+public:
+
+    typedef typename CompatibleTypes<Transform<T> >::Type CompatibleType;
+
+    Transform() { }
+    Transform(const Quat<T>& orientation, const Vector3<T>& pos)
+        : Rotation(orientation), Translation(pos) {  }
+    Transform(const Transform& s)
+        : Rotation(s.Rotation), Translation(s.Translation) {  }
+    Transform(const CompatibleType& s)
+        : Rotation(s.Orientation), Translation(s.Position) {  }
+    explicit Transform(const Transform<typename Math<T>::OtherFloatType> &s)
+        : Rotation(s.Rotation), Translation(s.Translation) {  }
+
+    operator typename CompatibleTypes<Transform<T> >::Type () const
+    {
+        typename CompatibleTypes<Transform<T> >::Type result;
+        result.Orientation = Rotation;
+        result.Position = Translation;
+        return result;
+    }
+
+    Quat<T>    Rotation;
+    Vector3<T> Translation;
+
+    Vector3<T> Rotate(const Vector3<T>& v) const
+    {
+        return Rotation.Rotate(v);
+    }
+
+    Vector3<T> Translate(const Vector3<T>& v) const
+    {
+        return v + Translation;
+    }
+
+    Vector3<T> Apply(const Vector3<T>& v) const
+    {
+        return Translate(Rotate(v));
+    }
+
+    Transform operator*(const Transform& other) const   
+    {
+        return Transform(Rotation * other.Rotation, Apply(other.Translation));
+    }
+
+    PoseState<T> operator*(const PoseState<T>& poseState) const   
+    {
+        PoseState<T> result;
+        result.Pose                = (*this) * poseState.Pose;
+        result.LinearVelocity      = this->Rotate(poseState.LinearVelocity);
+        result.LinearAcceleration  = this->Rotate(poseState.LinearAcceleration);
+        result.AngularVelocity     = this->Rotate(poseState.AngularVelocity);
+        result.AngularAcceleration = this->Rotate(poseState.AngularAcceleration);
+        return result;
+    }
+
+    Transform Inverted() const   
+    {
+        Quat<T> inv = Rotation.Inverted();
+        return Transform(inv, inv.Rotate(-Translation));
+    }
+};
+
+typedef Transform<float>  Transformf;
+typedef Transform<double> Transformd;
+
+
+//-------------------------------------------------------------------------------------
+// ***** Matrix4
+//
+// Matrix4 is a 4x4 matrix used for 3d transformations and projections.
+// Translation stored in the last column.
+// The matrix is stored in row-major order in memory, meaning that values
+// of the first row are stored before the next one.
+//
+// The arrangement of the matrix is chosen to be in Right-Handed 
+// coordinate system and counterclockwise rotations when looking down
+// the axis
+//
+// Transformation Order:
+//   - Transformations are applied from right to left, so the expression
+//     M1 * M2 * M3 * V means that the vector V is transformed by M3 first,
+//     followed by M2 and M1. 
+//
+// Coordinate system: Right Handed
+//
+// Rotations: Counterclockwise when looking down the axis. All angles are in radians.
+//    
+//  | sx   01   02   tx |    // First column  (sx, 10, 20): Axis X basis vector.
+//  | 10   sy   12   ty |    // Second column (01, sy, 21): Axis Y basis vector.
+//  | 20   21   sz   tz |    // Third columnt (02, 12, sz): Axis Z basis vector.
+//  | 30   31   32   33 |
+//
+//  The basis vectors are first three columns.
+
+template<class T>
+class Matrix4
+{
+    static const Matrix4 IdentityValue;
+
+public:
+    T M[4][4];    
+
+    enum NoInitType { NoInit };
+
+    // Construct with no memory initialization.
+    Matrix4(NoInitType) { }
+
+    // By default, we construct identity matrix.
+    Matrix4()
+    {
+        SetIdentity();        
+    }
+
+    Matrix4(T m11, T m12, T m13, T m14,
+            T m21, T m22, T m23, T m24,
+            T m31, T m32, T m33, T m34,
+            T m41, T m42, T m43, T m44)
+    {
+        M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = m14;
+        M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = m24;
+        M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = m34;
+        M[3][0] = m41; M[3][1] = m42; M[3][2] = m43; M[3][3] = m44;
+    }
+
+    Matrix4(T m11, T m12, T m13,
+            T m21, T m22, T m23,
+            T m31, T m32, T m33)
+    {
+        M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = 0;
+        M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = 0;
+        M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = 0;
+        M[3][0] = 0;   M[3][1] = 0;   M[3][2] = 0;   M[3][3] = 1;
+    }
+
+    explicit Matrix4(const Quat<T>& q)
+    {
+        T ww = q.w*q.w;
+        T xx = q.x*q.x;
+        T yy = q.y*q.y;
+        T zz = q.z*q.z;
+
+        M[0][0] = ww + xx - yy - zz;       M[0][1] = 2 * (q.x*q.y - q.w*q.z); M[0][2] = 2 * (q.x*q.z + q.w*q.y); M[0][3] = 0;
+        M[1][0] = 2 * (q.x*q.y + q.w*q.z); M[1][1] = ww - xx + yy - zz;       M[1][2] = 2 * (q.y*q.z - q.w*q.x); M[1][3] = 0;
+        M[2][0] = 2 * (q.x*q.z - q.w*q.y); M[2][1] = 2 * (q.y*q.z + q.w*q.x); M[2][2] = ww - xx - yy + zz;       M[2][3] = 0;
+        M[3][0] = 0;                       M[3][1] = 0;                       M[3][2] = 0;                       M[3][3] = 1;
+    }
+
+    explicit Matrix4(const Transform<T>& p)
+    {
+        Matrix4 result(p.Rotation);
+        result.SetTranslation(p.Translation);
+        *this = result;
+    }
+
+    // C-interop support
+    explicit Matrix4(const Matrix4<typename Math<T>::OtherFloatType> &src)
+    {
+        for (int i = 0; i < 4; i++)
+            for (int j = 0; j < 4; j++)
+                M[i][j] = (T)src.M[i][j];
+    }
+
+    // C-interop support.
+    Matrix4(const typename CompatibleTypes<Matrix4<T> >::Type& s) 
+    {
+        OVR_COMPILER_ASSERT(sizeof(s) == sizeof(Matrix4));
+        memcpy(M, s.M, sizeof(M));
+    }
+
+    operator typename CompatibleTypes<Matrix4<T> >::Type () const
+    {
+        typename CompatibleTypes<Matrix4<T> >::Type result;
+        OVR_COMPILER_ASSERT(sizeof(result) == sizeof(Matrix4));
+        memcpy(result.M, M, sizeof(M));
+        return result;
+    }
+
+    void ToString(char* dest, UPInt destsize) const
+    {
+        UPInt pos = 0;
+        for (int r=0; r<4; r++)
+            for (int c=0; c<4; c++)
+                pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]);
+    }
+
+    static Matrix4 FromString(const char* src)
+    {
+        Matrix4 result;
+        for (int r=0; r<4; r++)
+            for (int c=0; c<4; c++)
+            {
+                result.M[r][c] = (T)atof(src);
+                while (src && *src != ' ')
+                    src++;
+                while (src && *src == ' ')
+                    src++;
+            }
+        return result;
+    }
+
+    static const Matrix4& Identity()  { return IdentityValue; }
+
+    void SetIdentity()
+    {
+        M[0][0] = M[1][1] = M[2][2] = M[3][3] = 1;
+        M[0][1] = M[1][0] = M[2][3] = M[3][1] = 0;
+        M[0][2] = M[1][2] = M[2][0] = M[3][2] = 0;
+        M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0;
+    }
+
+	bool operator== (const Matrix4& b) const
+	{
+		bool isEqual = true;
+        for (int i = 0; i < 4; i++)
+            for (int j = 0; j < 4; j++)
+                isEqual &= (M[i][j] == b.M[i][j]);
+
+		return isEqual;
+	}
+
+    Matrix4 operator+ (const Matrix4& b) const
+    {
+        Matrix4 result(*this);
+        result += b;
+        return result;
+    }
+
+    Matrix4& operator+= (const Matrix4& b)
+    {
+        for (int i = 0; i < 4; i++)
+            for (int j = 0; j < 4; j++)
+                M[i][j] += b.M[i][j];
+        return *this;
+    }
+
+    Matrix4 operator- (const Matrix4& b) const
+    {
+        Matrix4 result(*this);
+        result -= b;
+        return result;
+    }
+
+    Matrix4& operator-= (const Matrix4& b)
+    {
+        for (int i = 0; i < 4; i++)
+            for (int j = 0; j < 4; j++)
+                M[i][j] -= b.M[i][j];
+        return *this;
+    }
+
+    // Multiplies two matrices into destination with minimum copying.
+    static Matrix4& Multiply(Matrix4* d, const Matrix4& a, const Matrix4& b)
+    {
+        OVR_ASSERT((d != &a) && (d != &b));
+        int i = 0;
+        do {
+            d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0] + a.M[i][3] * b.M[3][0];
+            d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1] + a.M[i][3] * b.M[3][1];
+            d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2] + a.M[i][3] * b.M[3][2];
+            d->M[i][3] = a.M[i][0] * b.M[0][3] + a.M[i][1] * b.M[1][3] + a.M[i][2] * b.M[2][3] + a.M[i][3] * b.M[3][3];
+        } while((++i) < 4);
+
+        return *d;
+    }
+
+    Matrix4 operator* (const Matrix4& b) const
+    {
+        Matrix4 result(Matrix4::NoInit);
+        Multiply(&result, *this, b);
+        return result;
+    }
+
+    Matrix4& operator*= (const Matrix4& b)
+    {
+        return Multiply(this, Matrix4(*this), b);
+    }
+
+    Matrix4 operator* (T s) const
+    {
+        Matrix4 result(*this);
+        result *= s;
+        return result;
+    }
+
+    Matrix4& operator*= (T s)
+    {
+        for (int i = 0; i < 4; i++)
+            for (int j = 0; j < 4; j++)
+                M[i][j] *= s;
+        return *this;
+    }
+
+
+    Matrix4 operator/ (T s) const
+    {
+        Matrix4 result(*this);
+        result /= s;
+        return result;
+    }
+
+    Matrix4& operator/= (T s)
+    {
+        for (int i = 0; i < 4; i++)
+            for (int j = 0; j < 4; j++)
+                M[i][j] /= s;
+        return *this;
+    }
+
+    Vector3<T> Transform(const Vector3<T>& v) const
+    {
+        return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3],
+                          M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3],
+                          M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]);
+    }
+
+    Matrix4 Transposed() const
+    {
+        return Matrix4(M[0][0], M[1][0], M[2][0], M[3][0],
+                        M[0][1], M[1][1], M[2][1], M[3][1],
+                        M[0][2], M[1][2], M[2][2], M[3][2],
+                        M[0][3], M[1][3], M[2][3], M[3][3]);
+    }
+
+    void     Transpose()
+    {
+        *this = Transposed();
+    }
+
+
+    T SubDet (const UPInt* rows, const UPInt* cols) const
+    {
+        return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]])
+             - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]])
+             + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]);
+    }
+
+    T Cofactor(UPInt I, UPInt J) const
+    {
+        const UPInt indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}};
+        return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]);
+    }
+
+    T    Determinant() const
+    {
+        return M[0][0] * Cofactor(0,0) + M[0][1] * Cofactor(0,1) + M[0][2] * Cofactor(0,2) + M[0][3] * Cofactor(0,3);
+    }
+
+    Matrix4 Adjugated() const
+    {
+        return Matrix4(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0), 
+                        Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1), 
+                        Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2),
+                        Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3));
+    }
+
+    Matrix4 Inverted() const
+    {
+        T det = Determinant();
+        assert(det != 0);
+        return Adjugated() * (1.0f/det);
+    }
+
+    void Invert()
+    {
+        *this = Inverted();
+    }
+
+	// This is more efficient than general inverse, but ONLY works
+	// correctly if it is a homogeneous transform matrix (rot + trans)
+	Matrix4 InvertedHomogeneousTransform() const
+	{
+		// Make the inverse rotation matrix
+		Matrix4 rinv = this->Transposed();
+		rinv.M[3][0] = rinv.M[3][1] = rinv.M[3][2] = 0.0f;
+		// Make the inverse translation matrix
+		Vector3<T> tvinv(-M[0][3],-M[1][3],-M[2][3]);
+		Matrix4 tinv = Matrix4::Translation(tvinv);
+		return rinv * tinv;  // "untranslate", then "unrotate"
+	}
+
+	// This is more efficient than general inverse, but ONLY works
+	// correctly if it is a homogeneous transform matrix (rot + trans)
+	void InvertHomogeneousTransform()
+	{
+        *this = InvertedHomogeneousTransform();
+	}
+
+	// Matrix to Euler Angles conversion
+    // a,b,c, are the YawPitchRoll angles to be returned
+    // rotation a around axis A1
+    // is followed by rotation b around axis A2
+    // is followed by rotation c around axis A3
+    // rotations are CCW or CW (D) in LH or RH coordinate system (S)
+    template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
+    void ToEulerAngles(T *a, T *b, T *c)
+    {
+        OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3));
+
+        T psign = -1;
+        if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation
+        psign = 1;
+        
+        T pm = psign*M[A1][A3];
+        if (pm < -1.0f + Math<T>::SingularityRadius)
+        { // South pole singularity
+            *a = 0;
+            *b = -S*D*Math<T>::PiOver2;
+            *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
+        }
+        else if (pm > 1.0f - Math<T>::SingularityRadius)
+        { // North pole singularity
+            *a = 0;
+            *b = S*D*Math<T>::PiOver2;
+            *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
+        }
+        else
+        { // Normal case (nonsingular)
+            *a = S*D*atan2( -psign*M[A2][A3], M[A3][A3] );
+            *b = S*D*asin(pm);
+            *c = S*D*atan2( -psign*M[A1][A2], M[A1][A1] );
+        }
+
+        return;
+    }
+
+	// Matrix to Euler Angles conversion
+    // a,b,c, are the YawPitchRoll angles to be returned
+    // rotation a around axis A1
+    // is followed by rotation b around axis A2
+    // is followed by rotation c around axis A1
+    // rotations are CCW or CW (D) in LH or RH coordinate system (S)
+    template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
+    void ToEulerAnglesABA(T *a, T *b, T *c)
+    {        
+         OVR_COMPILER_ASSERT(A1 != A2);
+  
+        // Determine the axis that was not supplied
+        int m = 3 - A1 - A2;
+
+        T psign = -1;
+        if ((A1 + 1) % 3 == A2) // Determine whether even permutation
+            psign = 1.0f;
+
+        T c2 = M[A1][A1];
+        if (c2 < -1 + Math<T>::SingularityRadius)
+        { // South pole singularity
+            *a = 0;
+            *b = S*D*Math<T>::Pi;
+            *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
+        }
+        else if (c2 > 1.0f - Math<T>::SingularityRadius)
+        { // North pole singularity
+            *a = 0;
+            *b = 0;
+            *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
+        }
+        else
+        { // Normal case (nonsingular)
+            *a = S*D*atan2( M[A2][A1],-psign*M[m][A1]);
+            *b = S*D*acos(c2);
+            *c = S*D*atan2( M[A1][A2],psign*M[A1][m]);
+        }
+        return;
+    }
+  
+    // Creates a matrix that converts the vertices from one coordinate system
+    // to another.
+    static Matrix4 AxisConversion(const WorldAxes& to, const WorldAxes& from)
+    {        
+        // Holds axis values from the 'to' structure
+        int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis };
+
+        // The inverse of the toArray
+        int inv[4]; 
+        inv[0] = inv[abs(to.XAxis)] = 0;
+        inv[abs(to.YAxis)] = 1;
+        inv[abs(to.ZAxis)] = 2;
+
+        Matrix4 m(0,  0,  0, 
+                  0,  0,  0,
+                  0,  0,  0);
+
+        // Only three values in the matrix need to be changed to 1 or -1.
+        m.M[inv[abs(from.XAxis)]][0] = T(from.XAxis/toArray[inv[abs(from.XAxis)]]);
+        m.M[inv[abs(from.YAxis)]][1] = T(from.YAxis/toArray[inv[abs(from.YAxis)]]);
+        m.M[inv[abs(from.ZAxis)]][2] = T(from.ZAxis/toArray[inv[abs(from.ZAxis)]]);
+        return m;
+    } 
+
+
+	// Creates a matrix for translation by vector
+    static Matrix4 Translation(const Vector3<T>& v)
+    {
+        Matrix4 t;
+        t.M[0][3] = v.x;
+        t.M[1][3] = v.y;
+        t.M[2][3] = v.z;
+        return t;
+    }
+
+	// Creates a matrix for translation by vector
+    static Matrix4 Translation(T x, T y, T z = 0.0f)
+    {
+        Matrix4 t;
+        t.M[0][3] = x;
+        t.M[1][3] = y;
+        t.M[2][3] = z;
+        return t;
+    }
+
+	// Sets the translation part
+    void SetTranslation(const Vector3<T>& v)
+    {
+        M[0][3] = v.x;
+        M[1][3] = v.y;
+        M[2][3] = v.z;
+    }
+
+    Vector3<T> GetTranslation() const
+    {
+        return Vector3<T>( M[0][3], M[1][3], M[2][3] );
+    }
+
+	// Creates a matrix for scaling by vector
+    static Matrix4 Scaling(const Vector3<T>& v)
+    {
+        Matrix4 t;
+        t.M[0][0] = v.x;
+        t.M[1][1] = v.y;
+        t.M[2][2] = v.z;
+        return t;
+    }
+
+	// Creates a matrix for scaling by vector
+    static Matrix4 Scaling(T x, T y, T z)
+    {
+        Matrix4 t;
+        t.M[0][0] = x;
+        t.M[1][1] = y;
+        t.M[2][2] = z;
+        return t;
+    }
+
+	// Creates a matrix for scaling by constant
+    static Matrix4 Scaling(T s)
+    {
+        Matrix4 t;
+        t.M[0][0] = s;
+        t.M[1][1] = s;
+        t.M[2][2] = s;
+        return t;
+    }
+
+    // Simple L1 distance in R^12
+	T Distance(const Matrix4& m2) const           
+	{ 
+		T d = fabs(M[0][0] - m2.M[0][0]) + fabs(M[0][1] - m2.M[0][1]);
+		d += fabs(M[0][2] - m2.M[0][2]) + fabs(M[0][3] - m2.M[0][3]);
+		d += fabs(M[1][0] - m2.M[1][0]) + fabs(M[1][1] - m2.M[1][1]);
+		d += fabs(M[1][2] - m2.M[1][2]) + fabs(M[1][3] - m2.M[1][3]);
+		d += fabs(M[2][0] - m2.M[2][0]) + fabs(M[2][1] - m2.M[2][1]);
+		d += fabs(M[2][2] - m2.M[2][2]) + fabs(M[2][3] - m2.M[2][3]);
+		d += fabs(M[3][0] - m2.M[3][0]) + fabs(M[3][1] - m2.M[3][1]);
+		d += fabs(M[3][2] - m2.M[3][2]) + fabs(M[3][3] - m2.M[3][3]);
+		return d; 
+	}
+
+    // Creates a rotation matrix rotating around the X axis by 'angle' radians.
+    // Just for quick testing.  Not for final API.  Need to remove case.
+    static Matrix4 RotationAxis(Axis A, T angle, RotateDirection d, HandedSystem s)
+    {
+        T sina = s * d *sin(angle);
+        T cosa = cos(angle);
+        
+        switch(A)
+        {
+        case Axis_X:
+            return Matrix4(1,  0,     0, 
+                           0,  cosa,  -sina,
+                           0,  sina,  cosa);
+        case Axis_Y:
+            return Matrix4(cosa,  0,   sina, 
+                           0,     1,   0,
+                           -sina, 0,   cosa);
+        case Axis_Z:
+            return Matrix4(cosa,  -sina,  0, 
+                           sina,  cosa,   0,
+                           0,     0,      1);
+        }
+    }
+
+
+    // Creates a rotation matrix rotating around the X axis by 'angle' radians.
+    // Rotation direction is depends on the coordinate system:
+    // RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
+    //                        while looking in the negative axis direction. This is the
+    //                        same as looking down from positive axis values towards origin.
+    // LHS: Positive angle values rotate clock-wise (CW), while looking in the
+    //       negative axis direction.
+    static Matrix4 RotationX(T angle)
+    {
+        T sina = sin(angle);
+        T cosa = cos(angle);
+        return Matrix4(1,  0,     0, 
+                       0,  cosa,  -sina,
+                       0,  sina,  cosa);
+    }
+
+    // Creates a rotation matrix rotating around the Y axis by 'angle' radians.
+    // Rotation direction is depends on the coordinate system:
+    //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
+    //                        while looking in the negative axis direction. This is the
+    //                        same as looking down from positive axis values towards origin.
+    //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
+    //       negative axis direction.
+    static Matrix4 RotationY(T angle)
+    {
+        T sina = sin(angle);
+        T cosa = cos(angle);
+        return Matrix4(cosa,  0,   sina, 
+                       0,     1,   0,
+                       -sina, 0,   cosa);
+    }
+
+    // Creates a rotation matrix rotating around the Z axis by 'angle' radians.
+    // Rotation direction is depends on the coordinate system:
+    //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
+    //                        while looking in the negative axis direction. This is the
+    //                        same as looking down from positive axis values towards origin.
+    //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
+    //       negative axis direction.
+    static Matrix4 RotationZ(T angle)
+    {
+        T sina = sin(angle);
+        T cosa = cos(angle);
+        return Matrix4(cosa,  -sina,  0, 
+                       sina,  cosa,   0,
+                       0,     0,      1);
+    }
+
+    // LookAtRH creates a View transformation matrix for right-handed coordinate system.
+    // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
+    // specifying the up vector. The resulting matrix should be used with PerspectiveRH
+    // projection.
+    static Matrix4 LookAtRH(const Vector3<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
+    {
+        Vector3<T> z = (eye - at).Normalized();  // Forward
+        Vector3<T> x = up.Cross(z).Normalized(); // Right
+        Vector3<T> y = z.Cross(x);
+
+        Matrix4 m(x.x,  x.y,  x.z,  -(x.Dot(eye)),
+                  y.x,  y.y,  y.z,  -(y.Dot(eye)),
+                  z.x,  z.y,  z.z,  -(z.Dot(eye)),
+                  0,    0,    0,    1 );
+        return m;
+    }
+    
+    // LookAtLH creates a View transformation matrix for left-handed coordinate system.
+    // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
+    // specifying the up vector. 
+    static Matrix4 LookAtLH(const Vector3<T>& eye, const Vector3<T>& at, const Vector3<T>& up)
+    {
+        Vector3<T> z = (at - eye).Normalized();  // Forward
+        Vector3<T> x = up.Cross(z).Normalized(); // Right
+        Vector3<T> y = z.Cross(x);
+
+        Matrix4 m(x.x,  x.y,  x.z,  -(x.Dot(eye)),
+                  y.x,  y.y,  y.z,  -(y.Dot(eye)),
+                  z.x,  z.y,  z.z,  -(z.Dot(eye)),
+                  0,    0,    0,    1 ); 
+        return m;
+    }
+    
+    // PerspectiveRH creates a right-handed perspective projection matrix that can be
+    // used with the Oculus sample renderer. 
+    //  yfov   - Specifies vertical field of view in radians.
+    //  aspect - Screen aspect ration, which is usually width/height for square pixels.
+    //           Note that xfov = yfov * aspect.
+    //  znear  - Absolute value of near Z clipping clipping range.
+    //  zfar   - Absolute value of far  Z clipping clipping range (larger then near).
+    // Even though RHS usually looks in the direction of negative Z, positive values
+    // are expected for znear and zfar.
+    static Matrix4 PerspectiveRH(T yfov, T aspect, T znear, T zfar)
+    {
+        Matrix4 m;
+        T tanHalfFov = tan(yfov * 0.5f);
+
+        m.M[0][0] = 1 / (aspect * tanHalfFov);
+        m.M[1][1] = 1 / tanHalfFov;
+        m.M[2][2] = zfar / (zfar - znear);
+        m.M[3][2] = 1;
+        m.M[2][3] = (zfar * znear) / (znear - zfar);
+        m.M[3][3] = 0;
+
+        // Note: Post-projection matrix result assumes Left-Handed coordinate system,
+        //       with Y up, X right and Z forward. This supports positive z-buffer values.
+        return m;
+    }
+    
+    // PerspectiveRH creates a left-handed perspective projection matrix that can be
+    // used with the Oculus sample renderer. 
+    //  yfov   - Specifies vertical field of view in radians.
+    //  aspect - Screen aspect ration, which is usually width/height for square pixels.
+    //           Note that xfov = yfov * aspect.
+    //  znear  - Absolute value of near Z clipping clipping range.
+    //  zfar   - Absolute value of far  Z clipping clipping range (larger then near).
+    static Matrix4 PerspectiveLH(T yfov, T aspect, T znear, T zfar)
+    {
+        Matrix4 m;
+        T tanHalfFov = tan(yfov * 0.5f);
+
+        m.M[0][0] = 1.0 / (aspect * tanHalfFov);
+        m.M[1][1] = 1.0 / tanHalfFov;
+        m.M[2][2] = zfar / (znear - zfar);
+        // m.M[2][2] = zfar / (zfar - znear);
+        m.M[3][2] = -1.0;
+        m.M[2][3] = (zfar * znear) / (znear - zfar);
+        m.M[3][3] = 0.0;
+
+        // Note: Post-projection matrix result assumes Left-Handed coordinate system,    
+        //       with Y up, X right and Z forward. This supports positive z-buffer values.
+        // This is the case even for RHS cooridnate input.       
+        return m;
+    }
+
+    static Matrix4 Ortho2D(T w, T h)
+    {
+        Matrix4 m;
+        m.M[0][0] = 2.0/w;
+        m.M[1][1] = -2.0/h;
+        m.M[0][3] = -1.0;
+        m.M[1][3] = 1.0;
+        m.M[2][2] = 0;
+        return m;
+    }
+};
+
+typedef Matrix4<float>  Matrix4f;
+typedef Matrix4<double> Matrix4d;
+
+//-------------------------------------------------------------------------------------
+// ***** Matrix3
+//
+// Matrix3 is a 3x3 matrix used for representing a rotation matrix.
+// The matrix is stored in row-major order in memory, meaning that values
+// of the first row are stored before the next one.
+//
+// The arrangement of the matrix is chosen to be in Right-Handed 
+// coordinate system and counterclockwise rotations when looking down
+// the axis
+//
+// Transformation Order:
+//   - Transformations are applied from right to left, so the expression
+//     M1 * M2 * M3 * V means that the vector V is transformed by M3 first,
+//     followed by M2 and M1. 
+//
+// Coordinate system: Right Handed
+//
+// Rotations: Counterclockwise when looking down the axis. All angles are in radians.
+
+template<typename T>
+class SymMat3;
+
+template<class T>
+class Matrix3
+{
+	static const Matrix3 IdentityValue;
+
+public:
+	T M[3][3];    
+
+	enum NoInitType { NoInit };
+
+	// Construct with no memory initialization.
+	Matrix3(NoInitType) { }
+
+	// By default, we construct identity matrix.
+	Matrix3()
+	{
+		SetIdentity();        
+	}
+
+	Matrix3(T m11, T m12, T m13,
+			T m21, T m22, T m23,
+			T m31, T m32, T m33)
+	{
+		M[0][0] = m11; M[0][1] = m12; M[0][2] = m13;
+		M[1][0] = m21; M[1][1] = m22; M[1][2] = m23;
+		M[2][0] = m31; M[2][1] = m32; M[2][2] = m33;
+	}
+	
+	/*
+	explicit Matrix3(const Quat<T>& q)
+	{
+		T ww = q.w*q.w;
+		T xx = q.x*q.x;
+		T yy = q.y*q.y;
+		T zz = q.z*q.z;
+
+		M[0][0] = ww + xx - yy - zz;       M[0][1] = 2 * (q.x*q.y - q.w*q.z); M[0][2] = 2 * (q.x*q.z + q.w*q.y);
+		M[1][0] = 2 * (q.x*q.y + q.w*q.z); M[1][1] = ww - xx + yy - zz;       M[1][2] = 2 * (q.y*q.z - q.w*q.x);
+		M[2][0] = 2 * (q.x*q.z - q.w*q.y); M[2][1] = 2 * (q.y*q.z + q.w*q.x); M[2][2] = ww - xx - yy + zz;      
+	}
+	*/
+	
+	explicit Matrix3(const Quat<T>& q)
+	{
+		const T tx  = q.x+q.x,  ty  = q.y+q.y,  tz  = q.z+q.z;
+		const T twx = q.w*tx,   twy = q.w*ty,   twz = q.w*tz;
+		const T txx = q.x*tx,   txy = q.x*ty,   txz = q.x*tz;
+		const T tyy = q.y*ty,   tyz = q.y*tz,   tzz = q.z*tz;
+		M[0][0] = T(1) - (tyy + tzz);	M[0][1] = txy - twz;			M[0][2] = txz + twy;
+		M[1][0] = txy + twz;			M[1][1] = T(1) - (txx + tzz);	M[1][2] = tyz - twx;
+		M[2][0] = txz - twy;			M[2][1] = tyz + twx;			M[2][2] = T(1) - (txx + tyy);
+	}
+	
+	inline explicit Matrix3(T s)
+    {
+        M[0][0] = M[1][1] = M[2][2] = s;
+        M[0][1] = M[0][2] = M[1][0] = M[1][2] = M[2][0] = M[2][1] = 0;
+    }
+
+	explicit Matrix3(const Transform<T>& p)
+	{
+		Matrix3 result(p.Rotation);
+		result.SetTranslation(p.Translation);
+		*this = result;
+	}
+
+	// C-interop support
+	explicit Matrix3(const Matrix4<typename Math<T>::OtherFloatType> &src)
+	{
+		for (int i = 0; i < 3; i++)
+			for (int j = 0; j < 3; j++)
+				M[i][j] = (T)src.M[i][j];
+	}
+
+	// C-interop support.
+	Matrix3(const typename CompatibleTypes<Matrix3<T> >::Type& s) 
+	{
+		OVR_COMPILER_ASSERT(sizeof(s) == sizeof(Matrix3));
+		memcpy(M, s.M, sizeof(M));
+	}
+
+	operator typename CompatibleTypes<Matrix3<T> >::Type () const
+	{
+		typename CompatibleTypes<Matrix3<T> >::Type result;
+		OVR_COMPILER_ASSERT(sizeof(result) == sizeof(Matrix3));
+		memcpy(result.M, M, sizeof(M));
+		return result;
+	}
+
+	void ToString(char* dest, UPInt destsize) const
+	{
+		UPInt pos = 0;
+		for (int r=0; r<3; r++)
+			for (int c=0; c<3; c++)
+				pos += OVR_sprintf(dest+pos, destsize-pos, "%g ", M[r][c]);
+	}
+
+	static Matrix3 FromString(const char* src)
+	{
+		Matrix3 result;
+		for (int r=0; r<3; r++)
+			for (int c=0; c<3; c++)
+			{
+				result.M[r][c] = (T)atof(src);
+				while (src && *src != ' ')
+					src++;
+				while (src && *src == ' ')
+					src++;
+			}
+			return result;
+	}
+
+	static const Matrix3& Identity()  { return IdentityValue; }
+
+	void SetIdentity()
+	{
+		M[0][0] = M[1][1] = M[2][2] = 1;
+		M[0][1] = M[1][0] = M[2][0] = 0;
+		M[0][2] = M[1][2] = M[2][1] = 0;
+	}
+
+	bool operator== (const Matrix3& b) const
+	{
+		bool isEqual = true;
+		for (int i = 0; i < 3; i++)
+			for (int j = 0; j < 3; j++)
+				isEqual &= (M[i][j] == b.M[i][j]);
+
+		return isEqual;
+	}
+
+	Matrix3 operator+ (const Matrix3& b) const
+	{
+        Matrix4<T> result(*this);
+		result += b;
+		return result;
+	}
+
+	Matrix3& operator+= (const Matrix3& b)
+	{
+		for (int i = 0; i < 3; i++)
+			for (int j = 0; j < 3; j++)
+				M[i][j] += b.M[i][j];
+		return *this;
+	}
+
+	void operator= (const Matrix3& b)
+	{
+		for (int i = 0; i < 3; i++)
+			for (int j = 0; j < 3; j++)
+				M[i][j] = b.M[i][j];
+		return;
+	}
+
+	void operator= (const SymMat3<T>& b)
+	{
+		for (int i = 0; i < 3; i++)
+			for (int j = 0; j < 3; j++)
+				M[i][j] = 0;
+
+		M[0][0] = b.v[0];
+		M[0][1] = b.v[1];
+		M[0][2] = b.v[2];
+		M[1][1] = b.v[3];
+		M[1][2] = b.v[4];
+		M[2][2] = b.v[5];
+
+		return;
+	}
+
+	Matrix3 operator- (const Matrix3& b) const
+	{
+		Matrix3 result(*this);
+		result -= b;
+		return result;
+	}
+
+	Matrix3& operator-= (const Matrix3& b)
+	{
+		for (int i = 0; i < 3; i++)
+			for (int j = 0; j < 3; j++)
+				M[i][j] -= b.M[i][j];
+		return *this;
+	}
+
+	// Multiplies two matrices into destination with minimum copying.
+	static Matrix3& Multiply(Matrix3* d, const Matrix3& a, const Matrix3& b)
+	{
+		OVR_ASSERT((d != &a) && (d != &b));
+		int i = 0;
+		do {
+			d->M[i][0] = a.M[i][0] * b.M[0][0] + a.M[i][1] * b.M[1][0] + a.M[i][2] * b.M[2][0];
+			d->M[i][1] = a.M[i][0] * b.M[0][1] + a.M[i][1] * b.M[1][1] + a.M[i][2] * b.M[2][1];
+			d->M[i][2] = a.M[i][0] * b.M[0][2] + a.M[i][1] * b.M[1][2] + a.M[i][2] * b.M[2][2];
+		} while((++i) < 3);
+
+		return *d;
+	}
+
+	Matrix3 operator* (const Matrix3& b) const
+	{
+		Matrix3 result(Matrix3::NoInit);
+		Multiply(&result, *this, b);
+		return result;
+	}
+
+	Matrix3& operator*= (const Matrix3& b)
+	{
+		return Multiply(this, Matrix3(*this), b);
+	}
+
+	Matrix3 operator* (T s) const
+	{
+		Matrix3 result(*this);
+		result *= s;
+		return result;
+	}
+
+	Matrix3& operator*= (T s)
+	{
+		for (int i = 0; i < 3; i++)
+			for (int j = 0; j < 3; j++)
+				M[i][j] *= s;
+		return *this;
+	}
+
+	Vector3<T> operator* (const Vector3<T> &b) const
+	{
+		Vector3<T> result;
+		result.x = M[0][0]*b.x + M[0][1]*b.y + M[0][2]*b.z;
+		result.y = M[1][0]*b.x + M[1][1]*b.y + M[1][2]*b.z;
+		result.z = M[2][0]*b.x + M[2][1]*b.y + M[2][2]*b.z;
+
+		return result;
+	}
+
+	Matrix3 operator/ (T s) const
+	{
+		Matrix3 result(*this);
+		result /= s;
+		return result;
+	}
+
+	Matrix3& operator/= (T s)
+	{
+		for (int i = 0; i < 3; i++)
+			for (int j = 0; j < 3; j++)
+				M[i][j] /= s;
+		return *this;
+	}
+
+	Vector3<T> Transform(const Vector3<T>& v) const
+	{
+		return Vector3<T>(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z,
+						  M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z,
+						  M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z);
+	}
+
+	Matrix3 Transposed() const
+	{
+		return Matrix3(M[0][0], M[1][0], M[2][0],
+					   M[0][1], M[1][1], M[2][1],
+					   M[0][2], M[1][2], M[2][2]);
+	}
+
+	void     Transpose()
+	{
+		*this = Transposed();
+	}
+
+
+	T SubDet (const UPInt* rows, const UPInt* cols) const
+	{
+		return M[rows[0]][cols[0]] * (M[rows[1]][cols[1]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[1]])
+			 - M[rows[0]][cols[1]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[2]] - M[rows[1]][cols[2]] * M[rows[2]][cols[0]])
+			 + M[rows[0]][cols[2]] * (M[rows[1]][cols[0]] * M[rows[2]][cols[1]] - M[rows[1]][cols[1]] * M[rows[2]][cols[0]]);
+	}
+
+	// M += a*b.t()
+	inline void Rank1Add(const Vector3<T> &a, const Vector3<T> &b)
+	{
+		M[0][0] += a.x*b.x;		M[0][1] += a.x*b.y;		M[0][2] += a.x*b.z;
+		M[1][0] += a.y*b.x;		M[1][1] += a.y*b.y;		M[1][2] += a.y*b.z;
+		M[2][0] += a.z*b.x;		M[2][1] += a.z*b.y;		M[2][2] += a.z*b.z;
+	}
+
+	// M -= a*b.t()
+	inline void Rank1Sub(const Vector3<T> &a, const Vector3<T> &b)
+	{
+		M[0][0] -= a.x*b.x;		M[0][1] -= a.x*b.y;		M[0][2] -= a.x*b.z;
+		M[1][0] -= a.y*b.x;		M[1][1] -= a.y*b.y;		M[1][2] -= a.y*b.z;
+		M[2][0] -= a.z*b.x;		M[2][1] -= a.z*b.y;		M[2][2] -= a.z*b.z;
+	}
+
+	inline Vector3<T> Col(int c) const
+	{
+		return Vector3<T>(M[0][c], M[1][c], M[2][c]);
+	}
+
+	inline Vector3<T> Row(int r) const
+	{
+        return Vector3<T>(M[r][0], M[r][1], M[r][2]);
+	}
+
+	inline T Determinant() const
+	{
+		const Matrix3<T>& m = *this;
+		T d; 
+
+		d  = m.M[0][0] * (m.M[1][1]*m.M[2][2] - m.M[1][2] * m.M[2][1]);
+		d -= m.M[0][1] * (m.M[1][0]*m.M[2][2] - m.M[1][2] * m.M[2][0]);
+		d += m.M[0][2] * (m.M[1][0]*m.M[2][1] - m.M[1][1] * m.M[2][0]);
+
+		return d;
+	}
+	
+	inline Matrix3<T> Inverse() const
+    {
+        Matrix3<T> a;
+        const  Matrix3<T>& m = *this;
+        T d = Determinant();
+
+        assert(d != 0);
+        T s = T(1)/d;
+
+        a.M[0][0] = s * (m.M[1][1] * m.M[2][2] - m.M[1][2] * m.M[2][1]);   
+        a.M[1][0] = s * (m.M[1][2] * m.M[2][0] - m.M[1][0] * m.M[2][2]);   
+        a.M[2][0] = s * (m.M[1][0] * m.M[2][1] - m.M[1][1] * m.M[2][0]);   
+
+		a.M[0][1] = s * (m.M[0][2] * m.M[2][1] - m.M[0][1] * m.M[2][2]);   
+		a.M[1][1] = s * (m.M[0][0] * m.M[2][2] - m.M[0][2] * m.M[2][0]);   
+		a.M[2][1] = s * (m.M[0][1] * m.M[2][0] - m.M[0][0] * m.M[2][1]);   
+        
+		a.M[0][2] = s * (m.M[0][1] * m.M[1][2] - m.M[0][2] * m.M[1][1]);   
+		a.M[1][2] = s * (m.M[0][2] * m.M[1][0] - m.M[0][0] * m.M[1][2]);   
+		a.M[2][2] = s * (m.M[0][0] * m.M[1][1] - m.M[0][1] * m.M[1][0]);   
+        
+        return a;
+    }
+	
+};
+
+typedef Matrix3<float>  Matrix3f;
+typedef Matrix3<double> Matrix3d;
+
+//-------------------------------------------------------------------------------------
+
+template<typename T>
+class SymMat3
+{
+private:
+	typedef SymMat3<T> this_type;
+
+public:
+	typedef T Value_t;
+	// Upper symmetric
+	T v[6]; // _00 _01 _02 _11 _12 _22
+
+	inline SymMat3() {}
+
+	inline explicit SymMat3(T s)
+	{
+		v[0] = v[3] = v[5] = s;
+		v[1] = v[2] = v[4] = 0;
+	}
+
+	inline explicit SymMat3(T a00, T a01, T a02, T a11, T a12, T a22)
+	{
+		v[0] = a00; v[1] = a01; v[2] = a02;
+		v[3] = a11; v[4] = a12;
+		v[5] = a22;
+	}
+
+	static inline int Index(unsigned int i, unsigned int j)
+	{
+		return (i <= j) ? (3*i - i*(i+1)/2 + j) : (3*j - j*(j+1)/2 + i);
+	}
+
+	inline T operator()(int i, int j) const { return v[Index(i,j)]; }
+	
+	inline T &operator()(int i, int j) { return v[Index(i,j)]; }
+
+	template<typename U>
+	inline SymMat3<U> CastTo() const
+	{
+		return SymMat3<U>(static_cast<U>(v[0]), static_cast<U>(v[1]), static_cast<U>(v[2]),
+						  static_cast<U>(v[3]), static_cast<U>(v[4]), static_cast<U>(v[5]));
+	}
+
+	inline this_type& operator+=(const this_type& b)
+	{
+		v[0]+=b.v[0];
+		v[1]+=b.v[1];
+		v[2]+=b.v[2];
+		v[3]+=b.v[3];
+		v[4]+=b.v[4];
+		v[5]+=b.v[5];
+		return *this;
+	}
+
+	inline this_type& operator-=(const this_type& b)
+	{
+		v[0]-=b.v[0];
+		v[1]-=b.v[1];
+		v[2]-=b.v[2];
+		v[3]-=b.v[3];
+		v[4]-=b.v[4];
+		v[5]-=b.v[5];
+
+		return *this;
+	}
+
+	inline this_type& operator*=(T s)
+	{
+		v[0]*=s;
+		v[1]*=s;
+		v[2]*=s;
+		v[3]*=s;
+		v[4]*=s;
+		v[5]*=s;
+
+		return *this;
+	}
+		
+	inline SymMat3 operator*(T s) const
+	{
+		SymMat3 d;
+		d.v[0] = v[0]*s; 
+		d.v[1] = v[1]*s; 
+		d.v[2] = v[2]*s; 
+		d.v[3] = v[3]*s; 
+		d.v[4] = v[4]*s; 
+		d.v[5] = v[5]*s; 
+						
+		return d;
+	}
+
+	// Multiplies two matrices into destination with minimum copying.
+	static SymMat3& Multiply(SymMat3* d, const SymMat3& a, const SymMat3& b)
+	{		
+		// _00 _01 _02 _11 _12 _22
+
+		d->v[0] = a.v[0] * b.v[0];
+		d->v[1] = a.v[0] * b.v[1] + a.v[1] * b.v[3];
+		d->v[2] = a.v[0] * b.v[2] + a.v[1] * b.v[4];
+					
+		d->v[3] = a.v[3] * b.v[3];
+		d->v[4] = a.v[3] * b.v[4] + a.v[4] * b.v[5];
+				
+		d->v[5] = a.v[5] * b.v[5];
+	
+		return *d;
+	}
+	
+	inline T Determinant() const
+	{
+		const this_type& m = *this;
+		T d; 
+
+		d  = m(0,0) * (m(1,1)*m(2,2) - m(1,2) * m(2,1));
+		d -= m(0,1) * (m(1,0)*m(2,2) - m(1,2) * m(2,0));
+		d += m(0,2) * (m(1,0)*m(2,1) - m(1,1) * m(2,0));
+
+		return d;
+	}
+
+	inline this_type Inverse() const
+	{
+		this_type a;
+		const this_type& m = *this;
+		T d = Determinant();
+
+		assert(d != 0);
+		T s = T(1)/d;
+
+		a(0,0) = s * (m(1,1) * m(2,2) - m(1,2) * m(2,1));   
+
+		a(0,1) = s * (m(0,2) * m(2,1) - m(0,1) * m(2,2));   
+		a(1,1) = s * (m(0,0) * m(2,2) - m(0,2) * m(2,0));   
+
+		a(0,2) = s * (m(0,1) * m(1,2) - m(0,2) * m(1,1));   
+		a(1,2) = s * (m(0,2) * m(1,0) - m(0,0) * m(1,2));   
+		a(2,2) = s * (m(0,0) * m(1,1) - m(0,1) * m(1,0));   
+
+		return a;
+	}
+
+	inline T Trace() const { return v[0] + v[3] + v[5]; }
+
+	// M = a*a.t()
+	inline void Rank1(const Vector3<T> &a)
+	{
+		v[0] = a.x*a.x; v[1] = a.x*a.y; v[2] = a.x*a.z;
+		v[3] = a.y*a.y; v[4] = a.y*a.z;
+		v[5] = a.z*a.z;
+	}
+
+	// M += a*a.t()
+	inline void Rank1Add(const Vector3<T> &a)
+	{
+		v[0] += a.x*a.x; v[1] += a.x*a.y; v[2] += a.x*a.z;
+		v[3] += a.y*a.y; v[4] += a.y*a.z;
+		v[5] += a.z*a.z;
+	}
+
+	// M -= a*a.t()
+	inline void Rank1Sub(const Vector3<T> &a)
+	{
+		v[0] -= a.x*a.x; v[1] -= a.x*a.y; v[2] -= a.x*a.z;
+		v[3] -= a.y*a.y; v[4] -= a.y*a.z;
+		v[5] -= a.z*a.z;
+	}
+};
+
+typedef SymMat3<float>  SymMat3f;
+typedef SymMat3<double> SymMat3d;
+
+template<typename T>
+inline Matrix3<T> operator*(const SymMat3<T>& a, const SymMat3<T>& b)
+{
+	#define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c))
+    return Matrix3<T>(
+		AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2),
+		AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2),
+		AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2));
+	#undef AJB_ARBC
+}
+
+template<typename T>
+inline Matrix3<T> operator*(const Matrix3<T>& a, const SymMat3<T>& b)
+{
+	#define AJB_ARBC(r,c) (a(r,0)*b(0,c)+a(r,1)*b(1,c)+a(r,2)*b(2,c))
+	return Matrix3<T>(
+		AJB_ARBC(0,0), AJB_ARBC(0,1), AJB_ARBC(0,2),
+		AJB_ARBC(1,0), AJB_ARBC(1,1), AJB_ARBC(1,2),
+		AJB_ARBC(2,0), AJB_ARBC(2,1), AJB_ARBC(2,2));
+	#undef AJB_ARBC
+}
+
+//-------------------------------------------------------------------------------------
+// ***** Angle
+
+// Cleanly representing the algebra of 2D rotations.
+// The operations maintain the angle between -Pi and Pi, the same range as atan2.
+
+template<class T>
+class Angle
+{
+public:
+	enum AngularUnits
+	{
+		Radians = 0,
+		Degrees = 1
+	};
+
+    Angle() : a(0) {}
+    
+	// Fix the range to be between -Pi and Pi
+	Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*Math<T>::DegreeToRadFactor) { FixRange(); }
+
+	T    Get(AngularUnits u = Radians) const       { return (u == Radians) ? a : a*Math<T>::RadToDegreeFactor; }
+	void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*Math<T>::DegreeToRadFactor; FixRange(); }
+	int Sign() const                               { if (a == 0) return 0; else return (a > 0) ? 1 : -1; }
+	T   Abs() const                                { return (a > 0) ? a : -a; }
+
+    bool operator== (const Angle& b) const    { return a == b.a; }
+    bool operator!= (const Angle& b) const    { return a != b.a; }
+//	bool operator<  (const Angle& b) const    { return a < a.b; } 
+//	bool operator>  (const Angle& b) const    { return a > a.b; } 
+//	bool operator<= (const Angle& b) const    { return a <= a.b; } 
+//	bool operator>= (const Angle& b) const    { return a >= a.b; } 
+//	bool operator= (const T& x)               { a = x; FixRange(); }
+
+	// These operations assume a is already between -Pi and Pi.
+	Angle& operator+= (const Angle& b)        { a = a + b.a; FastFixRange(); return *this; }
+	Angle& operator+= (const T& x)            { a = a + x; FixRange(); return *this; }
+    Angle  operator+  (const Angle& b) const  { Angle res = *this; res += b; return res; }
+	Angle  operator+  (const T& x) const      { Angle res = *this; res += x; return res; }
+	Angle& operator-= (const Angle& b)        { a = a - b.a; FastFixRange(); return *this; }
+	Angle& operator-= (const T& x)            { a = a - x; FixRange(); return *this; }
+	Angle  operator-  (const Angle& b) const  { Angle res = *this; res -= b; return res; }
+	Angle  operator-  (const T& x) const      { Angle res = *this; res -= x; return res; }
+	
+	T   Distance(const Angle& b)              { T c = fabs(a - b.a); return (c <= Math<T>::Pi) ? c : Math<T>::TwoPi - c; }
+
+private:
+
+	// The stored angle, which should be maintained between -Pi and Pi
+	T a;
+
+	// Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side 
+	inline void FastFixRange()
+	{
+		if (a < -Math<T>::Pi)
+			a += Math<T>::TwoPi;
+		else if (a > Math<T>::Pi)
+			a -= Math<T>::TwoPi;
+	}
+
+	// Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method
+	inline void FixRange()
+	{
+        // do nothing if the value is already in the correct range, since fmod call is expensive
+        if (a >= -Math<T>::Pi && a <= Math<T>::Pi)
+            return;
+		a = fmod(a,Math<T>::TwoPi);
+		if (a < -Math<T>::Pi)
+			a += Math<T>::TwoPi;
+		else if (a > Math<T>::Pi)
+			a -= Math<T>::TwoPi;
+	}
+};
+
+
+typedef Angle<float>  Anglef;
+typedef Angle<double> Angled;
+
+
+//-------------------------------------------------------------------------------------
+// ***** Plane
+
+// Consists of a normal vector and distance from the origin where the plane is located.
+
+template<class T>
+class Plane : public RefCountBase<Plane<T> >
+{
+public:
+    Vector3<T> N;
+    T          D;
+
+    Plane() : D(0) {}
+
+    // Normals must already be normalized
+    Plane(const Vector3<T>& n, T d) : N(n), D(d) {}
+    Plane(T x, T y, T z, T d) : N(x,y,z), D(d) {}
+
+    // construct from a point on the plane and the normal
+    Plane(const Vector3<T>& p, const Vector3<T>& n) : N(n), D(-(p * n)) {}
+
+    // Find the point to plane distance. The sign indicates what side of the plane the point is on (0 = point on plane).
+    T TestSide(const Vector3<T>& p) const
+    {
+        return (N.Dot(p)) + D;
+    }
+
+    Plane<T> Flipped() const
+    {
+        return Plane(-N, -D);
+    }
+
+    void Flip()
+    {
+        N = -N;
+        D = -D;
+    }
+
+	bool operator==(const Plane<T>& rhs) const
+	{
+		return (this->D == rhs.D && this->N == rhs.N);
+	}
+};
+
+typedef Plane<float> Planef;
+
+} // Namespace OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_RefCount.cpp b/LibOVR/Src/Kernel/OVR_RefCount.cpp
new file mode 100644
index 0000000..c6301ed
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_RefCount.cpp
@@ -0,0 +1,111 @@
+/************************************************************************************
+
+Filename    :   OVR_RefCount.cpp
+Content     :   Reference counting implementation
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_RefCount.h"
+#include "OVR_Atomic.h"
+#include "OVR_Log.h"
+
+namespace OVR {
+
+#ifdef OVR_CC_ARM
+void* ReturnArg0(void* p)
+{
+    return p;
+}
+#endif
+
+// ***** Reference Count Base implementation
+
+RefCountImplCore::~RefCountImplCore()
+{
+    // RefCount can be either 1 or 0 here.
+    //  0 if Release() was properly called.
+    //  1 if the object was declared on stack or as an aggregate.
+    OVR_ASSERT(RefCount <= 1);
+}
+
+#ifdef OVR_BUILD_DEBUG
+void RefCountImplCore::reportInvalidDelete(void *pmem)
+{
+    OVR_DEBUG_LOG(
+        ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem));
+    OVR_ASSERT(0);
+}
+#endif
+
+RefCountNTSImplCore::~RefCountNTSImplCore()
+{
+    // RefCount can be either 1 or 0 here.
+    //  0 if Release() was properly called.
+    //  1 if the object was declared on stack or as an aggregate.
+    OVR_ASSERT(RefCount <= 1);
+}
+
+#ifdef OVR_BUILD_DEBUG
+void RefCountNTSImplCore::reportInvalidDelete(void *pmem)
+{
+    OVR_DEBUG_LOG(
+        ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem));
+    OVR_ASSERT(0);
+}
+#endif
+
+
+// *** Thread-Safe RefCountImpl
+
+void    RefCountImpl::AddRef()
+{
+    AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1);
+}
+void    RefCountImpl::Release()
+{
+    if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
+        delete this;
+}
+
+// *** Thread-Safe RefCountVImpl w/virtual AddRef/Release
+
+void    RefCountVImpl::AddRef()
+{
+    AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1);
+}
+void    RefCountVImpl::Release()
+{
+    if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
+        delete this;
+}
+
+// *** NON-Thread-Safe RefCountImpl
+
+void    RefCountNTSImpl::Release() const
+{
+    RefCount--;
+    if (RefCount == 0)
+        delete this;
+}
+
+
+} // OVR
diff --git a/LibOVR/Src/Kernel/OVR_RefCount.h b/LibOVR/Src/Kernel/OVR_RefCount.h
new file mode 100644
index 0000000..775e24c
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_RefCount.h
@@ -0,0 +1,564 @@
+/************************************************************************************
+
+PublicHeader:   Kernel
+Filename    :   OVR_RefCount.h
+Content     :   Reference counting implementation headers
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_RefCount_h
+#define OVR_RefCount_h
+
+#include "OVR_Types.h"
+#include "OVR_Allocator.h"
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** Reference Counting
+
+// There are three types of reference counting base classes:
+//
+//  RefCountBase     - Provides thread-safe reference counting (Default).
+//  RefCountBaseNTS  - Non Thread Safe version of reference counting.
+
+
+// ***** Declared classes
+
+template<class C>
+class   RefCountBase;
+template<class C>
+class   RefCountBaseNTS;
+
+class   RefCountImpl;
+class   RefCountNTSImpl;
+
+
+//-----------------------------------------------------------------------------------
+// ***** Implementation For Reference Counting
+
+// RefCountImplCore holds RefCount value and defines a few utility
+// functions shared by all implementations.
+
+class RefCountImplCore
+{
+protected:
+   volatile int RefCount;
+
+public:
+    // RefCountImpl constructor always initializes RefCount to 1 by default.
+    OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { }
+
+    // Need virtual destructor
+    // This:    1. Makes sure the right destructor's called.
+    //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
+    virtual ~RefCountImplCore();
+
+    // Debug method only.
+    int GetRefCount() const { return RefCount;  }
+
+    // This logic is used to detect invalid 'delete' calls of reference counted
+    // objects. Direct delete calls are not allowed on them unless they come in
+    // internally from Release.
+#ifdef OVR_BUILD_DEBUG    
+    static void   OVR_CDECL  reportInvalidDelete(void *pmem);
+    inline static void checkInvalidDelete(RefCountImplCore *pmem)
+    {
+        if (pmem->RefCount != 0)
+            reportInvalidDelete(pmem);
+    }
+#else
+    inline static void checkInvalidDelete(RefCountImplCore *) { }
+#endif
+
+    // Base class ref-count content should not be copied.
+    void operator = (const RefCountImplCore &) { }  
+};
+
+class RefCountNTSImplCore
+{
+protected:
+    mutable int RefCount;
+
+public:
+    // RefCountImpl constructor always initializes RefCount to 1 by default.
+    OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { }
+
+    // Need virtual destructor
+    // This:    1. Makes sure the right destructor's called.
+    //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
+    virtual ~RefCountNTSImplCore();
+
+    // Debug method only.
+    int             GetRefCount() const { return RefCount;  }
+
+    // This logic is used to detect invalid 'delete' calls of reference counted
+    // objects. Direct delete calls are not allowed on them unless they come in
+    // internally from Release.
+#ifdef OVR_BUILD_DEBUG    
+    static void   OVR_CDECL  reportInvalidDelete(void *pmem);
+    OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem)
+    {
+        if (pmem->RefCount != 0)
+            reportInvalidDelete(pmem);
+    }
+#else
+    OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { }
+#endif
+
+    // Base class ref-count content should not be copied.
+    void operator = (const RefCountNTSImplCore &) { }  
+};
+
+
+
+// RefCountImpl provides Thread-Safe implementation of reference counting, so
+// it should be used by default in most places.
+
+class RefCountImpl : public RefCountImplCore
+{
+public:
+    // Thread-Safe Ref-Count Implementation.
+    void    AddRef();
+    void    Release();   
+};
+
+// RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
+// virtual AddRef and Release.
+
+class RefCountVImpl : virtual public RefCountImplCore
+{
+public:
+    // Thread-Safe Ref-Count Implementation.
+    virtual void      AddRef();
+    virtual void      Release();   
+};
+
+
+// RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
+// which is slightly more efficient since it doesn't use atomics.
+
+class RefCountNTSImpl : public RefCountNTSImplCore
+{
+public:
+    OVR_FORCE_INLINE void    AddRef() const { RefCount++; }
+    void    Release() const;   
+};
+
+
+
+// RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
+// to the reference counting implementation. Base must be one of the RefCountImpl classes.
+
+template<class Base>
+class RefCountBaseStatImpl : public Base
+{
+public:
+    RefCountBaseStatImpl() { }
+     
+    // *** Override New and Delete
+
+    // DOM-IGNORE-BEGIN
+    // Undef new temporarily if it is being redefined
+#ifdef OVR_DEFINE_NEW
+#undef new
+#endif
+
+#ifdef OVR_BUILD_DEBUG
+    // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
+    #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)   \
+        do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
+#else
+    #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
+#endif
+
+    // Redefine all new & delete operators.
+    OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
+
+#undef OVR_REFCOUNTALLOC_CHECK_DELETE
+
+#ifdef OVR_DEFINE_NEW
+#define new OVR_DEFINE_NEW
+#endif
+        // OVR_BUILD_DEFINE_NEW
+        // DOM-IGNORE-END
+};
+
+
+template<class Base>
+class RefCountBaseStatVImpl : virtual public Base
+{
+public:
+	RefCountBaseStatVImpl() { }
+
+	// *** Override New and Delete
+
+	// DOM-IGNORE-BEGIN
+	// Undef new temporarily if it is being redefined
+#ifdef OVR_DEFINE_NEW
+#undef new
+#endif
+
+#define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
+
+	// Redefine all new & delete operators.
+	OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
+
+#undef OVR_REFCOUNTALLOC_CHECK_DELETE
+
+#ifdef OVR_DEFINE_NEW
+#define new OVR_DEFINE_NEW
+#endif
+		// OVR_BUILD_DEFINE_NEW
+		// DOM-IGNORE-END
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// *** End user RefCountBase<> classes
+
+
+// RefCountBase is a base class for classes that require thread-safe reference
+// counting; it also overrides the new and delete operators to use MemoryHeap.
+//
+// Reference counted objects start out with RefCount value of 1. Further lifetime
+// management is done through the AddRef() and Release() methods, typically
+// hidden by Ptr<>.
+
+template<class C>
+class RefCountBase : public RefCountBaseStatImpl<RefCountImpl>
+{
+public:    
+    // Constructor.
+    OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { }    
+};
+
+// RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
+
+template<class C>
+class RefCountBaseV : virtual public RefCountBaseStatVImpl<RefCountVImpl>
+{
+public:    
+    // Constructor.
+    OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatVImpl<RefCountVImpl>() { }    
+};
+
+
+// RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
+// counting; it also overrides the new and delete operators to use MemoryHeap.
+// This class should only be used if all pointers to it are known to be assigned,
+// destroyed and manipulated within one thread.
+//
+// Reference counted objects start out with RefCount value of 1. Further lifetime
+// management is done through the AddRef() and Release() methods, typically
+// hidden by Ptr<>.
+
+template<class C>
+class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl>
+{
+public:    
+    // Constructor.
+    OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { }    
+};
+
+//-----------------------------------------------------------------------------------
+// ***** Pickable template pointer
+enum PickType { PickValue };
+
+template <typename T>
+class Pickable
+{
+public:
+    Pickable() : pV(NULL) {}
+    explicit Pickable(T* p) : pV(p) {}
+    Pickable(T* p, PickType) : pV(p) 
+    {
+        OVR_ASSERT(pV);
+        if (pV)
+            pV->AddRef();
+    }
+    template <typename OT>
+    Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {}
+
+public:
+    Pickable& operator =(const Pickable& other)
+    {
+        OVR_ASSERT(pV == NULL);
+        pV = other.pV;
+        // Extra check.
+        //other.pV = NULL;
+        return *this;
+    }
+
+public:
+    T* GetPtr() const { return pV; }
+    T* operator->() const
+    {
+        return pV;
+    }
+    T& operator*() const
+    {
+        OVR_ASSERT(pV);
+        return *pV;
+    }
+
+private:
+    T* pV;
+};
+
+template <typename T>
+OVR_FORCE_INLINE
+Pickable<T> MakePickable(T* p)
+{
+    return Pickable<T>(p);
+}
+
+//-----------------------------------------------------------------------------------
+// ***** Ref-Counted template pointer
+
+// Automatically AddRefs and Releases interfaces
+
+void* ReturnArg0(void* p);
+
+template<class C>
+class Ptr
+{
+#ifdef OVR_CC_ARM
+    static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); }
+#endif
+
+protected:
+    C   *pObject;
+
+public:
+
+    // Constructors
+    OVR_FORCE_INLINE Ptr() : pObject(0)
+    { }
+#ifdef OVR_CC_ARM
+    OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj))
+#else
+    OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj)
+#endif
+    { }
+    OVR_FORCE_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr())
+    {
+        // No AddRef() on purpose.
+    }
+    OVR_FORCE_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject)
+    {
+        other.pObject = NULL;
+        // No AddRef() on purpose.
+    }
+    OVR_FORCE_INLINE Ptr(C *pobj)
+    {
+        if (pobj) pobj->AddRef();   
+        pObject = pobj;
+    }
+    OVR_FORCE_INLINE Ptr(const Ptr<C> &src)
+    {
+        if (src.pObject) src.pObject->AddRef();     
+        pObject = src.pObject;
+    }
+
+    template<class R>
+    OVR_FORCE_INLINE Ptr(Ptr<R> &src)
+    {
+        if (src) src->AddRef();
+        pObject = src;
+    }
+    template<class R>
+    OVR_FORCE_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr())
+    {
+        // No AddRef() on purpose.
+    }
+
+    // Destructor
+    OVR_FORCE_INLINE ~Ptr()
+    {
+        if (pObject) pObject->Release();        
+    }
+
+    // Compares
+    OVR_FORCE_INLINE bool operator == (const Ptr &other) const       { return pObject == other.pObject; }
+    OVR_FORCE_INLINE bool operator != (const Ptr &other) const       { return pObject != other.pObject; }
+
+    OVR_FORCE_INLINE bool operator == (C *pother) const              { return pObject == pother; }
+    OVR_FORCE_INLINE bool operator != (C *pother) const              { return pObject != pother; }
+
+
+    OVR_FORCE_INLINE bool operator < (const Ptr &other) const       { return pObject < other.pObject; }
+
+    // Assignment
+    template<class R>
+    OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src)
+    {
+        if (src) src->AddRef();
+        if (pObject) pObject->Release();        
+        pObject = src;
+        return *this;
+    }   
+    // Specialization
+    OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src)
+    {
+        if (src) src->AddRef();
+        if (pObject) pObject->Release();        
+        pObject = src;
+        return *this;
+    }   
+    
+    OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc)
+    {
+        if (psrc) psrc->AddRef();
+        if (pObject) pObject->Release();        
+        pObject = psrc;
+        return *this;
+    }   
+    OVR_FORCE_INLINE const Ptr<C>& operator = (C &src)
+    {       
+        if (pObject) pObject->Release();        
+        pObject = &src;
+        return *this;
+    }
+    OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<C> src)
+    {
+        return Pick(src);
+    }
+    template<class R>
+    OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<R> src)
+    {
+        return Pick(src);
+    }
+    
+    // Set Assignment
+    template<class R>
+    OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src)
+    {
+        if (src) src->AddRef();
+        if (pObject) pObject->Release();
+        pObject = src;
+        return *this;
+    }
+    // Specialization
+    OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src)
+    {
+        if (src) src->AddRef();
+        if (pObject) pObject->Release();
+        pObject = src;
+        return *this;
+    }   
+    
+    OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc)
+    {
+        if (psrc) psrc->AddRef();
+        if (pObject) pObject->Release();
+        pObject = psrc;
+        return *this;
+    }   
+    OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src)
+    {       
+        if (pObject) pObject->Release();
+        pObject = &src;
+        return *this;
+    }
+    OVR_FORCE_INLINE Ptr<C>& SetPtr(Pickable<C> src)
+    {       
+        return Pick(src);
+    }
+
+    // Nulls ref-counted pointer without decrement
+    OVR_FORCE_INLINE void    NullWithoutRelease()    
+    { 
+        pObject = 0;    
+    }
+
+    // Clears the pointer to the object
+    OVR_FORCE_INLINE void    Clear()
+    {
+        if (pObject) pObject->Release();
+        pObject = 0;
+    }
+
+    // Obtain pointer reference directly, for D3D interfaces
+    OVR_FORCE_INLINE C*& GetRawRef()                 { return pObject; }
+
+    // Access Operators
+    OVR_FORCE_INLINE C* GetPtr() const               { return pObject; }
+    OVR_FORCE_INLINE C& operator * () const          { return *pObject; }
+    OVR_FORCE_INLINE C* operator -> ()  const        { return pObject; }
+    // Conversion                   
+    OVR_FORCE_INLINE operator C* () const            { return pObject; }
+
+    // Pickers.
+
+    // Pick a value.
+    OVR_FORCE_INLINE Ptr<C>& Pick(Ptr<C>& other)
+    {
+        if (&other != this)
+        {
+            if (pObject) pObject->Release();
+            pObject = other.pObject;
+            other.pObject = 0;
+        }
+
+        return *this;
+    }
+
+    OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<C> v)
+    {
+        if (v.GetPtr() != pObject)
+        {
+            if (pObject) pObject->Release();
+            pObject = v.GetPtr();
+        }
+
+        return *this;
+    }
+
+    template<class R>
+    OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<R> v)
+    {
+        if (v.GetPtr() != pObject)
+        {
+            if (pObject) pObject->Release();
+            pObject = v.GetPtr();
+        }
+
+        return *this;
+    }
+
+    OVR_FORCE_INLINE Ptr<C>& Pick(C* p)
+    {
+        if (p != pObject)
+        {
+            if (pObject) pObject->Release();
+            pObject = p;
+        }
+
+        return *this;
+    }
+};
+
+} // OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_Std.cpp b/LibOVR/Src/Kernel/OVR_Std.cpp
new file mode 100644
index 0000000..6b5be18
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Std.cpp
@@ -0,0 +1,1036 @@
+/************************************************************************************
+
+Filename    :   OVR_Std.cpp
+Content     :   Standard C function implementation
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_Std.h"
+#include "OVR_Alg.h"
+
+// localeconv() call in OVR_strtod()
+#include <locale.h>
+
+namespace OVR {
+
+// Source for functions not available on all platforms is included here.
+
+// Case insensitive compare implemented in platform-specific way.
+int OVR_CDECL OVR_stricmp(const char* a, const char* b)
+{
+#if defined(OVR_OS_WIN32)
+    #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
+        return ::_stricmp(a, b);
+    #else
+        return ::stricmp(a, b);
+    #endif
+
+#else
+    return strcasecmp(a, b);
+#endif
+}
+
+int OVR_CDECL OVR_strnicmp(const char* a, const char* b, UPInt count)
+{
+#if defined(OVR_OS_WIN32)
+#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
+    return ::_strnicmp(a, b, count);
+#else
+    return ::strnicmp(a, b, count);
+#endif
+
+#else
+    return strncasecmp(a, b, count);
+#endif
+}
+
+wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src)
+{
+#if defined(OVR_MSVC_SAFESTRING)
+    wcscpy_s(dest, destsize, src);
+    return dest;
+#elif defined(OVR_OS_WIN32)
+    OVR_UNUSED(destsize);
+    wcscpy(dest, src);
+    return dest;
+#else
+    UPInt l = OVR_wcslen(src) + 1; // incl term null
+    l = (l < destsize) ? l : destsize;
+    memcpy(dest, src, l * sizeof(wchar_t));
+    return dest;
+#endif
+}
+
+wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count)
+{
+#if defined(OVR_MSVC_SAFESTRING)
+    wcsncpy_s(dest, destsize, src, count);
+    return dest;
+#else
+    UPInt srclen = OVR_wcslen(src);
+    UPInt l = Alg::Min(srclen, count);
+    l = (l < destsize) ? l : destsize;
+    memcpy(dest, src, l * sizeof(wchar_t));
+    if (count > srclen)
+    {
+        UPInt remLen = Alg::Min(destsize - l, (count - srclen));
+        memset(&dest[l], 0, sizeof(wchar_t)*remLen);
+    }
+    else if (l < destsize)
+        dest[l] = 0;
+    return dest;
+#endif
+}
+
+
+wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src)
+{
+#if defined(OVR_MSVC_SAFESTRING)
+    wcscat_s(dest, destsize, src);
+    return dest;
+#elif defined(OVR_OS_WIN32)
+    OVR_UNUSED(destsize);
+    wcscat(dest, src);
+    return dest;
+#else
+    UPInt dstlen = OVR_wcslen(dest); // do not incl term null
+    UPInt srclen = OVR_wcslen(src) + 1; // incl term null
+    UPInt copylen = (dstlen + srclen < destsize) ? srclen : destsize - dstlen;
+    memcpy(dest + dstlen, src, copylen * sizeof(wchar_t));
+    return dest;
+#endif
+}
+
+UPInt   OVR_CDECL OVR_wcslen(const wchar_t* str)
+{
+#if defined(OVR_OS_WIN32)
+    return wcslen(str);
+#else
+    UPInt i = 0;
+    while(str[i] != '\0')
+        ++i;
+    return i;
+#endif
+}
+
+int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b)
+{
+#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX)
+    return wcscmp(a, b);
+#else
+    // not supported, use custom implementation
+    const wchar_t *pa = a, *pb = b;
+    while (*pa && *pb)
+    {
+        wchar_t ca = *pa;
+        wchar_t cb = *pb;
+        if (ca < cb)
+            return -1;
+        else if (ca > cb)
+            return 1;
+        pa++;
+        pb++;
+    }
+    if (*pa)
+        return 1;
+    else if (*pb)
+        return -1;
+    else
+        return 0;
+#endif
+}
+
+int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b)
+{
+#if defined(OVR_OS_WIN32)
+#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
+    return ::_wcsicmp(a, b);
+#else
+    return ::wcsicmp(a, b);
+#endif
+#elif defined(OVR_OS_MAC) || defined(__CYGWIN__) || defined(OVR_OS_ANDROID) || defined(OVR_OS_IPHONE)
+    // not supported, use custom implementation
+    const wchar_t *pa = a, *pb = b;
+    while (*pa && *pb)
+    {
+        wchar_t ca = OVR_towlower(*pa);
+        wchar_t cb = OVR_towlower(*pb);
+        if (ca < cb)
+            return -1;
+        else if (ca > cb)
+            return 1;
+        pa++;
+        pb++;
+    }
+    if (*pa)
+        return 1;
+    else if (*pb)
+        return -1;
+    else
+        return 0;
+#else
+    return wcscasecmp(a, b);
+#endif
+}
+
+// This function is not inline because of dependency on <locale.h>
+double OVR_CDECL OVR_strtod(const char* string, char** tailptr)
+{
+#if !defined(OVR_OS_ANDROID)
+    const char s = *localeconv()->decimal_point;
+
+    if (s != '.')
+    {
+        char buffer[347 + 1];
+
+        OVR_strcpy(buffer, sizeof(buffer), string);
+
+        for (char* c = buffer; *c != '\0'; ++c)
+        {
+            if (*c == '.')
+            {
+                *c = s;
+                break;
+            }
+        }
+
+        return strtod(buffer, tailptr);
+    }
+#endif
+
+    return strtod(string, tailptr);
+}
+
+
+#ifndef OVR_NO_WCTYPE
+
+//// Use this class to generate Unicode bitsets. For example:
+////
+//// UnicodeBitSet bitSet;
+//// for(unsigned i = 0; i < 65536; ++i)
+//// {
+////     if (iswalpha(i))
+////         bitSet.Set(i);
+//// }
+//// bitSet.Dump();
+////
+////---------------------------------------------------------------
+//class UnicodeBitSet
+//{
+//public:
+//    UnicodeBitSet()
+//    {
+//        memset(Offsets, 0, sizeof(Offsets));
+//        memset(Bits,    0, sizeof(Bits));
+//    }
+//
+//    void Set(unsigned bit) { Bits[bit >> 8][(bit >> 4) & 15] |= 1 << (bit & 15); }
+//
+//    void Dump()
+//    {
+//        unsigned i, j;
+//        unsigned offsetCount = 0;
+//        for(i = 0; i < 256; ++i)
+//        {
+//            if (isNull(i)) Offsets[i] = 0;
+//            else
+//            if (isFull(i)) Offsets[i] = 1;
+//            else           Offsets[i] = UInt16(offsetCount++ * 16 + 256);
+//        }
+//        for(i = 0; i < 16; ++i)
+//        {
+//            for(j = 0; j < 16; ++j)
+//            {
+//                printf("%5u,", Offsets[i*16+j]);
+//            }
+//            printf("\n");
+//        }
+//        for(i = 0; i < 256; ++i)
+//        {
+//            if (Offsets[i] > 255)
+//            {
+//                for(j = 0; j < 16; j++)
+//                {
+//                    printf("%5u,", Bits[i][j]);
+//                }
+//                printf("\n");
+//            }
+//        }
+//    }
+//
+//private:
+//    bool isNull(unsigned n) const
+//    {
+//        const UInt16* p = Bits[n];
+//        for(unsigned i = 0; i < 16; ++i)
+//            if (p[i] != 0) return false;
+//        return true;
+//    }
+//
+//    bool isFull(unsigned n) const
+//    {
+//        const UInt16* p = Bits[n];
+//        for(unsigned i = 0; i < 16; ++i)
+//            if (p[i] != 0xFFFF) return false;
+//        return true;
+//    }
+//
+//    UInt16 Offsets[256];
+//    UInt16 Bits[256][16];
+//};
+
+
+const UInt16 UnicodeAlnumBits[] = {
+  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
+  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
+  640,  656,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  672,  688,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  704,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,
+    1,    1,    1,    1,  736,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  768,  784,    1,  800,  816,  832,
+    0,    0,    0, 1023,65534, 2047,65534, 2047,    0,    0,    0,  524,65535,65407,65535,65407,
+65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
+    0,    0,    0,    0,   32,    0,    0, 1024,55104,65535,65531,65535,32767,64767,65535,   15,
+65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
+    0,    0,    0,65534,65535,  639,65534,65535,  255,    0,    0,    0,    0,65535, 2047,    7,
+    0,    0,65534, 2047,65534,   63, 1023,65535,65535,65535,65535,65535,65535, 8175, 8702, 8191,
+    0,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
+65518,65535,65535,58367, 8191,65281,65487,    0,40942,65529,65023,50117, 6559,45184,65487,    3,
+34788,65529,65023,50029, 6535,24064,65472,   31,45038,65531,65023,58349, 7103,    1,65473,    0,
+40942,65529,65023,58317, 6543,45248,65475,    0,51180,54845,50968,50111, 7623,  128,65408,    0,
+57326,65533,65023,50159, 7647,   96,65475,    0,57324,65533,65023,50159, 7647,16480,65475,    0,
+57324,65533,65023,50175, 7631,  128,65475,    0,65516,64639,65535,12283,32895,65375,    0,   12,
+65534,65535,65535, 2047,32767, 1023,    0,    0, 9622,65264,60590,15359, 8223,13311,    0,    0,
+    1,    0, 1023,    0,65279,65535, 2047,65534, 3843,65279,65535, 8191,    0,    0,    0,    0,
+65535,65535,63227,  327, 1023, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535,  127,
+65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
+65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
+32767,32573,65535,65535,65407, 2047,65024,    3,    0,    0,65535,65535,65535,65535,65535,   31,
+65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
+65535,65535,65535,65535,65535,65535,40959,  127,65534, 2047,65535,65535,65535,65535, 2047,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511,    0, 1023,    0,
+    0, 1023,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
+65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
+    0,    0,    0,    0,    0,    0,    0,32768,    0,    0,    0,    0,    0,    0,    0,    0,
+64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
+  192,    0, 1022, 1792,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 2047,
+65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
+65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
+65535,65535,65535,16383,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
+    0,    0,    0,    0,    0,    0,    0,65495,65535,65535,65535,65535,65535,65535,65535, 8191,
+    0, 1023,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
+
+const UInt16 UnicodeAlphaBits[] = {
+  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
+  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
+  640,  656,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  672,  688,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  704,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,
+    1,    1,    1,    1,  736,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+    1,    1,    1,    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  768,  784,    1,  800,  816,  832,
+    0,    0,    0,    0,65534, 2047,65534, 2047,    0,    0,    0,    0,65535,65407,65535,65407,
+65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
+    0,    0,    0,    0,   32,    0,    0, 1024,55104,65535,65531,65535,32767,64767,65535,   15,
+65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
+    0,    0,    0,65534,65535,  639,65534,65535,  255,    0,    0,    0,    0,65535, 2047,    7,
+    0,    0,65534, 2047,65534,   63,    0,65535,65535,65535,65535,65535,65535, 8175, 8702, 7168,
+    0,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
+65518,65535,65535,58367, 8191,65281,   15,    0,40942,65529,65023,50117, 6559,45184,   15,    3,
+34788,65529,65023,50029, 6535,24064,    0,   31,45038,65531,65023,58349, 7103,    1,    1,    0,
+40942,65529,65023,58317, 6543,45248,    3,    0,51180,54845,50968,50111, 7623,  128,    0,    0,
+57326,65533,65023,50159, 7647,   96,    3,    0,57324,65533,65023,50159, 7647,16480,    3,    0,
+57324,65533,65023,50175, 7631,  128,    3,    0,65516,64639,65535,12283,32895,65375,    0,   12,
+65534,65535,65535, 2047,32767,    0,    0,    0, 9622,65264,60590,15359, 8223,12288,    0,    0,
+    1,    0,    0,    0,65279,65535, 2047,65534, 3843,65279,65535, 8191,    0,    0,    0,    0,
+65535,65535,63227,  327,    0, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535,  127,
+65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
+65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
+32767,32573,65535,65535,65407, 2047,    0,    0,    0,    0,65535,65535,65535,65535,65535,   31,
+65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
+65535,65535,65535,65535,65535,65535,40959,  127,65534, 2047,65535,65535,65535,65535, 2047,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511,    0,    0,    0,
+    0,    0,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
+65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
+    0,    0,    0,    0,    0,    0,    0,32768,    0,    0,    0,    0,    0,    0,    0,    0,
+64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
+  192,    0, 1022, 1792,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 2047,
+65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
+65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
+65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
+65535,65535,65535,16383,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
+    0,    0,    0,    0,    0,    0,    0,65495,65535,65535,65535,65535,65535,65535,65535, 8191,
+    0,    0,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
+
+const UInt16 UnicodeDigitBits[] = {
+  256,    0,    0,    0,    0,    0,  272,    0,    0,  288,  304,  320,  336,  352,  368,  384,
+  400,    0,    0,  416,    0,    0,    0,  432,  448,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  464,
+    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,  524,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0, 1023,
+    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65472,    0,
+    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65472,    0,
+    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65408,    0,
+    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65472,    0,
+    0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0, 1023,    0,    0,
+    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,65024,    3,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 1023,    0,
+    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
+
+const UInt16 UnicodeSpaceBits[] = {
+  256,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,  272,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  288,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  304,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+15872,    0,    1,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,    0,    0,    0,    0,
+ 4095,    0,33536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
+
+const UInt16 UnicodeXDigitBits[] = {
+  256,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  272,
+    0,    0,    0, 1023,  126,    0,  126,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0, 1023,  126,    0,  126,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
+
+// Uncomment if necessary
+//const UInt16 UnicodeCntrlBits[] = {
+//  256,    0,    0,    0,    0,    0,    0,  272,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,  288,    0,    0,    0,    0,    0,    0,    0,
+//  304,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  320,  336,
+//65535,65535,    0,    0,    0,    0,    0,32768,65535,65535,    0,    0,    0,    0,    0,    0,
+//32768,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//30720,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//61440,    0,31744,    0,    0,    0,64512,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,32768,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 3584};
+//
+//const UInt16 UnicodeGraphBits[] = {
+//  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
+//  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
+//  640,  656,    0,  672,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//  688,  704,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  736,
+//    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,  768,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  784,  800,    1,  816,  832,  848,
+//    0,    0,65534,65535,65535,65535,65535,32767,    0,    0,65534,65535,65535,65535,65535,65535,
+//65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
+//    0,    0,    0,    0,   32,    0,    0,17408,55232,65535,65531,65535,32767,64767,65535,   15,
+//65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
+//    0,    0,    0,65534,65535,65151,65534,65535, 1791,    0,    0,16384,    9,65535, 2047,   31,
+// 4096,34816,65534, 2047,65534,   63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191,
+//16383,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
+//65518,65535,65535,58367, 8191,65281,65535,    1,40942,65529,65023,50117, 6559,45184,65487,    3,
+//34788,65529,65023,50029, 6535,24064,65472,   31,45038,65531,65023,58349, 7103,    1,65473,    0,
+//40942,65529,65023,58317, 6543,45248,65475,    0,51180,54845,50968,50111, 7623,  128,65408,    0,
+//57326,65533,65023,50159, 7647,   96,65475,    0,57324,65533,65023,50159, 7647,16480,65475,    0,
+//57324,65533,65023,50175, 7631,  128,65475,    0,65516,64639,65535,12283,32895,65375,    0,   28,
+//65534,65535,65535, 2047,65535, 4095,    0,    0, 9622,65264,60590,15359, 8223,13311,    0,    0,
+//65521,    7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191,    0,    0,    0,    0,
+//65535,65535,63227,  327,65535, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535, 2175,
+//65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
+//65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
+//32767,32573,65535,65535,65407, 2047,65534,    3,    0,    0,65535,65535,65535,65535,65535,   31,
+//65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
+//65535,65535,65535,65535,65535,65535,65535,  127,65534, 8191,65535,65535,65535,65535,16383,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511, 6128, 1023,    0,
+// 2047, 1023,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
+//65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
+//    0,65535,  255,65535,16239,    0,    0,57344,24576,    0,    0,    0,    0,    0,    0,    0,
+//64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0, 1536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//65486,65523, 1022, 1793,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 4095,
+//65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
+//65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
+//65535,65535,65535,65535,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
+//    0,    0,    0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535, 8191,
+//63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
+//
+//const UInt16 UnicodePrintBits[] = {
+//  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
+//  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
+//  640,  656,    0,  672,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//  688,  704,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  736,
+//    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+//    1,    1,    1,    1,    1,    1,    1,  768,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  784,  800,    1,  816,  832,  848,
+//  512,    0,65535,65535,65535,65535,65535,32767,    0,    0,65535,65535,65535,65535,65535,65535,
+//65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
+//    0,    0,    0,    0,   32,    0,    0,17408,55232,65535,65531,65535,32767,64767,65535,   15,
+//65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
+//    0,    0,    0,65534,65535,65151,65534,65535, 1791,    0,    0,16384,    9,65535, 2047,   31,
+// 4096,34816,65534, 2047,65534,   63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191,
+//16383,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
+//65518,65535,65535,58367, 8191,65281,65535,    1,40942,65529,65023,50117, 6559,45184,65487,    3,
+//34788,65529,65023,50029, 6535,24064,65472,   31,45038,65531,65023,58349, 7103,    1,65473,    0,
+//40942,65529,65023,58317, 6543,45248,65475,    0,51180,54845,50968,50111, 7623,  128,65408,    0,
+//57326,65533,65023,50159, 7647,   96,65475,    0,57324,65533,65023,50159, 7647,16480,65475,    0,
+//57324,65533,65023,50175, 7631,  128,65475,    0,65516,64639,65535,12283,32895,65375,    0,   28,
+//65534,65535,65535, 2047,65535, 4095,    0,    0, 9622,65264,60590,15359, 8223,13311,    0,    0,
+//65521,    7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191,    0,    0,    0,    0,
+//65535,65535,63227,  327,65535, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535, 2175,
+//65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
+//65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
+//32767,32573,65535,65535,65407, 2047,65534,    3,    0,    0,65535,65535,65535,65535,65535,   31,
+//65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
+//65535,65535,65535,65535,65535,65535,65535,  127,65534, 8191,65535,65535,65535,65535,16383,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511, 6128, 1023,    0,
+// 2047, 1023,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
+//65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
+//    0,65535,  255,65535,16239,    0,    0,57344,24576,    0,    0,    0,    0,    0,    0,    0,
+//64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0, 1536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//65487,65523, 1022, 1793,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 4095,
+//65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
+//65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
+//65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
+//65535,65535,65535,65535,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
+//    0,    0,    0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535,40959,
+//63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
+//
+//const UInt16 UnicodePunctBits[] = {
+//  256,    0,    0,  272,    0,  288,  304,  320,    0,  336,    0,    0,    0,  352,  368,  384,
+//  400,    0,    0,  416,    0,    0,  432,  448,  464,    0,    0,    0,    0,    0,    0,    0,
+//  480,    0,    0,  496,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//  512,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  528,  544,  560,
+//    0,    0,65534,64512,    1,63488,    1,30720,    0,    0,65534,65535,    0,  128,    0,  128,
+//    0,    0,    0,    0,    0,    0,    0,16384,  128,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,64512,    0,    0, 1536,    0,    0,16384,    9,    0,    0,   24,
+// 4096,34816,    0,    0,    0,    0,15360,    0,    0,    0,    0,    0,    0,   16,    0,    0,
+//16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,   48,    1,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   16,
+//    0,    0,    0,    0,32768, 3072,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//65520,    7,    0,15360,    0,    0,    0,    0,   32,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,64512,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 2048,
+//    0,    0,    0,    0,    0,    0,  510,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,24576,    0,    0, 6144,    0,    0,    0,    0,14336,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 6128,    0,    0,
+// 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,65535,  255,65535,16239,    0,    0,24576,24576,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0, 1536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//65294,65523,    0,    1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 2048,
+//    0,    0,    0,49152,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,65535,65055,65527, 3339,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//63470,35840,    1,47104,    0,10240,   62,    0,    0,    0,    0,    0,    0,    0,    0,    0};
+//
+//const UInt16 UnicodeLowerBits[] = {
+//  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  352,  368,
+//  384,  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  416,    0,    0,    0,  432,
+//    0,    0,    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,32768,65535,65407,
+//43690,43690,43690,21930,43861,43690,43690,54442,12585,20004,11562,58961,23392,46421,43690,43565,
+//43690,43690,43688,   10,    0,65535,65535,65535,65535,65535,16383,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,61440,65535,32767,43235,43690,   15,
+//    0,    0,    0,65535,65535,65535,43690,43690,40962,43690,43690,43690, 4372,43690,43690,  554,
+//    0,    0,    0,    0,    0,    0,65534,65535,  255,    0,    0,    0,    0,    0,    0,    0,
+//43690,43690,43690,43690,43690,43690,43690,43690,43690, 4074,43690,43690,43690,43690,43690,  682,
+//  255,   63,  255,  255,   63,  255,  255,16383,65535,65535,65535,20703, 4316,  207,  255, 4316,
+//    0,    0,    0,    0,    0,    0,    0,32768,    0,    0,    0,    0,    0,    0,    0,    0,
+//50176,    8,32768,  528,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//  127,  248,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
+//
+//const UInt16 UnicodeUpperBits[] = {
+//  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//  352,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  368,  384,
+//    0,  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  416,
+//    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,65535,32639,    0,    0,
+//21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53973, 4526,44464,19114,21845,21974,
+//21845,21845,21844,    5,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,55104,65534, 4091,    0,    0,21532,21845,    0,
+//65535,65535,65535,    0,    0,    0,21845,21845,20481,21845,21845,21845, 2187,21845,21845,  277,
+//    0,    0,    0,65534,65535,  127,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,   63,    0,    0,    0,
+//21845,21845,21845,21845,21845,21845,21845,21845,21845,   21,21845,21845,21845,21845,21845,  341,
+//65280,16128,65280,65280,16128,43520,65280,    0,65280,65280,65280, 7936, 7936, 3840, 7936, 7936,
+//14468,15911,15696,   11,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+//    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
+
+
+// MA: March 19, 2010
+// Modified ToUpper and ToLower tables to match values expected by AS3 tests.
+// ToLower modifications:
+//    304 ->  105
+//   1024 -> 1104 *
+//   1037 -> 1117 * 
+// UoUpper modifications:
+//    255 ->  376
+//    305 ->   73
+//    383 ->   83
+//   1104 -> 1024 *
+//   1117 -> 1037 *
+// Entries marked with a '*' don't make complete sense based on Unicode manual, although
+// they match AS3.
+
+
+static const UInt16 UnicodeToUpperBits[] = {
+  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  352,  368,
+    0,  384,    0,    0,  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  416,
+    0,    0,    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,65535,65407,
+43690,43690,43690,21674,43349,43690,43690,54442, 4392,  516, 8490, 8785,21056,46421,43690,43048, // MA: Modified for AS3.
+43690,  170,    0,    0,    0, 2776,33545,   36, 3336,    4,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,61440,65534,32767,    0,43688,    0,
+    0,    0,    0,65535,65535,65535,43690,43690,    2,43690,43690,43690, 4372,43690,35498,  554, // MA: Modified for AS3.
+    0,    0,    0,    0,    0,    0,65534,65535,  127,    0,    0,    0,    0,    0,    0,    0,
+43690,43690,43690,43690,43690,43690,43690,43690,43690,   42,43690,43690,43690,43690,43690,  682,
+  255,   63,  255,  255,   63,  170,  255,16383,    0,    0,    0,    3,    0,    3,   35,    0,
+    0,    0,    0,    0,    0,    0,    0,65535,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65535, 1023,    0,
+    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
+
+static const UInt16 UnicodeToLowerBits[] = {
+  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+  352,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  368,  384,
+    0,  400,    0,    0,  416,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  432,
+    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,65535,32639,    0,    0,
+21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53909, 4526,42128,19114,21845,21522,// MA: Modidied for AS3.
+21845,   85,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,55104,65534, 4091,    0,    0,    0,21844,    0,
+65535,65535,65535,    0,    0,    0,21845,21845,    1,21845,21845,21845, 2186,21845,17749,  277,
+    0,    0,    0,65534,65535,  127,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,   63,    0,    0,    0,
+21845,21845,21845,21845,21845,21845,21845,21845,21845,   21,21845,21845,21845,21845,21845,  341,
+65280,16128,65280,65280,16128,43520,65280,    0,    0,    0,    0, 3840, 3840, 3840, 7936, 3840,
+    0,    0,    0,    0,    0,    0,65535,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65472,65535,    0,    0,    0,
+    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
+
+struct GUnicodePairType
+{
+    UInt16 Key, Value;
+};
+
+static inline bool CmpUnicodeKey(const GUnicodePairType& a, UInt16 key)
+{
+    return a.Key < key;
+}
+
+static const GUnicodePairType UnicodeToUpperTable[] = {
+{   97,   65}, {   98,   66}, {   99,   67}, {  100,   68}, {  101,   69}, {  102,   70}, {  103,   71},
+{  104,   72}, {  105,   73}, {  106,   74}, {  107,   75}, {  108,   76}, {  109,   77}, {  110,   78},
+{  111,   79}, {  112,   80}, {  113,   81}, {  114,   82}, {  115,   83}, {  116,   84}, {  117,   85},
+{  118,   86}, {  119,   87}, {  120,   88}, {  121,   89}, {  122,   90}, {  224,  192}, {  225,  193},
+{  226,  194}, {  227,  195}, {  228,  196}, {  229,  197}, {  230,  198}, {  231,  199}, {  232,  200},
+{  233,  201}, {  234,  202}, {  235,  203}, {  236,  204}, {  237,  205}, {  238,  206}, {  239,  207},
+{  240,  208}, {  241,  209}, {  242,  210}, {  243,  211}, {  244,  212}, {  245,  213}, {  246,  214},
+{  248,  216}, {  249,  217}, {  250,  218}, {  251,  219}, {  252,  220}, {  253,  221}, {  254,  222},
+{  255,  376}, {  257,  256}, {  259,  258}, {  261,  260}, {  263,  262}, {  265,  264}, {  267,  266},
+{  269,  268}, {  271,  270}, {  273,  272}, {  275,  274}, {  277,  276}, {  279,  278}, {  281,  280},
+{  283,  282}, {  285,  284}, {  287,  286}, {  289,  288}, {  291,  290}, {  293,  292}, {  295,  294},
+{  297,  296}, {  299,  298}, {  301,  300}, {  303,  302}, {  305,   73}, {  307,  306}, {  309,  308}, {  311,  310},
+{  314,  313}, {  316,  315}, {  318,  317}, {  320,  319}, {  322,  321}, {  324,  323}, {  326,  325},
+{  328,  327}, {  331,  330}, {  333,  332}, {  335,  334}, {  337,  336}, {  339,  338}, {  341,  340},
+{  343,  342}, {  345,  344}, {  347,  346}, {  349,  348}, {  351,  350}, {  353,  352}, {  355,  354},
+{  357,  356}, {  359,  358}, {  361,  360}, {  363,  362}, {  365,  364}, {  367,  366}, {  369,  368},
+{  371,  370}, {  373,  372}, {  375,  374}, {  378,  377}, {  380,  379}, {  382,  381}, {  383,   83}, {  387,  386},
+{  389,  388}, {  392,  391}, {  396,  395}, {  402,  401}, {  409,  408}, {  417,  416}, {  419,  418},
+{  421,  420}, {  424,  423}, {  429,  428}, {  432,  431}, {  436,  435}, {  438,  437}, {  441,  440},
+{  445,  444}, {  454,  452}, {  457,  455}, {  460,  458}, {  462,  461}, {  464,  463}, {  466,  465},
+{  468,  467}, {  470,  469}, {  472,  471}, {  474,  473}, {  476,  475}, {  477,  398}, {  479,  478},
+{  481,  480}, {  483,  482}, {  485,  484}, {  487,  486}, {  489,  488}, {  491,  490}, {  493,  492},
+{  495,  494}, {  499,  497}, {  501,  500}, {  507,  506}, {  509,  508}, {  511,  510}, {  513,  512},
+{  515,  514}, {  517,  516}, {  519,  518}, {  521,  520}, {  523,  522}, {  525,  524}, {  527,  526},
+{  529,  528}, {  531,  530}, {  533,  532}, {  535,  534}, {  595,  385}, {  596,  390}, {  598,  393},
+{  599,  394}, {  601,  399}, {  603,  400}, {  608,  403}, {  611,  404}, {  616,  407}, {  617,  406},
+{  623,  412}, {  626,  413}, {  629,  415}, {  643,  425}, {  648,  430}, {  650,  433}, {  651,  434},
+{  658,  439}, {  940,  902}, {  941,  904}, {  942,  905}, {  943,  906}, {  945,  913}, {  946,  914},
+{  947,  915}, {  948,  916}, {  949,  917}, {  950,  918}, {  951,  919}, {  952,  920}, {  953,  921},
+{  954,  922}, {  955,  923}, {  956,  924}, {  957,  925}, {  958,  926}, {  959,  927}, {  960,  928},
+{  961,  929}, {  962,  931}, {  963,  931}, {  964,  932}, {  965,  933}, {  966,  934}, {  967,  935},
+{  968,  936}, {  969,  937}, {  970,  938}, {  971,  939}, {  972,  908}, {  973,  910}, {  974,  911},
+{  995,  994}, {  997,  996}, {  999,  998}, { 1001, 1000}, { 1003, 1002}, { 1005, 1004}, { 1007, 1006},
+{ 1072, 1040}, { 1073, 1041}, { 1074, 1042}, { 1075, 1043}, { 1076, 1044}, { 1077, 1045}, { 1078, 1046},
+{ 1079, 1047}, { 1080, 1048}, { 1081, 1049}, { 1082, 1050}, { 1083, 1051}, { 1084, 1052}, { 1085, 1053},
+{ 1086, 1054}, { 1087, 1055}, { 1088, 1056}, { 1089, 1057}, { 1090, 1058}, { 1091, 1059}, { 1092, 1060},
+{ 1093, 1061}, { 1094, 1062}, { 1095, 1063}, { 1096, 1064}, { 1097, 1065}, { 1098, 1066}, { 1099, 1067},
+{ 1100, 1068}, { 1101, 1069}, { 1102, 1070}, { 1103, 1071}, { 1104, 1024}, { 1105, 1025}, { 1106, 1026}, { 1107, 1027},
+{ 1108, 1028}, { 1109, 1029}, { 1110, 1030}, { 1111, 1031}, { 1112, 1032}, { 1113, 1033}, { 1114, 1034},
+{ 1115, 1035}, { 1116, 1036}, { 1117, 1037}, { 1118, 1038}, { 1119, 1039}, { 1121, 1120}, { 1123, 1122}, { 1125, 1124},
+{ 1127, 1126}, { 1129, 1128}, { 1131, 1130}, { 1133, 1132}, { 1135, 1134}, { 1137, 1136}, { 1139, 1138},
+{ 1141, 1140}, { 1143, 1142}, { 1145, 1144}, { 1147, 1146}, { 1149, 1148}, { 1151, 1150}, { 1153, 1152},
+{ 1169, 1168}, { 1171, 1170}, { 1173, 1172}, { 1175, 1174}, { 1177, 1176}, { 1179, 1178}, { 1181, 1180},
+{ 1183, 1182}, { 1185, 1184}, { 1187, 1186}, { 1189, 1188}, { 1191, 1190}, { 1193, 1192}, { 1195, 1194},
+{ 1197, 1196}, { 1199, 1198}, { 1201, 1200}, { 1203, 1202}, { 1205, 1204}, { 1207, 1206}, { 1209, 1208},
+{ 1211, 1210}, { 1213, 1212}, { 1215, 1214}, { 1218, 1217}, { 1220, 1219}, { 1224, 1223}, { 1228, 1227},
+{ 1233, 1232}, { 1235, 1234}, { 1237, 1236}, { 1239, 1238}, { 1241, 1240}, { 1243, 1242}, { 1245, 1244},
+{ 1247, 1246}, { 1249, 1248}, { 1251, 1250}, { 1253, 1252}, { 1255, 1254}, { 1257, 1256}, { 1259, 1258},
+{ 1263, 1262}, { 1265, 1264}, { 1267, 1266}, { 1269, 1268}, { 1273, 1272}, { 1377, 1329}, { 1378, 1330},
+{ 1379, 1331}, { 1380, 1332}, { 1381, 1333}, { 1382, 1334}, { 1383, 1335}, { 1384, 1336}, { 1385, 1337},
+{ 1386, 1338}, { 1387, 1339}, { 1388, 1340}, { 1389, 1341}, { 1390, 1342}, { 1391, 1343}, { 1392, 1344},
+{ 1393, 1345}, { 1394, 1346}, { 1395, 1347}, { 1396, 1348}, { 1397, 1349}, { 1398, 1350}, { 1399, 1351},
+{ 1400, 1352}, { 1401, 1353}, { 1402, 1354}, { 1403, 1355}, { 1404, 1356}, { 1405, 1357}, { 1406, 1358},
+{ 1407, 1359}, { 1408, 1360}, { 1409, 1361}, { 1410, 1362}, { 1411, 1363}, { 1412, 1364}, { 1413, 1365},
+{ 1414, 1366}, { 7681, 7680}, { 7683, 7682}, { 7685, 7684}, { 7687, 7686}, { 7689, 7688}, { 7691, 7690},
+{ 7693, 7692}, { 7695, 7694}, { 7697, 7696}, { 7699, 7698}, { 7701, 7700}, { 7703, 7702}, { 7705, 7704},
+{ 7707, 7706}, { 7709, 7708}, { 7711, 7710}, { 7713, 7712}, { 7715, 7714}, { 7717, 7716}, { 7719, 7718},
+{ 7721, 7720}, { 7723, 7722}, { 7725, 7724}, { 7727, 7726}, { 7729, 7728}, { 7731, 7730}, { 7733, 7732},
+{ 7735, 7734}, { 7737, 7736}, { 7739, 7738}, { 7741, 7740}, { 7743, 7742}, { 7745, 7744}, { 7747, 7746},
+{ 7749, 7748}, { 7751, 7750}, { 7753, 7752}, { 7755, 7754}, { 7757, 7756}, { 7759, 7758}, { 7761, 7760},
+{ 7763, 7762}, { 7765, 7764}, { 7767, 7766}, { 7769, 7768}, { 7771, 7770}, { 7773, 7772}, { 7775, 7774},
+{ 7777, 7776}, { 7779, 7778}, { 7781, 7780}, { 7783, 7782}, { 7785, 7784}, { 7787, 7786}, { 7789, 7788},
+{ 7791, 7790}, { 7793, 7792}, { 7795, 7794}, { 7797, 7796}, { 7799, 7798}, { 7801, 7800}, { 7803, 7802},
+{ 7805, 7804}, { 7807, 7806}, { 7809, 7808}, { 7811, 7810}, { 7813, 7812}, { 7815, 7814}, { 7817, 7816},
+{ 7819, 7818}, { 7821, 7820}, { 7823, 7822}, { 7825, 7824}, { 7827, 7826}, { 7829, 7828}, { 7841, 7840},
+{ 7843, 7842}, { 7845, 7844}, { 7847, 7846}, { 7849, 7848}, { 7851, 7850}, { 7853, 7852}, { 7855, 7854},
+{ 7857, 7856}, { 7859, 7858}, { 7861, 7860}, { 7863, 7862}, { 7865, 7864}, { 7867, 7866}, { 7869, 7868},
+{ 7871, 7870}, { 7873, 7872}, { 7875, 7874}, { 7877, 7876}, { 7879, 7878}, { 7881, 7880}, { 7883, 7882},
+{ 7885, 7884}, { 7887, 7886}, { 7889, 7888}, { 7891, 7890}, { 7893, 7892}, { 7895, 7894}, { 7897, 7896},
+{ 7899, 7898}, { 7901, 7900}, { 7903, 7902}, { 7905, 7904}, { 7907, 7906}, { 7909, 7908}, { 7911, 7910},
+{ 7913, 7912}, { 7915, 7914}, { 7917, 7916}, { 7919, 7918}, { 7921, 7920}, { 7923, 7922}, { 7925, 7924},
+{ 7927, 7926}, { 7929, 7928}, { 7936, 7944}, { 7937, 7945}, { 7938, 7946}, { 7939, 7947}, { 7940, 7948},
+{ 7941, 7949}, { 7942, 7950}, { 7943, 7951}, { 7952, 7960}, { 7953, 7961}, { 7954, 7962}, { 7955, 7963},
+{ 7956, 7964}, { 7957, 7965}, { 7968, 7976}, { 7969, 7977}, { 7970, 7978}, { 7971, 7979}, { 7972, 7980},
+{ 7973, 7981}, { 7974, 7982}, { 7975, 7983}, { 7984, 7992}, { 7985, 7993}, { 7986, 7994}, { 7987, 7995},
+{ 7988, 7996}, { 7989, 7997}, { 7990, 7998}, { 7991, 7999}, { 8000, 8008}, { 8001, 8009}, { 8002, 8010},
+{ 8003, 8011}, { 8004, 8012}, { 8005, 8013}, { 8017, 8025}, { 8019, 8027}, { 8021, 8029}, { 8023, 8031},
+{ 8032, 8040}, { 8033, 8041}, { 8034, 8042}, { 8035, 8043}, { 8036, 8044}, { 8037, 8045}, { 8038, 8046},
+{ 8039, 8047}, { 8048, 8122}, { 8049, 8123}, { 8050, 8136}, { 8051, 8137}, { 8052, 8138}, { 8053, 8139},
+{ 8054, 8154}, { 8055, 8155}, { 8056, 8184}, { 8057, 8185}, { 8058, 8170}, { 8059, 8171}, { 8060, 8186},
+{ 8061, 8187}, { 8112, 8120}, { 8113, 8121}, { 8144, 8152}, { 8145, 8153}, { 8160, 8168}, { 8161, 8169},
+{ 8165, 8172}, { 8560, 8544}, { 8561, 8545}, { 8562, 8546}, { 8563, 8547}, { 8564, 8548}, { 8565, 8549},
+{ 8566, 8550}, { 8567, 8551}, { 8568, 8552}, { 8569, 8553}, { 8570, 8554}, { 8571, 8555}, { 8572, 8556},
+{ 8573, 8557}, { 8574, 8558}, { 8575, 8559}, { 9424, 9398}, { 9425, 9399}, { 9426, 9400}, { 9427, 9401},
+{ 9428, 9402}, { 9429, 9403}, { 9430, 9404}, { 9431, 9405}, { 9432, 9406}, { 9433, 9407}, { 9434, 9408},
+{ 9435, 9409}, { 9436, 9410}, { 9437, 9411}, { 9438, 9412}, { 9439, 9413}, { 9440, 9414}, { 9441, 9415},
+{ 9442, 9416}, { 9443, 9417}, { 9444, 9418}, { 9445, 9419}, { 9446, 9420}, { 9447, 9421}, { 9448, 9422},
+{ 9449, 9423}, {65345,65313}, {65346,65314}, {65347,65315}, {65348,65316}, {65349,65317}, {65350,65318},
+{65351,65319}, {65352,65320}, {65353,65321}, {65354,65322}, {65355,65323}, {65356,65324}, {65357,65325},
+{65358,65326}, {65359,65327}, {65360,65328}, {65361,65329}, {65362,65330}, {65363,65331}, {65364,65332},
+{65365,65333}, {65366,65334}, {65367,65335}, {65368,65336}, {65369,65337}, {65370,65338}, {65535,    0}};
+
+static const GUnicodePairType UnicodeToLowerTable[] = {
+{   65,   97}, {   66,   98}, {   67,   99}, {   68,  100}, {   69,  101}, {   70,  102}, {   71,  103},
+{   72,  104}, {   73,  105}, {   74,  106}, {   75,  107}, {   76,  108}, {   77,  109}, {   78,  110},
+{   79,  111}, {   80,  112}, {   81,  113}, {   82,  114}, {   83,  115}, {   84,  116}, {   85,  117},
+{   86,  118}, {   87,  119}, {   88,  120}, {   89,  121}, {   90,  122}, {  192,  224}, {  193,  225},
+{  194,  226}, {  195,  227}, {  196,  228}, {  197,  229}, {  198,  230}, {  199,  231}, {  200,  232},
+{  201,  233}, {  202,  234}, {  203,  235}, {  204,  236}, {  205,  237}, {  206,  238}, {  207,  239},
+{  208,  240}, {  209,  241}, {  210,  242}, {  211,  243}, {  212,  244}, {  213,  245}, {  214,  246},
+{  216,  248}, {  217,  249}, {  218,  250}, {  219,  251}, {  220,  252}, {  221,  253}, {  222,  254},
+{  256,  257}, {  258,  259}, {  260,  261}, {  262,  263}, {  264,  265}, {  266,  267}, {  268,  269},
+{  270,  271}, {  272,  273}, {  274,  275}, {  276,  277}, {  278,  279}, {  280,  281}, {  282,  283},
+{  284,  285}, {  286,  287}, {  288,  289}, {  290,  291}, {  292,  293}, {  294,  295}, {  296,  297},
+{  298,  299}, {  300,  301}, {  302,  303}, {  304,  105}, {  306,  307}, {  308,  309}, {  310,  311}, {  313,  314},
+{  315,  316}, {  317,  318}, {  319,  320}, {  321,  322}, {  323,  324}, {  325,  326}, {  327,  328},
+{  330,  331}, {  332,  333}, {  334,  335}, {  336,  337}, {  338,  339}, {  340,  341}, {  342,  343},
+{  344,  345}, {  346,  347}, {  348,  349}, {  350,  351}, {  352,  353}, {  354,  355}, {  356,  357},
+{  358,  359}, {  360,  361}, {  362,  363}, {  364,  365}, {  366,  367}, {  368,  369}, {  370,  371},
+{  372,  373}, {  374,  375}, {  376,  255}, {  377,  378}, {  379,  380}, {  381,  382}, {  385,  595},
+{  386,  387}, {  388,  389}, {  390,  596}, {  391,  392}, {  393,  598}, {  394,  599}, {  395,  396},
+{  398,  477}, {  399,  601}, {  400,  603}, {  401,  402}, {  403,  608}, {  404,  611}, {  406,  617},
+{  407,  616}, {  408,  409}, {  412,  623}, {  413,  626}, {  415,  629}, {  416,  417}, {  418,  419},
+{  420,  421}, {  423,  424}, {  425,  643}, {  428,  429}, {  430,  648}, {  431,  432}, {  433,  650},
+{  434,  651}, {  435,  436}, {  437,  438}, {  439,  658}, {  440,  441}, {  444,  445}, {  452,  454},
+{  455,  457}, {  458,  460}, {  461,  462}, {  463,  464}, {  465,  466}, {  467,  468}, {  469,  470},
+{  471,  472}, {  473,  474}, {  475,  476}, {  478,  479}, {  480,  481}, {  482,  483}, {  484,  485},
+{  486,  487}, {  488,  489}, {  490,  491}, {  492,  493}, {  494,  495}, {  497,  499}, {  500,  501},
+{  506,  507}, {  508,  509}, {  510,  511}, {  512,  513}, {  514,  515}, {  516,  517}, {  518,  519},
+{  520,  521}, {  522,  523}, {  524,  525}, {  526,  527}, {  528,  529}, {  530,  531}, {  532,  533},
+{  534,  535}, {  902,  940}, {  904,  941}, {  905,  942}, {  906,  943}, {  908,  972}, {  910,  973},
+{  911,  974}, {  913,  945}, {  914,  946}, {  915,  947}, {  916,  948}, {  917,  949}, {  918,  950},
+{  919,  951}, {  920,  952}, {  921,  953}, {  922,  954}, {  923,  955}, {  924,  956}, {  925,  957},
+{  926,  958}, {  927,  959}, {  928,  960}, {  929,  961}, {  931,  963}, {  932,  964}, {  933,  965},
+{  934,  966}, {  935,  967}, {  936,  968}, {  937,  969}, {  938,  970}, {  939,  971}, {  994,  995},
+{  996,  997}, {  998,  999}, { 1000, 1001}, { 1002, 1003}, { 1004, 1005}, { 1006, 1007}, { 1024, 1104}, { 1025, 1105},
+{ 1026, 1106}, { 1027, 1107}, { 1028, 1108}, { 1029, 1109}, { 1030, 1110}, { 1031, 1111}, { 1032, 1112},
+{ 1033, 1113}, { 1034, 1114}, { 1035, 1115}, { 1036, 1116}, { 1037, 1117}, { 1038, 1118}, { 1039, 1119}, { 1040, 1072},
+{ 1041, 1073}, { 1042, 1074}, { 1043, 1075}, { 1044, 1076}, { 1045, 1077}, { 1046, 1078}, { 1047, 1079},
+{ 1048, 1080}, { 1049, 1081}, { 1050, 1082}, { 1051, 1083}, { 1052, 1084}, { 1053, 1085}, { 1054, 1086},
+{ 1055, 1087}, { 1056, 1088}, { 1057, 1089}, { 1058, 1090}, { 1059, 1091}, { 1060, 1092}, { 1061, 1093},
+{ 1062, 1094}, { 1063, 1095}, { 1064, 1096}, { 1065, 1097}, { 1066, 1098}, { 1067, 1099}, { 1068, 1100},
+{ 1069, 1101}, { 1070, 1102}, { 1071, 1103}, { 1120, 1121}, { 1122, 1123}, { 1124, 1125}, { 1126, 1127},
+{ 1128, 1129}, { 1130, 1131}, { 1132, 1133}, { 1134, 1135}, { 1136, 1137}, { 1138, 1139}, { 1140, 1141},
+{ 1142, 1143}, { 1144, 1145}, { 1146, 1147}, { 1148, 1149}, { 1150, 1151}, { 1152, 1153}, { 1168, 1169},
+{ 1170, 1171}, { 1172, 1173}, { 1174, 1175}, { 1176, 1177}, { 1178, 1179}, { 1180, 1181}, { 1182, 1183},
+{ 1184, 1185}, { 1186, 1187}, { 1188, 1189}, { 1190, 1191}, { 1192, 1193}, { 1194, 1195}, { 1196, 1197},
+{ 1198, 1199}, { 1200, 1201}, { 1202, 1203}, { 1204, 1205}, { 1206, 1207}, { 1208, 1209}, { 1210, 1211},
+{ 1212, 1213}, { 1214, 1215}, { 1217, 1218}, { 1219, 1220}, { 1223, 1224}, { 1227, 1228}, { 1232, 1233},
+{ 1234, 1235}, { 1236, 1237}, { 1238, 1239}, { 1240, 1241}, { 1242, 1243}, { 1244, 1245}, { 1246, 1247},
+{ 1248, 1249}, { 1250, 1251}, { 1252, 1253}, { 1254, 1255}, { 1256, 1257}, { 1258, 1259}, { 1262, 1263},
+{ 1264, 1265}, { 1266, 1267}, { 1268, 1269}, { 1272, 1273}, { 1329, 1377}, { 1330, 1378}, { 1331, 1379},
+{ 1332, 1380}, { 1333, 1381}, { 1334, 1382}, { 1335, 1383}, { 1336, 1384}, { 1337, 1385}, { 1338, 1386},
+{ 1339, 1387}, { 1340, 1388}, { 1341, 1389}, { 1342, 1390}, { 1343, 1391}, { 1344, 1392}, { 1345, 1393},
+{ 1346, 1394}, { 1347, 1395}, { 1348, 1396}, { 1349, 1397}, { 1350, 1398}, { 1351, 1399}, { 1352, 1400},
+{ 1353, 1401}, { 1354, 1402}, { 1355, 1403}, { 1356, 1404}, { 1357, 1405}, { 1358, 1406}, { 1359, 1407},
+{ 1360, 1408}, { 1361, 1409}, { 1362, 1410}, { 1363, 1411}, { 1364, 1412}, { 1365, 1413}, { 1366, 1414},
+{ 4256, 4304}, { 4257, 4305}, { 4258, 4306}, { 4259, 4307}, { 4260, 4308}, { 4261, 4309}, { 4262, 4310},
+{ 4263, 4311}, { 4264, 4312}, { 4265, 4313}, { 4266, 4314}, { 4267, 4315}, { 4268, 4316}, { 4269, 4317},
+{ 4270, 4318}, { 4271, 4319}, { 4272, 4320}, { 4273, 4321}, { 4274, 4322}, { 4275, 4323}, { 4276, 4324},
+{ 4277, 4325}, { 4278, 4326}, { 4279, 4327}, { 4280, 4328}, { 4281, 4329}, { 4282, 4330}, { 4283, 4331},
+{ 4284, 4332}, { 4285, 4333}, { 4286, 4334}, { 4287, 4335}, { 4288, 4336}, { 4289, 4337}, { 4290, 4338},
+{ 4291, 4339}, { 4292, 4340}, { 4293, 4341}, { 7680, 7681}, { 7682, 7683}, { 7684, 7685}, { 7686, 7687},
+{ 7688, 7689}, { 7690, 7691}, { 7692, 7693}, { 7694, 7695}, { 7696, 7697}, { 7698, 7699}, { 7700, 7701},
+{ 7702, 7703}, { 7704, 7705}, { 7706, 7707}, { 7708, 7709}, { 7710, 7711}, { 7712, 7713}, { 7714, 7715},
+{ 7716, 7717}, { 7718, 7719}, { 7720, 7721}, { 7722, 7723}, { 7724, 7725}, { 7726, 7727}, { 7728, 7729},
+{ 7730, 7731}, { 7732, 7733}, { 7734, 7735}, { 7736, 7737}, { 7738, 7739}, { 7740, 7741}, { 7742, 7743},
+{ 7744, 7745}, { 7746, 7747}, { 7748, 7749}, { 7750, 7751}, { 7752, 7753}, { 7754, 7755}, { 7756, 7757},
+{ 7758, 7759}, { 7760, 7761}, { 7762, 7763}, { 7764, 7765}, { 7766, 7767}, { 7768, 7769}, { 7770, 7771},
+{ 7772, 7773}, { 7774, 7775}, { 7776, 7777}, { 7778, 7779}, { 7780, 7781}, { 7782, 7783}, { 7784, 7785},
+{ 7786, 7787}, { 7788, 7789}, { 7790, 7791}, { 7792, 7793}, { 7794, 7795}, { 7796, 7797}, { 7798, 7799},
+{ 7800, 7801}, { 7802, 7803}, { 7804, 7805}, { 7806, 7807}, { 7808, 7809}, { 7810, 7811}, { 7812, 7813},
+{ 7814, 7815}, { 7816, 7817}, { 7818, 7819}, { 7820, 7821}, { 7822, 7823}, { 7824, 7825}, { 7826, 7827},
+{ 7828, 7829}, { 7840, 7841}, { 7842, 7843}, { 7844, 7845}, { 7846, 7847}, { 7848, 7849}, { 7850, 7851},
+{ 7852, 7853}, { 7854, 7855}, { 7856, 7857}, { 7858, 7859}, { 7860, 7861}, { 7862, 7863}, { 7864, 7865},
+{ 7866, 7867}, { 7868, 7869}, { 7870, 7871}, { 7872, 7873}, { 7874, 7875}, { 7876, 7877}, { 7878, 7879},
+{ 7880, 7881}, { 7882, 7883}, { 7884, 7885}, { 7886, 7887}, { 7888, 7889}, { 7890, 7891}, { 7892, 7893},
+{ 7894, 7895}, { 7896, 7897}, { 7898, 7899}, { 7900, 7901}, { 7902, 7903}, { 7904, 7905}, { 7906, 7907},
+{ 7908, 7909}, { 7910, 7911}, { 7912, 7913}, { 7914, 7915}, { 7916, 7917}, { 7918, 7919}, { 7920, 7921},
+{ 7922, 7923}, { 7924, 7925}, { 7926, 7927}, { 7928, 7929}, { 7944, 7936}, { 7945, 7937}, { 7946, 7938},
+{ 7947, 7939}, { 7948, 7940}, { 7949, 7941}, { 7950, 7942}, { 7951, 7943}, { 7960, 7952}, { 7961, 7953},
+{ 7962, 7954}, { 7963, 7955}, { 7964, 7956}, { 7965, 7957}, { 7976, 7968}, { 7977, 7969}, { 7978, 7970},
+{ 7979, 7971}, { 7980, 7972}, { 7981, 7973}, { 7982, 7974}, { 7983, 7975}, { 7992, 7984}, { 7993, 7985},
+{ 7994, 7986}, { 7995, 7987}, { 7996, 7988}, { 7997, 7989}, { 7998, 7990}, { 7999, 7991}, { 8008, 8000},
+{ 8009, 8001}, { 8010, 8002}, { 8011, 8003}, { 8012, 8004}, { 8013, 8005}, { 8025, 8017}, { 8027, 8019},
+{ 8029, 8021}, { 8031, 8023}, { 8040, 8032}, { 8041, 8033}, { 8042, 8034}, { 8043, 8035}, { 8044, 8036},
+{ 8045, 8037}, { 8046, 8038}, { 8047, 8039}, { 8120, 8112}, { 8121, 8113}, { 8122, 8048}, { 8123, 8049},
+{ 8136, 8050}, { 8137, 8051}, { 8138, 8052}, { 8139, 8053}, { 8152, 8144}, { 8153, 8145}, { 8154, 8054},
+{ 8155, 8055}, { 8168, 8160}, { 8169, 8161}, { 8170, 8058}, { 8171, 8059}, { 8172, 8165}, { 8184, 8056},
+{ 8185, 8057}, { 8186, 8060}, { 8187, 8061}, { 8544, 8560}, { 8545, 8561}, { 8546, 8562}, { 8547, 8563},
+{ 8548, 8564}, { 8549, 8565}, { 8550, 8566}, { 8551, 8567}, { 8552, 8568}, { 8553, 8569}, { 8554, 8570},
+{ 8555, 8571}, { 8556, 8572}, { 8557, 8573}, { 8558, 8574}, { 8559, 8575}, { 9398, 9424}, { 9399, 9425},
+{ 9400, 9426}, { 9401, 9427}, { 9402, 9428}, { 9403, 9429}, { 9404, 9430}, { 9405, 9431}, { 9406, 9432},
+{ 9407, 9433}, { 9408, 9434}, { 9409, 9435}, { 9410, 9436}, { 9411, 9437}, { 9412, 9438}, { 9413, 9439},
+{ 9414, 9440}, { 9415, 9441}, { 9416, 9442}, { 9417, 9443}, { 9418, 9444}, { 9419, 9445}, { 9420, 9446},
+{ 9421, 9447}, { 9422, 9448}, { 9423, 9449}, {65313,65345}, {65314,65346}, {65315,65347}, {65316,65348},
+{65317,65349}, {65318,65350}, {65319,65351}, {65320,65352}, {65321,65353}, {65322,65354}, {65323,65355},
+{65324,65356}, {65325,65357}, {65326,65358}, {65327,65359}, {65328,65360}, {65329,65361}, {65330,65362},
+{65331,65363}, {65332,65364}, {65333,65365}, {65334,65366}, {65335,65367}, {65336,65368}, {65337,65369},
+{65338,65370}, {65535,    0}};
+
+int OVR_CDECL OVR_towupper(wchar_t charCode)
+{
+    // Don't use UnicodeUpperBits! It differs from UnicodeToUpperBits.
+    if (UnicodeCharIs(UnicodeToUpperBits, charCode))
+    {
+        // To protect from memory overrun in case the character is not found
+        // we use one extra fake element in the table {65536, 0}.
+        UPInt idx = Alg::LowerBoundSliced(
+            UnicodeToUpperTable,
+            0,
+            sizeof(UnicodeToUpperTable) / sizeof(UnicodeToUpperTable[0]) - 1,
+            (UInt16)charCode,
+            CmpUnicodeKey);
+        return UnicodeToUpperTable[idx].Value;
+    }
+    return charCode;
+}
+
+int OVR_CDECL OVR_towlower(wchar_t charCode)
+{
+    // Don't use UnicodeLowerBits! It differs from UnicodeToLowerBits.
+    if (UnicodeCharIs(UnicodeToLowerBits, charCode))
+    {
+        // To protect from memory overrun in case the character is not found
+        // we use one extra fake element in the table {65536, 0}.
+        UPInt idx = Alg::LowerBoundSliced(
+            UnicodeToLowerTable,
+            0,
+            sizeof(UnicodeToLowerTable) / sizeof(UnicodeToLowerTable[0]) - 1,
+            (UInt16)charCode,
+            CmpUnicodeKey);
+        return UnicodeToLowerTable[idx].Value;
+    }
+    return charCode;
+}
+
+#endif //OVR_NO_WCTYPE
+
+} // OVR
diff --git a/LibOVR/Src/Kernel/OVR_Std.h b/LibOVR/Src/Kernel/OVR_Std.h
new file mode 100644
index 0000000..c11f853
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Std.h
@@ -0,0 +1,514 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Std.h
+Content     :   Standard C function interface
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Std_h
+#define OVR_Std_h
+
+#include "OVR_Types.h"
+#include <stdarg.h> // for va_list args
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#if !defined(OVR_OS_WINCE) && defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
+#define OVR_MSVC_SAFESTRING
+#include <errno.h>
+#endif
+
+// Wide-char funcs
+#include <wchar.h>
+#include <wctype.h>
+
+namespace OVR {
+
+#if defined(OVR_OS_WIN32)
+inline char* OVR_CDECL OVR_itoa(int val, char *dest, UPInt destsize, int radix)
+{
+#if defined(OVR_MSVC_SAFESTRING)
+    _itoa_s(val, dest, destsize, radix);
+    return dest;
+#else
+    OVR_UNUSED(destsize);
+    return itoa(val, dest, radix);
+#endif
+}
+#else // OVR_OS_WIN32
+inline char* OVR_itoa(int val, char* dest, unsigned int len, int radix)
+{
+    if (val == 0)
+    {
+        if (len > 1)
+        {
+            dest[0] = '0';
+            dest[1] = '\0';  
+        }
+        return dest;
+    }
+
+    int cur = val;
+    unsigned int i    = 0; 
+    unsigned int sign = 0;
+
+    if (val < 0)
+    {
+        val = -val;
+        sign = 1;
+    }
+
+    while ((val != 0) && (i < (len - 1 - sign)))        
+    {
+        cur    = val % radix;
+        val   /= radix;
+
+        if (radix == 16)
+        {
+            switch(cur)
+            {
+            case 10:
+                dest[i] = 'a';
+                break;
+            case 11:
+                dest[i] = 'b';
+                break;
+            case 12:
+                dest[i] = 'c';
+                break;
+            case 13:
+                dest[i] = 'd';
+                break;
+            case 14:
+                dest[i] = 'e';
+                break;
+            case 15:
+                dest[i] = 'f';
+                break;
+            default:
+                dest[i] = (char)('0' + cur);
+                break;
+            }
+        } 
+        else
+        {
+            dest[i] = (char)('0' + cur);
+        }
+        ++i;
+    }
+
+    if (sign)
+    {
+        dest[i++] = '-';
+    }
+
+    for (unsigned int j = 0; j < i / 2; ++j)
+    {
+        char tmp        = dest[j];
+        dest[j]         = dest[i - 1 - j];
+        dest[i - 1 - j] = tmp;
+    }
+    dest[i] = '\0';
+
+    return dest;
+}
+
+#endif
+
+
+// String functions
+
+inline UPInt OVR_CDECL OVR_strlen(const char* str)
+{
+    return strlen(str);
+}
+
+inline char* OVR_CDECL OVR_strcpy(char* dest, UPInt destsize, const char* src)
+{
+#if defined(OVR_MSVC_SAFESTRING)
+    strcpy_s(dest, destsize, src);
+    return dest;
+#else
+    OVR_UNUSED(destsize);
+    return strcpy(dest, src);
+#endif
+}
+
+inline char* OVR_CDECL OVR_strncpy(char* dest, UPInt destsize, const char* src, UPInt count)
+{
+#if defined(OVR_MSVC_SAFESTRING)
+    strncpy_s(dest, destsize, src, count);
+    return dest;
+#else
+    OVR_UNUSED(destsize);
+    return strncpy(dest, src, count);
+#endif
+}
+
+inline char * OVR_CDECL OVR_strcat(char* dest, UPInt destsize, const char* src)
+{
+#if defined(OVR_MSVC_SAFESTRING)
+    strcat_s(dest, destsize, src);
+    return dest;
+#else
+    OVR_UNUSED(destsize);
+    return strcat(dest, src);
+#endif
+}
+
+inline int OVR_CDECL OVR_strcmp(const char* dest, const char* src)
+{
+    return strcmp(dest, src);
+}
+
+inline const char* OVR_CDECL OVR_strchr(const char* str, char c)
+{
+    return strchr(str, c);
+}
+
+inline char* OVR_CDECL OVR_strchr(char* str, char c)
+{
+    return strchr(str, c);
+}
+
+inline const char* OVR_strrchr(const char* str, char c)
+{
+    UPInt len = OVR_strlen(str);
+    for (UPInt i=len; i>0; i--)     
+        if (str[i]==c) 
+            return str+i;
+    return 0;
+}
+
+inline const UByte* OVR_CDECL OVR_memrchr(const UByte* str, UPInt size, UByte c)
+{
+    for (SPInt i = (SPInt)size - 1; i >= 0; i--)     
+    {
+        if (str[i] == c) 
+            return str + i;
+    }
+    return 0;
+}
+
+inline char* OVR_CDECL OVR_strrchr(char* str, char c)
+{
+    UPInt len = OVR_strlen(str);
+    for (UPInt i=len; i>0; i--)     
+        if (str[i]==c) 
+            return str+i;
+    return 0;
+}
+
+
+double OVR_CDECL OVR_strtod(const char* string, char** tailptr);
+
+inline long OVR_CDECL OVR_strtol(const char* string, char** tailptr, int radix)
+{
+    return strtol(string, tailptr, radix);
+}
+
+inline long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix)
+{
+    return strtoul(string, tailptr, radix);
+}
+
+inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, UPInt size)
+{
+    return strncmp(ws1, ws2, size);
+}
+
+inline UInt64 OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base)
+{
+#if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE)
+    return _strtoui64(nptr, endptr, base);
+#else
+    return strtoull(nptr, endptr, base);
+#endif
+}
+
+inline SInt64 OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base)
+{
+#if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE)
+    return _strtoi64(nptr, endptr, base);
+#else
+    return strtoll(nptr, endptr, base);
+#endif
+}
+
+
+inline SInt64 OVR_CDECL OVR_atoq(const char* string)
+{
+#if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE)
+    return _atoi64(string);
+#else
+    return atoll(string);
+#endif
+}
+
+inline UInt64 OVR_CDECL OVR_atouq(const char* string)
+{
+  return OVR_strtouq(string, NULL, 10);
+}
+
+
+// Implemented in GStd.cpp in platform-specific manner.
+int OVR_CDECL OVR_stricmp(const char* dest, const char* src);
+int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, UPInt count);
+
+inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* format, ...)
+{
+    va_list argList;
+    va_start(argList,format);
+    UPInt ret;
+#if defined(OVR_CC_MSVC)
+    #if defined(OVR_MSVC_SAFESTRING)
+        ret = _vsnprintf_s(dest, destsize, _TRUNCATE, format, argList);
+        OVR_ASSERT(ret != -1);
+    #else
+        OVR_UNUSED(destsize);
+        ret = _vsnprintf(dest, destsize - 1, format, argList); // -1 for space for the null character
+        OVR_ASSERT(ret != -1);
+        dest[destsize-1] = 0;
+    #endif
+#else
+    OVR_UNUSED(destsize);
+    ret = vsprintf(dest, format, argList);
+    OVR_ASSERT(ret < destsize);
+#endif
+    va_end(argList);
+    return ret;
+}
+
+inline UPInt OVR_CDECL OVR_vsprintf(char *dest, UPInt destsize, const char * format, va_list argList)
+{
+    UPInt ret;
+#if defined(OVR_CC_MSVC)
+    #if defined(OVR_MSVC_SAFESTRING)
+        dest[0] = '\0';
+        int rv = vsnprintf_s(dest, destsize, _TRUNCATE, format, argList);
+        if (rv == -1)
+        {
+            dest[destsize - 1] = '\0';
+            ret = destsize - 1;
+        }
+        else
+            ret = (UPInt)rv;
+    #else
+        OVR_UNUSED(destsize);
+        int rv = _vsnprintf(dest, destsize - 1, format, argList);
+        OVR_ASSERT(rv != -1);
+        ret = (UPInt)rv;
+        dest[destsize-1] = 0;
+    #endif
+#else
+    OVR_UNUSED(destsize);
+    ret = (UPInt)vsprintf(dest, format, argList);
+    OVR_ASSERT(ret < destsize);
+#endif
+    return ret;
+}
+
+// Returns the number of characters in the formatted string.
+inline UPInt OVR_CDECL OVR_vscprintf(const char * format, va_list argList)
+{
+    UPInt ret;
+#if defined(OVR_CC_MSVC)
+    ret = (UPInt) _vscprintf(format, argList);
+#else    
+    ret = (UPInt) vsnprintf(NULL, 0, format, argList);
+#endif
+    return ret;       
+}
+
+
+wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src);
+wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count);
+wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src);
+UPInt    OVR_CDECL OVR_wcslen(const wchar_t* str);
+int      OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b);
+int      OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b);
+
+inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b)
+{
+#if defined(OVR_OS_WIN32)
+#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
+    return ::_wcsicoll(a, b);
+#else
+    return ::wcsicoll(a, b);
+#endif
+#else
+    // not supported, use regular wcsicmp
+    return OVR_wcsicmp(a, b);
+#endif
+}
+
+inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b)
+{
+#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX)
+    return wcscoll(a, b);
+#else
+    // not supported, use regular wcscmp
+    return OVR_wcscmp(a, b);
+#endif
+}
+
+#ifndef OVR_NO_WCTYPE
+
+inline int OVR_CDECL UnicodeCharIs(const UInt16* table, wchar_t charCode)
+{
+    unsigned offset = table[charCode >> 8];
+    if (offset == 0) return 0;
+    if (offset == 1) return 1;
+    return (table[offset + ((charCode >> 4) & 15)] & (1 << (charCode & 15))) != 0;
+}
+
+extern const UInt16 UnicodeAlnumBits[];
+extern const UInt16 UnicodeAlphaBits[];
+extern const UInt16 UnicodeDigitBits[];
+extern const UInt16 UnicodeSpaceBits[];
+extern const UInt16 UnicodeXDigitBits[];
+
+// Uncomment if necessary
+//extern const UInt16 UnicodeCntrlBits[];
+//extern const UInt16 UnicodeGraphBits[];
+//extern const UInt16 UnicodeLowerBits[];
+//extern const UInt16 UnicodePrintBits[];
+//extern const UInt16 UnicodePunctBits[];
+//extern const UInt16 UnicodeUpperBits[];
+
+inline int OVR_CDECL OVR_iswalnum (wchar_t charCode) { return UnicodeCharIs(UnicodeAlnumBits,  charCode); }
+inline int OVR_CDECL OVR_iswalpha (wchar_t charCode) { return UnicodeCharIs(UnicodeAlphaBits,  charCode); }
+inline int OVR_CDECL OVR_iswdigit (wchar_t charCode) { return UnicodeCharIs(UnicodeDigitBits,  charCode); }
+inline int OVR_CDECL OVR_iswspace (wchar_t charCode) { return UnicodeCharIs(UnicodeSpaceBits,  charCode); }
+inline int OVR_CDECL OVR_iswxdigit(wchar_t charCode) { return UnicodeCharIs(UnicodeXDigitBits, charCode); }
+
+// Uncomment if necessary
+//inline int OVR_CDECL OVR_iswcntrl (wchar_t charCode) { return UnicodeCharIs(UnicodeCntrlBits,  charCode); }
+//inline int OVR_CDECL OVR_iswgraph (wchar_t charCode) { return UnicodeCharIs(UnicodeGraphBits,  charCode); }
+//inline int OVR_CDECL OVR_iswlower (wchar_t charCode) { return UnicodeCharIs(UnicodeLowerBits,  charCode); }
+//inline int OVR_CDECL OVR_iswprint (wchar_t charCode) { return UnicodeCharIs(UnicodePrintBits,  charCode); }
+//inline int OVR_CDECL OVR_iswpunct (wchar_t charCode) { return UnicodeCharIs(UnicodePunctBits,  charCode); }
+//inline int OVR_CDECL OVR_iswupper (wchar_t charCode) { return UnicodeCharIs(UnicodeUpperBits,  charCode); }
+
+int OVR_CDECL OVR_towupper(wchar_t charCode);
+int OVR_CDECL OVR_towlower(wchar_t charCode);
+
+#else // OVR_NO_WCTYPE
+
+inline int OVR_CDECL OVR_iswspace(wchar_t c)
+{
+    return iswspace(c);
+}
+
+inline int OVR_CDECL OVR_iswdigit(wchar_t c)
+{
+    return iswdigit(c);
+}
+
+inline int OVR_CDECL OVR_iswxdigit(wchar_t c)
+{
+    return iswxdigit(c);
+}
+
+inline int OVR_CDECL OVR_iswalpha(wchar_t c)
+{
+    return iswalpha(c);
+}
+
+inline int OVR_CDECL OVR_iswalnum(wchar_t c)
+{
+    return iswalnum(c);
+}
+
+inline wchar_t OVR_CDECL OVR_towlower(wchar_t c)
+{
+    return (wchar_t)towlower(c);
+}
+
+inline wchar_t OVR_towupper(wchar_t c)
+{
+    return (wchar_t)towupper(c);
+}
+
+#endif // OVR_NO_WCTYPE
+
+// ASCII versions of tolower and toupper. Don't use "char"
+inline int OVR_CDECL OVR_tolower(int c)
+{
+    return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c;
+}
+
+inline int OVR_CDECL OVR_toupper(int c)
+{
+    return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
+}
+
+
+
+inline double OVR_CDECL OVR_wcstod(const wchar_t* string, wchar_t** tailptr)
+{
+#if defined(OVR_OS_OTHER)
+    OVR_UNUSED(tailptr);
+    char buffer[64];
+    char* tp = NULL;
+    UPInt max = OVR_wcslen(string);
+    if (max > 63) max = 63;
+    unsigned char c = 0;
+    for (UPInt i=0; i < max; i++)
+    {
+        c = (unsigned char)string[i];
+        buffer[i] = ((c) < 128 ? (char)c : '!');
+    }
+    buffer[max] = 0;
+    return OVR_strtod(buffer, &tp);
+#else
+    return wcstod(string, tailptr);
+#endif
+}
+
+inline long OVR_CDECL OVR_wcstol(const wchar_t* string, wchar_t** tailptr, int radix)
+{
+#if defined(OVR_OS_OTHER)
+    OVR_UNUSED(tailptr);
+    char buffer[64];
+    char* tp = NULL;
+    UPInt max = OVR_wcslen(string);
+    if (max > 63) max = 63;
+    unsigned char c = 0;
+    for (UPInt i=0; i < max; i++)
+    {
+        c = (unsigned char)string[i];
+        buffer[i] = ((c) < 128 ? (char)c : '!');
+    }
+    buffer[max] = 0;
+    return strtol(buffer, &tp, radix);
+#else
+    return wcstol(string, tailptr, radix);
+#endif
+}
+
+} // OVR
+
+#endif // OVR_Std_h
diff --git a/LibOVR/Src/Kernel/OVR_String.cpp b/LibOVR/Src/Kernel/OVR_String.cpp
new file mode 100644
index 0000000..75b7c0e
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_String.cpp
@@ -0,0 +1,768 @@
+/************************************************************************************
+
+Filename    :   OVR_String.cpp
+Content     :   String UTF8 string implementation with copy-on-write semantics
+                (thread-safe for assignment but not modification).
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_String.h"
+
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifdef OVR_OS_QNX
+# include <strings.h>
+#endif
+
+namespace OVR {
+
+#define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift)
+
+String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} };
+
+
+String::String()
+{
+    pData = &NullData;
+    pData->AddRef();
+};
+
+String::String(const char* pdata)
+{
+    // Obtain length in bytes; it doesn't matter if _data is UTF8.
+    UPInt size = pdata ? OVR_strlen(pdata) : 0; 
+    pData = AllocDataCopy1(size, 0, pdata, size);
+};
+
+String::String(const char* pdata1, const char* pdata2, const char* pdata3)
+{
+    // Obtain length in bytes; it doesn't matter if _data is UTF8.
+    UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0; 
+    UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0; 
+    UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0; 
+
+    DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0,
+                                         pdata1, size1, pdata2, size2);
+    memcpy(pdataDesc->Data + size1 + size2, pdata3, size3);   
+    pData = pdataDesc;    
+}
+
+String::String(const char* pdata, UPInt size)
+{
+    OVR_ASSERT((size == 0) || (pdata != 0));
+    pData = AllocDataCopy1(size, 0, pdata, size);
+};
+
+
+String::String(const InitStruct& src, UPInt size)
+{
+    pData = AllocData(size, 0);
+    src.InitString(GetData()->Data, size);
+}
+
+String::String(const String& src)
+{    
+    pData = src.GetData();
+    pData->AddRef();
+}
+
+String::String(const StringBuffer& src)
+{
+    pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize());
+}
+
+String::String(const wchar_t* data)
+{
+    pData = &NullData;
+    pData->AddRef();
+    // Simplified logic for wchar_t constructor.
+    if (data)    
+        *this = data;    
+}
+
+
+String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize)
+{
+    String::DataDesc* pdesc;
+
+    if (size == 0)
+    {
+        pdesc = &NullData;
+        pdesc->AddRef();
+        return pdesc;
+    }
+
+    pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size);
+    pdesc->Data[size] = 0;
+    pdesc->RefCount = 1;
+    pdesc->Size     = size | lengthIsSize;  
+    return pdesc;
+}
+
+
+String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize,
+                                         const char* pdata, UPInt copySize)
+{
+    String::DataDesc* pdesc = AllocData(size, lengthIsSize);
+    memcpy(pdesc->Data, pdata, copySize);
+    return pdesc;
+}
+
+String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize,
+                                         const char* pdata1, UPInt copySize1,
+                                         const char* pdata2, UPInt copySize2)
+{
+    String::DataDesc* pdesc = AllocData(size, lengthIsSize);
+    memcpy(pdesc->Data, pdata1, copySize1);
+    memcpy(pdesc->Data + copySize1, pdata2, copySize2);
+    return pdesc;
+}
+
+
+UPInt String::GetLength() const 
+{
+    // Optimize length accesses for non-UTF8 character strings. 
+    DataDesc* pdata = GetData();
+    UPInt     length, size = pdata->GetSize();
+    
+    if (pdata->LengthIsSize())
+        return size;    
+    
+    length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size);
+    
+    if (length == size)
+        pdata->Size |= String_LengthIsSize;
+    
+    return length;
+}
+
+
+//static UInt32 String_CharSearch(const char* buf, )
+
+
+UInt32 String::GetCharAt(UPInt index) const 
+{  
+    SPInt       i = (SPInt) index;
+    DataDesc*   pdata = GetData();
+    const char* buf = pdata->Data;
+    UInt32      c;
+    
+    if (pdata->LengthIsSize())
+    {
+        OVR_ASSERT(index < pdata->GetSize());
+        buf += i;
+        return UTF8Util::DecodeNextChar_Advance0(&buf);
+    }
+
+    c = UTF8Util::GetCharAt(index, buf, pdata->GetSize());
+    return c;
+}
+
+UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const
+{
+    DataDesc*   pdata = GetData();
+    SPInt       i = (SPInt) index;
+    const char* buf = pdata->Data;
+    const char* end = buf + pdata->GetSize();
+    UInt32      c;
+
+    do 
+    {
+        c = UTF8Util::DecodeNextChar_Advance0(&buf);
+        i--;
+
+        if (buf >= end)
+        {
+            // We've hit the end of the string; don't go further.
+            OVR_ASSERT(i == 0);
+            return c;
+        }
+    } while (i >= 0);
+
+    *offset = buf;
+
+    return c;
+}
+
+UInt32 String::GetNextChar(const char** offset) const
+{
+    return UTF8Util::DecodeNextChar(offset);
+}
+
+
+
+void String::AppendChar(UInt32 ch)
+{
+    DataDesc*   pdata = GetData();
+    UPInt       size = pdata->GetSize();
+    char        buff[8];
+    SPInt       encodeSize = 0;
+
+    // Converts ch into UTF8 string and fills it into buff.   
+    UTF8Util::EncodeChar(buff, &encodeSize, ch);
+    OVR_ASSERT(encodeSize >= 0);
+
+    SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0,
+                           pdata->Data, size, buff, (UPInt)encodeSize));
+    pdata->Release();
+}
+
+
+void String::AppendString(const wchar_t* pstr, SPInt len)
+{
+    if (!pstr)
+        return;
+
+    DataDesc*   pdata = GetData();
+    UPInt       oldSize = pdata->GetSize();    
+    UPInt       encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len);
+
+    DataDesc*   pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0,
+                                          pdata->Data, oldSize);
+    UTF8Util::EncodeString(pnewData->Data + oldSize,  pstr, len);
+
+    SetData(pnewData);
+    pdata->Release();
+}
+
+
+void String::AppendString(const char* putf8str, SPInt utf8StrSz)
+{
+    if (!putf8str || !utf8StrSz)
+        return;
+    if (utf8StrSz == -1)
+        utf8StrSz = (SPInt)OVR_strlen(putf8str);
+
+    DataDesc*   pdata = GetData();
+    UPInt       oldSize = pdata->GetSize();
+
+    SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0,
+                           pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz));
+    pdata->Release();
+}
+
+void    String::AssignString(const InitStruct& src, UPInt size)
+{
+    DataDesc*   poldData = GetData();
+    DataDesc*   pnewData = AllocData(size, 0);
+    src.InitString(pnewData->Data, size);
+    SetData(pnewData);
+    poldData->Release();
+}
+
+void    String::AssignString(const char* putf8str, UPInt size)
+{
+    DataDesc* poldData = GetData();
+    SetData(AllocDataCopy1(size, 0, putf8str, size));
+    poldData->Release();
+}
+
+void    String::operator = (const char* pstr)
+{
+    AssignString(pstr, pstr ? OVR_strlen(pstr) : 0);
+}
+
+void    String::operator = (const wchar_t* pwstr)
+{
+    DataDesc*   poldData = GetData();
+    UPInt       size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0;
+
+    DataDesc*   pnewData = AllocData(size, 0);
+    UTF8Util::EncodeString(pnewData->Data, pwstr);
+    SetData(pnewData);
+    poldData->Release();
+}
+
+
+void    String::operator = (const String& src)
+{     
+    DataDesc*    psdata = src.GetData();
+    DataDesc*    pdata = GetData();    
+
+    SetData(psdata);
+    psdata->AddRef();
+    pdata->Release();
+}
+
+
+void    String::operator = (const StringBuffer& src)
+{ 
+    DataDesc* polddata = GetData();    
+    SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()));
+    polddata->Release();
+}
+
+void    String::operator += (const String& src)
+{
+    DataDesc   *pourData = GetData(),
+               *psrcData = src.GetData();
+    UPInt       ourSize  = pourData->GetSize(),
+                srcSize  = psrcData->GetSize();
+    UPInt       lflag    = pourData->GetLengthFlag() & psrcData->GetLengthFlag();
+
+    SetData(AllocDataCopy2(ourSize + srcSize, lflag,
+                           pourData->Data, ourSize, psrcData->Data, srcSize));
+    pourData->Release();
+}
+
+
+String   String::operator + (const char* str) const
+{   
+    String tmp1(*this);
+    tmp1 += (str ? str : "");
+    return tmp1;
+}
+
+String   String::operator + (const String& src) const
+{ 
+    String tmp1(*this);
+    tmp1 += src;
+    return tmp1;
+}
+
+void    String::Remove(UPInt posAt, SPInt removeLength)
+{
+    DataDesc*   pdata = GetData();
+    UPInt       oldSize = pdata->GetSize();    
+    // Length indicates the number of characters to remove. 
+    UPInt       length = GetLength();
+
+    // If index is past the string, nothing to remove.
+    if (posAt >= length)
+        return;
+    // Otherwise, cap removeLength to the length of the string.
+    if ((posAt + removeLength) > length)
+        removeLength = length - posAt;
+
+    // Get the byte position of the UTF8 char at position posAt.
+    SPInt bytePos    = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize);
+    SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos);
+
+    SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(),
+                           pdata->Data, bytePos,
+                           pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize)));
+    pdata->Release();
+}
+
+
+String   String::Substring(UPInt start, UPInt end) const
+{
+    UPInt length = GetLength();
+    if ((start >= length) || (start >= end))
+        return String();   
+
+    DataDesc* pdata = GetData();
+    
+    // If size matches, we know the exact index range.
+    if (pdata->LengthIsSize())
+        return String(pdata->Data + start, end - start);
+    
+    // Get position of starting character.
+    SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize());
+    SPInt byteSize  = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart);
+    return String(pdata->Data + byteStart, (UPInt)byteSize);
+}
+
+void String::Clear()
+{   
+    NullData.AddRef();
+    GetData()->Release();
+    SetData(&NullData);
+}
+
+
+String   String::ToUpper() const 
+{       
+    UInt32      c;
+    const char* psource = GetData()->Data;
+    const char* pend = psource + GetData()->GetSize();
+    String      str;
+    SPInt       bufferOffset = 0;
+    char        buffer[512];
+    
+    while(psource < pend)
+    {
+        do {            
+            c = UTF8Util::DecodeNextChar_Advance0(&psource);
+            UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c)));
+        } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
+
+        // Append string a piece at a time.
+        str.AppendString(buffer, bufferOffset);
+        bufferOffset = 0;
+    }
+
+    return str;
+}
+
+String   String::ToLower() const 
+{
+    UInt32      c;
+    const char* psource = GetData()->Data;
+    const char* pend = psource + GetData()->GetSize();
+    String      str;
+    SPInt       bufferOffset = 0;
+    char        buffer[512];
+
+    while(psource < pend)
+    {
+        do {
+            c = UTF8Util::DecodeNextChar_Advance0(&psource);
+            UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c)));
+        } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
+
+        // Append string a piece at a time.
+        str.AppendString(buffer, bufferOffset);
+        bufferOffset = 0;
+    }
+
+    return str;
+}
+
+
+
+String& String::Insert(const char* substr, UPInt posAt, SPInt strSize)
+{
+    DataDesc* poldData   = GetData();
+    UPInt     oldSize    = poldData->GetSize();
+    UPInt     insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize;    
+    UPInt     byteIndex  =  (poldData->LengthIsSize()) ?
+                            posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize);
+
+    OVR_ASSERT(byteIndex <= oldSize);
+    
+    DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0,
+                                        poldData->Data, byteIndex, substr, insertSize);
+    memcpy(pnewData->Data + byteIndex + insertSize,
+           poldData->Data + byteIndex, oldSize - byteIndex);
+    SetData(pnewData);
+    poldData->Release();
+    return *this;
+}
+
+/*
+String& String::Insert(const UInt32* substr, UPInt posAt, SPInt len)
+{
+    for (SPInt i = 0; i < len; ++i)
+    {
+        UPInt charw = InsertCharAt(substr[i], posAt);
+        posAt += charw;
+    }
+    return *this;
+}
+*/
+
+UPInt String::InsertCharAt(UInt32 c, UPInt posAt)
+{
+    char    buf[8];
+    SPInt   index = 0;
+    UTF8Util::EncodeChar(buf, &index, c);
+    OVR_ASSERT(index >= 0);
+    buf[(UPInt)index] = 0;
+
+    Insert(buf, posAt, index);
+    return (UPInt)index;
+}
+
+
+int String::CompareNoCase(const char* a, const char* b)
+{
+    return OVR_stricmp(a, b);
+}
+
+int String::CompareNoCase(const char* a, const char* b, SPInt len)
+{
+    if (len)
+    {
+        SPInt f,l;
+        SPInt slen = len;
+        const char *s = b;
+        do {
+            f = (SPInt)OVR_tolower((int)(*(a++)));
+            l = (SPInt)OVR_tolower((int)(*(b++)));
+        } while (--len && f && (f == l) && *b != 0);
+
+        if (f == l && (len != 0 || *b != 0))
+        {
+            f = (SPInt)slen;
+            l = (SPInt)OVR_strlen(s);
+            return int(f - l);
+        }
+
+        return int(f - l);
+    }
+    else
+        return (0-(int)OVR_strlen(b));
+}
+
+// ***** Implement hash static functions
+
+// Hash function
+UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed)
+{
+    const UByte*    pdata   = (const UByte*) pdataIn;
+    UPInt           h       = seed;
+    while (size > 0)
+    {
+        size--;
+        h = ((h << 5) + h) ^ (unsigned) pdata[size];
+    }
+
+    return h;
+}
+
+// Hash function, case-insensitive
+UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed)
+{
+    const UByte*    pdata = (const UByte*) pdataIn;
+    UPInt           h = seed;
+    while (size > 0)
+    {
+        size--;
+        h = ((h << 5) + h) ^ OVR_tolower(pdata[size]);
+    }
+
+    // Alternative: "sdbm" hash function, suggested at same web page above.
+    // h = 0;
+    // for bytes { h = (h << 16) + (h << 6) - hash + *p; }
+    return h;
+}
+
+
+
+// ***** String Buffer used for Building Strings
+
+
+#define OVR_SBUFF_DEFAULT_GROW_SIZE 512
+// Constructors / Destructor.
+StringBuffer::StringBuffer()
+    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
+{
+}
+
+StringBuffer::StringBuffer(UPInt growSize)
+    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
+{
+    SetGrowSize(growSize);
+}
+
+StringBuffer::StringBuffer(const char* data)
+    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
+{
+    AppendString(data);
+}
+
+StringBuffer::StringBuffer(const char* data, UPInt dataSize)
+    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
+{
+    AppendString(data, dataSize);
+}
+
+StringBuffer::StringBuffer(const String& src)
+    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
+{
+    AppendString(src.ToCStr(), src.GetSize());
+}
+
+StringBuffer::StringBuffer(const StringBuffer& src)
+    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
+{
+    AppendString(src.ToCStr(), src.GetSize());
+}
+
+StringBuffer::StringBuffer(const wchar_t* data)
+    : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
+{
+    *this = data;
+}
+
+StringBuffer::~StringBuffer()
+{
+    if (pData)
+        OVR_FREE(pData);
+}
+void StringBuffer::SetGrowSize(UPInt growSize) 
+{ 
+    if (growSize <= 16)
+        GrowSize = 16;
+    else
+    {
+        UByte bits = Alg::UpperBit(UInt32(growSize-1));
+        UPInt size = 1<<bits;
+        GrowSize = size == growSize ? growSize : size;
+    }
+}
+
+UPInt StringBuffer::GetLength() const
+{
+    UPInt length, size = GetSize();
+    if (LengthIsSize)
+        return size;
+
+    length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize());
+
+    if (length == GetSize())
+        LengthIsSize = true;
+    return length;
+}
+
+void    StringBuffer::Reserve(UPInt _size)
+{
+    if (_size >= BufferSize) // >= because of trailing zero! (!AB)
+    {
+        BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1);
+        if (!pData)
+            pData = (char*)OVR_ALLOC(BufferSize);
+        else 
+            pData = (char*)OVR_REALLOC(pData, BufferSize);
+    }
+}
+void    StringBuffer::Resize(UPInt _size)
+{
+    Reserve(_size);
+    LengthIsSize = false;
+    Size = _size;
+    if (pData)
+        pData[Size] = 0;
+}
+
+void StringBuffer::Clear()
+{
+    Resize(0);
+    /*
+    if (pData != pEmptyNullData)
+    {
+        OVR_FREE(pHeap, pData);
+        pData = pEmptyNullData;
+        Size = BufferSize = 0;
+        LengthIsSize = false;
+    }
+    */
+}
+// Appends a character
+void     StringBuffer::AppendChar(UInt32 ch)
+{
+    char    buff[8];
+    UPInt   origSize = GetSize();
+
+    // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes
+    // in the UTF8 string.
+    SPInt   srcSize = 0;
+    UTF8Util::EncodeChar(buff, &srcSize, ch);
+    OVR_ASSERT(srcSize >= 0);
+    
+    UPInt size = origSize + srcSize;
+    Resize(size);
+    memcpy(pData + origSize, buff, srcSize);
+}
+
+// Append a string
+void     StringBuffer::AppendString(const wchar_t* pstr, SPInt len)
+{
+    if (!pstr)
+        return;
+
+    SPInt   srcSize     = UTF8Util::GetEncodeStringSize(pstr, len);
+    UPInt   origSize    = GetSize();
+    UPInt   size        = srcSize + origSize;
+
+    Resize(size);
+    UTF8Util::EncodeString(pData + origSize,  pstr, len);
+}
+
+void      StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz)
+{
+    if (!putf8str || !utf8StrSz)
+        return;
+    if (utf8StrSz == -1)
+        utf8StrSz = (SPInt)OVR_strlen(putf8str);
+
+    UPInt   origSize    = GetSize();
+    UPInt   size        = utf8StrSz + origSize;
+
+    Resize(size);
+    memcpy(pData + origSize, putf8str, utf8StrSz);
+}
+
+
+void      StringBuffer::operator = (const char* pstr)
+{
+    pstr = pstr ? pstr : "";
+    UPInt size = OVR_strlen(pstr);
+    Resize(size);
+    memcpy(pData, pstr, size);
+}
+
+void      StringBuffer::operator = (const wchar_t* pstr)
+{
+    pstr = pstr ? pstr : L"";
+    UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr);
+    Resize(size);
+    UTF8Util::EncodeString(pData, pstr);
+}
+
+void      StringBuffer::operator = (const String& src)
+{
+    Resize(src.GetSize());
+    memcpy(pData, src.ToCStr(), src.GetSize());
+}
+
+void      StringBuffer::operator = (const StringBuffer& src)
+{
+	Clear();
+	AppendString(src.ToCStr(), src.GetSize());
+}
+
+
+// Inserts substr at posAt
+void      StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len)
+{
+    UPInt     oldSize    = Size;
+    UPInt     insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len;    
+    UPInt     byteIndex  = LengthIsSize ? posAt : 
+                           (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size);
+
+    OVR_ASSERT(byteIndex <= oldSize);
+    Reserve(oldSize + insertSize);
+
+    memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1);
+    memcpy (pData + byteIndex, substr, insertSize);
+    LengthIsSize = false;
+    Size = oldSize + insertSize;
+    pData[Size] = 0;
+}
+
+// Inserts character at posAt
+UPInt     StringBuffer::InsertCharAt(UInt32 c, UPInt posAt)
+{
+    char    buf[8];
+    SPInt   len = 0;
+    UTF8Util::EncodeChar(buf, &len, c);
+    OVR_ASSERT(len >= 0);
+    buf[(UPInt)len] = 0;
+
+    Insert(buf, posAt, len);
+    return (UPInt)len;
+}
+
+} // OVR
diff --git a/LibOVR/Src/Kernel/OVR_String.h b/LibOVR/Src/Kernel/OVR_String.h
new file mode 100644
index 0000000..0866968
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_String.h
@@ -0,0 +1,657 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_String.h
+Content     :   String UTF8 string implementation with copy-on-write semantics
+                (thread-safe for assignment but not modification).
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_String_h
+#define OVR_String_h
+
+#include "OVR_Types.h"
+#include "OVR_Allocator.h"
+#include "OVR_UTF8Util.h"
+#include "OVR_Atomic.h"
+#include "OVR_Std.h"
+#include "OVR_Alg.h"
+
+namespace OVR {
+
+// ***** Classes
+
+class String;
+class StringBuffer;
+
+
+//-----------------------------------------------------------------------------------
+// ***** String Class 
+
+// String is UTF8 based string class with copy-on-write implementation
+// for assignment.
+
+class String
+{
+protected:
+
+    enum FlagConstants
+    {
+        //Flag_GetLength      = 0x7FFFFFFF,
+        // This flag is set if GetLength() == GetSize() for a string.
+        // Avoid extra scanning is Substring and indexing logic.
+        Flag_LengthIsSizeShift   = (sizeof(UPInt)*8 - 1)
+    };
+
+
+    // Internal structure to hold string data
+    struct DataDesc
+    {
+        // Number of bytes. Will be the same as the number of chars if the characters
+        // are ascii, may not be equal to number of chars in case string data is UTF8.
+        UPInt   Size;       
+        volatile SInt32 RefCount;
+        char    Data[1];
+
+        void    AddRef()
+        {
+            AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, 1);
+        }
+        // Decrement ref count. This needs to be thread-safe, since
+        // a different thread could have also decremented the ref count.
+        // For example, if u start off with a ref count = 2. Now if u
+        // decrement the ref count and check against 0 in different
+        // statements, a different thread can also decrement the ref count
+        // in between our decrement and checking against 0 and will find
+        // the ref count = 0 and delete the object. This will lead to a crash
+        // when context switches to our thread and we'll be trying to delete
+        // an already deleted object. Hence decrementing the ref count and
+        // checking against 0 needs to made an atomic operation.
+        void    Release()
+        {
+            if ((AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
+                OVR_FREE(this);
+        }
+
+        static UPInt GetLengthFlagBit()     { return UPInt(1) << Flag_LengthIsSizeShift; }
+        UPInt       GetSize() const         { return Size & ~GetLengthFlagBit() ; }
+        UPInt       GetLengthFlag()  const  { return Size & GetLengthFlagBit(); }
+        bool        LengthIsSize() const    { return GetLengthFlag() != 0; }
+    };
+
+    // Heap type of the string is encoded in the lower bits.
+    enum HeapType
+    {
+        HT_Global   = 0,    // Heap is global.
+        HT_Local    = 1,    // SF::String_loc: Heap is determined based on string's address.
+        HT_Dynamic  = 2,    // SF::String_temp: Heap is stored as a part of the class.
+        HT_Mask     = 3
+    };
+
+    union {
+        DataDesc* pData;
+        UPInt     HeapTypeBits;
+    };
+    typedef union {
+        DataDesc* pData;
+        UPInt     HeapTypeBits;
+    } DataDescUnion;
+
+    inline HeapType    GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); }
+
+    inline DataDesc*   GetData() const
+    {
+        DataDescUnion u;
+        u.pData    = pData;
+        u.HeapTypeBits = (u.HeapTypeBits & ~(UPInt)HT_Mask);
+        return u.pData;
+    }
+    
+    inline void        SetData(DataDesc* pdesc)
+    {
+        HeapType ht = GetHeapType();
+        pData = pdesc;
+        OVR_ASSERT((HeapTypeBits & HT_Mask) == 0);
+        HeapTypeBits |= ht;        
+    }
+
+    
+    DataDesc*   AllocData(UPInt size, UPInt lengthIsSize);
+    DataDesc*   AllocDataCopy1(UPInt size, UPInt lengthIsSize,
+                               const char* pdata, UPInt copySize);
+    DataDesc*   AllocDataCopy2(UPInt size, UPInt lengthIsSize,
+                               const char* pdata1, UPInt copySize1,
+                               const char* pdata2, UPInt copySize2);
+
+    // Special constructor to avoid data initalization when used in derived class.
+    struct NoConstructor { };
+    String(const NoConstructor&) { }
+
+public:
+
+    // For initializing string with dynamic buffer
+    struct InitStruct
+    {
+        virtual ~InitStruct() { }
+        virtual void InitString(char* pbuffer, UPInt size) const = 0;
+    };
+
+
+    // Constructors / Destructors.
+    String();
+    String(const char* data);
+    String(const char* data1, const char* pdata2, const char* pdata3 = 0);
+    String(const char* data, UPInt buflen);
+    String(const String& src);
+    String(const StringBuffer& src);
+    String(const InitStruct& src, UPInt size);
+    explicit String(const wchar_t* data);      
+
+    // Destructor (Captain Obvious guarantees!)
+    ~String()
+    {
+        GetData()->Release();
+    }
+
+    // Declaration of NullString
+    static DataDesc NullData;
+
+
+    // *** General Functions
+
+    void        Clear();
+
+    // For casting to a pointer to char.
+    operator const char*() const        { return GetData()->Data; }
+    // Pointer to raw buffer.
+    const char* ToCStr() const          { return GetData()->Data; }
+
+    // Returns number of bytes
+    UPInt       GetSize() const         { return GetData()->GetSize() ; }
+    // Tells whether or not the string is empty
+    bool        IsEmpty() const         { return GetSize() == 0; }
+
+    // Returns  number of characters
+    UPInt       GetLength() const;
+
+    // Returns  character at the specified index
+    UInt32      GetCharAt(UPInt index) const;
+    UInt32      GetFirstCharAt(UPInt index, const char** offset) const;
+    UInt32      GetNextChar(const char** offset) const;
+
+    // Appends a character
+    void        AppendChar(UInt32 ch);
+
+    // Append a string
+    void        AppendString(const wchar_t* pstr, SPInt len = -1);
+    void        AppendString(const char* putf8str, SPInt utf8StrSz = -1);
+
+    // Assigned a string with dynamic data (copied through initializer).
+    void        AssignString(const InitStruct& src, UPInt size);
+    // Assigns string with known size.
+    void        AssignString(const char* putf8str, UPInt size);
+
+    //  Resize the string to the new size
+//  void        Resize(UPInt _size);
+
+    // Removes the character at posAt
+    void        Remove(UPInt posAt, SPInt len = 1);
+
+    // Returns a String that's a substring of this.
+    //  -start is the index of the first UTF8 character you want to include.
+    //  -end is the index one past the last UTF8 character you want to include.
+    String   Substring(UPInt start, UPInt end) const;
+
+    // Case-conversion
+    String   ToUpper() const;
+    String   ToLower() const;
+
+    // Inserts substr at posAt
+    String&    Insert (const char* substr, UPInt posAt, SPInt len = -1);
+
+    // Inserts character at posAt
+    UPInt       InsertCharAt(UInt32 c, UPInt posAt);
+
+    // Inserts substr at posAt, which is an index of a character (not byte).
+    // Of size is specified, it is in bytes.
+//  String&    Insert(const UInt32* substr, UPInt posAt, SPInt size = -1);
+
+    // Get Byte index of the character at position = index
+    UPInt       GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); }
+
+    // Utility: case-insensitive string compare.  stricmp() & strnicmp() are not
+    // ANSI or POSIX, do not seem to appear in Linux.
+    static int OVR_STDCALL   CompareNoCase(const char* a, const char* b);
+    static int OVR_STDCALL   CompareNoCase(const char* a, const char* b, SPInt len);
+
+    // Hash function, case-insensitive
+    static UPInt OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed = 5381);
+
+    // Hash function, case-sensitive
+    static UPInt OVR_STDCALL BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed = 5381);
+
+
+    // ***** File path parsing helper functions.
+    // Implemented in OVR_String_FilePath.cpp.
+
+    // Absolute paths can star with:
+    //  - protocols:        'file://', 'http://'
+    //  - windows drive:    'c:\'
+    //  - UNC share name:   '\\share'
+    //  - unix root         '/'
+    static bool HasAbsolutePath(const char* path);
+    static bool HasExtension(const char* path);
+    static bool HasProtocol(const char* path);
+
+    bool    HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); }
+    bool    HasExtension() const    { return HasExtension(ToCStr()); }
+    bool    HasProtocol() const     { return HasProtocol(ToCStr()); }
+
+    String  GetProtocol() const;    // Returns protocol, if any, with trailing '://'.
+    String  GetPath() const;        // Returns path with trailing '/'.
+    String  GetFilename() const;    // Returns filename, including extension.
+    String  GetExtension() const;   // Returns extension with a dot.
+
+    void    StripProtocol();        // Strips front protocol, if any, from the string.
+    void    StripExtension();       // Strips off trailing extension.
+    
+
+    // Operators
+    // Assignment
+    void        operator =  (const char* str);
+    void        operator =  (const wchar_t* str);
+    void        operator =  (const String& src);
+    void        operator =  (const StringBuffer& src);
+
+    // Addition
+    void        operator += (const String& src);
+    void        operator += (const char* psrc)       { AppendString(psrc); }
+    void        operator += (const wchar_t* psrc)    { AppendString(psrc); }
+    void        operator += (char  ch)               { AppendChar(ch); }
+    String      operator +  (const char* str) const;
+    String      operator +  (const String& src)  const;
+
+    // Comparison
+    bool        operator == (const String& str) const
+    {
+        return (OVR_strcmp(GetData()->Data, str.GetData()->Data)== 0);
+    }
+
+    bool        operator != (const String& str) const
+    {
+        return !operator == (str);
+    }
+
+    bool        operator == (const char* str) const
+    {
+        return OVR_strcmp(GetData()->Data, str) == 0;
+    }
+
+    bool        operator != (const char* str) const
+    {
+        return !operator == (str);
+    }
+
+    bool        operator <  (const char* pstr) const
+    {
+        return OVR_strcmp(GetData()->Data, pstr) < 0;
+    }
+
+    bool        operator <  (const String& str) const
+    {
+        return *this < str.GetData()->Data;
+    }
+
+    bool        operator >  (const char* pstr) const
+    {
+        return OVR_strcmp(GetData()->Data, pstr) > 0;
+    }
+
+    bool        operator >  (const String& str) const
+    {
+        return *this > str.GetData()->Data;
+    }
+
+    int CompareNoCase(const char* pstr) const
+    {
+        return CompareNoCase(GetData()->Data, pstr);
+    }
+    int CompareNoCase(const String& str) const
+    {
+        return CompareNoCase(GetData()->Data, str.ToCStr());
+    }
+
+    // Accesses raw bytes
+    const char&     operator [] (int index) const
+    {
+        OVR_ASSERT(index >= 0 && (UPInt)index < GetSize());
+        return GetData()->Data[index];
+    }
+    const char&     operator [] (UPInt index) const
+    {
+        OVR_ASSERT(index < GetSize());
+        return GetData()->Data[index];
+    }
+
+
+    // Case insensitive keys are used to look up insensitive string in hash tables
+    // for SWF files with version before SWF 7.
+    struct NoCaseKey
+    {   
+        const String* pStr;
+        NoCaseKey(const String &str) : pStr(&str){};
+    };
+
+    bool    operator == (const NoCaseKey& strKey) const
+    {
+        return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
+    }
+    bool    operator != (const NoCaseKey& strKey) const
+    {
+        return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
+    }
+
+    // Hash functor used for strings.
+    struct HashFunctor
+    {    
+        UPInt  operator()(const String& data) const
+        {
+            UPInt  size = data.GetSize();
+            return String::BernsteinHashFunction((const char*)data, size);
+        }        
+    };
+    // Case-insensitive hash functor used for strings. Supports additional
+    // lookup based on NoCaseKey.
+    struct NoCaseHashFunctor
+    {    
+        UPInt  operator()(const String& data) const
+        {
+            UPInt  size = data.GetSize();
+            return String::BernsteinHashFunctionCIS((const char*)data, size);
+        }
+        UPInt  operator()(const NoCaseKey& data) const
+        {       
+            UPInt  size = data.pStr->GetSize();
+            return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size);
+        }
+    };
+
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** String Buffer used for Building Strings
+
+class StringBuffer
+{
+    char*           pData;
+    UPInt           Size;
+    UPInt           BufferSize;
+    UPInt           GrowSize;    
+    mutable bool    LengthIsSize;    
+
+public:
+
+    // Constructors / Destructor.    
+    StringBuffer();
+    explicit StringBuffer(UPInt growSize);
+    StringBuffer(const char* data);
+    StringBuffer(const char* data, UPInt buflen);
+    StringBuffer(const String& src);
+    StringBuffer(const StringBuffer& src);
+    explicit StringBuffer(const wchar_t* data);
+    ~StringBuffer();
+    
+
+    // Modify grow size used for growing/shrinking the buffer.
+    UPInt       GetGrowSize() const         { return GrowSize; }
+    void        SetGrowSize(UPInt growSize);
+    
+
+    // *** General Functions
+    // Does not release memory, just sets Size to 0
+    void        Clear();
+
+    // For casting to a pointer to char.
+    operator const char*() const        { return (pData) ? pData : ""; }
+    // Pointer to raw buffer.
+    const char* ToCStr() const          { return (pData) ? pData : ""; }
+
+    // Returns number of bytes.
+    UPInt       GetSize() const         { return Size ; }
+    // Tells whether or not the string is empty.
+    bool        IsEmpty() const         { return GetSize() == 0; }
+
+    // Returns  number of characters
+    UPInt       GetLength() const;
+
+    // Returns  character at the specified index
+    UInt32      GetCharAt(UPInt index) const;
+    UInt32      GetFirstCharAt(UPInt index, const char** offset) const;
+    UInt32      GetNextChar(const char** offset) const;
+
+
+    //  Resize the string to the new size
+    void        Resize(UPInt _size);
+    void        Reserve(UPInt _size);
+
+    // Appends a character
+    void        AppendChar(UInt32 ch);
+
+    // Append a string
+    void        AppendString(const wchar_t* pstr, SPInt len = -1);
+    void        AppendString(const char* putf8str, SPInt utf8StrSz = -1);
+    void        AppendFormat(const char* format, ...);
+
+    // Assigned a string with dynamic data (copied through initializer).
+    //void        AssignString(const InitStruct& src, UPInt size);
+
+    // Inserts substr at posAt
+    void        Insert (const char* substr, UPInt posAt, SPInt len = -1);
+    // Inserts character at posAt
+    UPInt       InsertCharAt(UInt32 c, UPInt posAt);
+
+    // Assignment
+    void        operator =  (const char* str);
+    void        operator =  (const wchar_t* str);
+    void        operator =  (const String& src);
+    void        operator =  (const StringBuffer& src);
+
+    // Addition
+    void        operator += (const String& src)      { AppendString(src.ToCStr(),src.GetSize()); }
+    void        operator += (const char* psrc)       { AppendString(psrc); }
+    void        operator += (const wchar_t* psrc)    { AppendString(psrc); }
+    void        operator += (char  ch)               { AppendChar(ch); }
+    //String   operator +  (const char* str) const ;
+    //String   operator +  (const String& src)  const ;
+
+    // Accesses raw bytes
+    char&       operator [] (int index)
+    {
+        OVR_ASSERT(((UPInt)index) < GetSize());
+        return pData[index];
+    }
+    char&       operator [] (UPInt index)
+    {
+        OVR_ASSERT(index < GetSize());
+        return pData[index];
+    }
+
+    const char&     operator [] (int index) const 
+    {
+        OVR_ASSERT(((UPInt)index) < GetSize());
+        return pData[index];
+    }
+    const char&     operator [] (UPInt index) const
+    {
+        OVR_ASSERT(index < GetSize());
+        return pData[index];
+    }
+};
+
+
+//
+// Wrapper for string data. The data must have a guaranteed 
+// lifespan throughout the usage of the wrapper. Not intended for 
+// cached usage. Not thread safe.
+//
+class StringDataPtr
+{
+public:
+    StringDataPtr() : pStr(NULL), Size(0) {}
+    StringDataPtr(const StringDataPtr& p)
+        : pStr(p.pStr), Size(p.Size) {}
+    StringDataPtr(const char* pstr, UPInt sz)
+        : pStr(pstr), Size(sz) {}
+    StringDataPtr(const char* pstr)
+        : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {}
+    explicit StringDataPtr(const String& str)
+        : pStr(str.ToCStr()), Size(str.GetSize()) {}
+    template <typename T, int N> 
+    StringDataPtr(const T (&v)[N])
+        : pStr(v), Size(N) {}
+
+public:
+    const char* ToCStr() const { return pStr; }
+    UPInt       GetSize() const { return Size; }
+    bool        IsEmpty() const { return GetSize() == 0; }
+
+    // value is a prefix of this string
+    // Character's values are not compared.
+    bool        IsPrefix(const StringDataPtr& value) const
+    {
+        return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize();
+    }
+    // value is a suffix of this string
+    // Character's values are not compared.
+    bool        IsSuffix(const StringDataPtr& value) const
+    {
+        return ToCStr() <= value.ToCStr() && (End()) == (value.End());
+    }
+
+    // Find first character.
+    // init_ind - initial index.
+    SPInt       FindChar(char c, UPInt init_ind = 0) const 
+    {
+        for (UPInt i = init_ind; i < GetSize(); ++i)
+            if (pStr[i] == c)
+                return static_cast<SPInt>(i);
+
+        return -1; 
+    }
+
+    // Find last character.
+    // init_ind - initial index.
+    SPInt       FindLastChar(char c, UPInt init_ind = ~0) const 
+    {
+        if (init_ind == (UPInt)~0 || init_ind > GetSize())
+            init_ind = GetSize();
+        else
+            ++init_ind;
+
+        for (UPInt i = init_ind; i > 0; --i)
+            if (pStr[i - 1] == c)
+                return static_cast<SPInt>(i - 1);
+
+        return -1; 
+    }
+
+    // Create new object and trim size bytes from the left.
+    StringDataPtr  GetTrimLeft(UPInt size) const
+    {
+        // Limit trim size to the size of the string.
+        size = Alg::PMin(GetSize(), size);
+
+        return StringDataPtr(ToCStr() + size, GetSize() - size);
+    }
+    // Create new object and trim size bytes from the right.
+    StringDataPtr  GetTrimRight(UPInt size) const
+    {
+        // Limit trim to the size of the string.
+        size = Alg::PMin(GetSize(), size);
+
+        return StringDataPtr(ToCStr(), GetSize() - size);
+    }
+
+    // Create new object, which contains next token.
+    // Useful for parsing.
+    StringDataPtr GetNextToken(char separator = ':') const
+    {
+        UPInt cur_pos = 0;
+        const char* cur_str = ToCStr();
+
+        for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos)
+        {
+            if (cur_str[cur_pos] == separator)
+            {
+                break;
+            }
+        }
+
+        return StringDataPtr(ToCStr(), cur_pos);
+    }
+
+    // Trim size bytes from the left.
+    StringDataPtr& TrimLeft(UPInt size)
+    {
+        // Limit trim size to the size of the string.
+        size = Alg::PMin(GetSize(), size);
+        pStr += size;
+        Size -= size;
+
+        return *this;
+    }
+    // Trim size bytes from the right.
+    StringDataPtr& TrimRight(UPInt size)
+    {
+        // Limit trim to the size of the string.
+        size = Alg::PMin(GetSize(), size);
+        Size -= size;
+
+        return *this;
+    }
+
+    const char* Begin() const { return ToCStr(); }
+    const char* End() const { return ToCStr() + GetSize(); }
+
+    // Hash functor used string data pointers
+    struct HashFunctor
+    {    
+        UPInt operator()(const StringDataPtr& data) const
+        {
+            return String::BernsteinHashFunction(data.ToCStr(), data.GetSize());
+        }        
+    };
+
+    bool operator== (const StringDataPtr& data) const 
+    {
+        return (OVR_strncmp(pStr, data.pStr, data.Size) == 0);
+    }
+
+protected:
+    const char* pStr;
+    UPInt       Size;
+};
+
+} // OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_StringHash.h b/LibOVR/Src/Kernel/OVR_StringHash.h
new file mode 100644
index 0000000..baa80a7
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_StringHash.h
@@ -0,0 +1,100 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_StringHash.h
+Content     :   String hash table used when optional case-insensitive
+                lookup is required.
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_StringHash_h
+#define OVR_StringHash_h
+
+#include "OVR_String.h"
+#include "OVR_Hash.h"
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// *** StringHash
+
+// This is a custom string hash table that supports case-insensitive
+// searches through special functions such as GetCaseInsensitive, etc.
+// This class is used for Flash labels, exports and other case-insensitive tables.
+
+template<class U, class Allocator = ContainerAllocator<U> >
+class StringHash : public Hash<String, U, String::NoCaseHashFunctor, Allocator>
+{
+public:
+    typedef U                                                        ValueType;
+    typedef StringHash<U, Allocator>                                 SelfType;
+    typedef Hash<String, U, String::NoCaseHashFunctor, Allocator>    BaseType;
+
+public:    
+
+    void    operator = (const SelfType& src) { BaseType::operator = (src); }
+
+    bool    GetCaseInsensitive(const String& key, U* pvalue) const
+    {
+        String::NoCaseKey ikey(key);
+        return BaseType::GetAlt(ikey, pvalue);
+    }
+    // Pointer-returning get variety.
+    const U* GetCaseInsensitive(const String& key) const   
+    {
+        String::NoCaseKey ikey(key);
+        return BaseType::GetAlt(ikey);
+    }
+    U*  GetCaseInsensitive(const String& key)
+    {
+        String::NoCaseKey ikey(key);
+        return BaseType::GetAlt(ikey);
+    }
+
+    
+    typedef typename BaseType::Iterator base_iterator;
+
+    base_iterator    FindCaseInsensitive(const String& key)
+    {
+        String::NoCaseKey ikey(key);
+        return BaseType::FindAlt(ikey);
+    }
+
+    // Set just uses a find and assigns value if found. The key is not modified;
+    // this behavior is identical to Flash string variable assignment.    
+    void    SetCaseInsensitive(const String& key, const U& value)
+    {
+        base_iterator it = FindCaseInsensitive(key);
+        if (it != BaseType::End())
+        {
+            it->Second = value;
+        }
+        else
+        {
+            BaseType::Add(key, value);
+        }
+    } 
+};
+
+} // OVR 
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp b/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp
new file mode 100644
index 0000000..e196dd7
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_String_FormatUtil.cpp
@@ -0,0 +1,53 @@
+/************************************************************************************
+
+Filename    :   OVR_String_FormatUtil.cpp
+Content     :   String format functions.
+Created     :   February 27, 2013
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_String.h"
+#include "OVR_Log.h"
+
+namespace OVR {
+
+void StringBuffer::AppendFormat(const char* format, ...)
+{       
+    va_list argList;
+
+    va_start(argList, format);
+    UPInt size = OVR_vscprintf(format, argList);
+    va_end(argList);
+
+    char* buffer = (char*) OVR_ALLOC(sizeof(char) * (size+1));
+
+    va_start(argList, format);
+    UPInt result = OVR_vsprintf(buffer, size+1, format, argList);
+    OVR_UNUSED1(result);
+    va_end(argList);
+    OVR_ASSERT_LOG(result == size, ("Error in OVR_vsprintf"));
+
+    AppendString(buffer);
+
+    OVR_FREE(buffer);
+}
+
+} // OVR
diff --git a/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp b/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp
new file mode 100644
index 0000000..02abe15
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_String_PathUtil.cpp
@@ -0,0 +1,211 @@
+/************************************************************************************
+
+Filename    :   OVR_String_PathUtil.cpp
+Content     :   String filename/url helper function
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_String.h"
+#include "OVR_UTF8Util.h"
+
+namespace OVR {
+
+//--------------------------------------------------------------------
+// ***** Path-Scanner helper function 
+
+// Scans file path finding filename start and extension start, fills in their addess.
+void ScanFilePath(const char* url, const char** pfilename, const char** pext)
+{ 
+    const char* urlStart = url;
+    const char *filename = 0;
+    const char *lastDot = 0;
+
+    UInt32 charVal = UTF8Util::DecodeNextChar(&url);
+
+    while (charVal != 0)
+    {
+        if ((charVal == '/') || (charVal == '\\'))
+        {
+            filename = url;
+            lastDot  = 0;
+        }
+        else if (charVal == '.')
+        {
+            lastDot = url - 1;
+        }
+        
+        charVal = UTF8Util::DecodeNextChar(&url);
+    }
+
+    if (pfilename)
+    {
+        // It was a naked filename
+        if (urlStart && (*urlStart != '.') && *urlStart)
+            *pfilename = urlStart;
+        else
+            *pfilename = filename;
+    }
+
+    if (pext)
+    {
+        *pext = lastDot;
+    }
+}
+
+// Scans till the end of protocol. Returns first character past protocol,
+// 0 if not found.
+//  - protocol: 'file://', 'http://'
+const char* ScanPathProtocol(const char* url)
+{    
+    UInt32 charVal = UTF8Util::DecodeNextChar(&url);
+    UInt32 charVal2;
+   
+    while (charVal != 0)
+    {
+        // Treat a colon followed by a slash as absolute.
+        if (charVal == ':')
+        {
+            charVal2 = UTF8Util::DecodeNextChar(&url);
+            charVal  = UTF8Util::DecodeNextChar(&url);
+            if ((charVal == '/') && (charVal2 == '\\'))
+                return url;
+        }
+        charVal = UTF8Util::DecodeNextChar(&url);
+    }
+    return 0;
+}
+
+
+//--------------------------------------------------------------------
+// ***** String Path API implementation
+
+bool String::HasAbsolutePath(const char* url)
+{
+    // Absolute paths can star with:
+    //  - protocols:        'file://', 'http://'
+    //  - windows drive:    'c:\'
+    //  - UNC share name:   '\\share'
+    //  - unix root         '/'
+
+    // On the other hand, relative paths are:
+    //  - directory:        'directory/file'
+    //  - this directory:   './file'
+    //  - parent directory: '../file'
+    // 
+    // For now, we don't parse '.' or '..' out, but instead let it be concatenated
+    // to string and let the OS figure it out. This, however, is not good for file
+    // name matching in library/etc, so it should be improved.
+
+    if (!url || !*url)
+        return true; // Treat empty strings as absolute.    
+
+    UInt32 charVal = UTF8Util::DecodeNextChar(&url);
+
+    // Fist character of '/' or '\\' means absolute url.
+    if ((charVal == '/') || (charVal == '\\'))
+        return true;
+
+    while (charVal != 0)
+    {
+        // Treat a colon followed by a slash as absolute.
+        if (charVal == ':')
+        {
+            charVal = UTF8Util::DecodeNextChar(&url);
+            // Protocol or windows drive. Absolute.
+            if ((charVal == '/') || (charVal == '\\'))
+                return true;
+        }
+        else if ((charVal == '/') || (charVal == '\\'))
+        {
+            // Not a first character (else 'if' above the loop would have caught it).
+            // Must be a relative url.
+            break;
+        }
+
+        charVal = UTF8Util::DecodeNextChar(&url);
+    }
+
+    // We get here for relative paths.
+    return false;    
+}
+
+
+bool String::HasExtension(const char* path)
+{
+    const char* ext = 0;
+    ScanFilePath(path, 0, &ext);
+    return ext != 0;
+}
+bool String::HasProtocol(const char* path)
+{
+    return ScanPathProtocol(path) != 0;
+}
+
+
+String  String::GetPath() const
+{
+    const char* filename = 0;
+    ScanFilePath(ToCStr(), &filename, 0);
+
+    // Technically we can have extra logic somewhere for paths,
+    // such as enforcing protocol and '/' only based on flags,
+    // but we keep it simple for now.
+    return String(ToCStr(), filename ? (filename-ToCStr()) : GetSize());
+}
+
+String  String::GetProtocol() const
+{
+    const char* protocolEnd = ScanPathProtocol(ToCStr());
+    return String(ToCStr(), protocolEnd ? (protocolEnd-ToCStr()) : 0);
+}
+
+String  String::GetFilename() const
+{
+    const char* filename = 0;
+    ScanFilePath(ToCStr(), &filename, 0);
+    return String(filename);
+}
+String  String::GetExtension() const
+{
+    const char* ext = 0;
+    ScanFilePath(ToCStr(), 0, &ext);
+    return String(ext);
+}
+
+void    String::StripExtension()
+{
+    const char* ext = 0;
+    ScanFilePath(ToCStr(), 0, &ext);    
+    if (ext)
+    {
+        *this = String(ToCStr(), ext-ToCStr());
+    }
+}
+
+void    String::StripProtocol()
+{
+    const char* protocol = ScanPathProtocol(ToCStr());
+    if (protocol)
+        AssignString(protocol, OVR_strlen(protocol));
+}
+
+} // OVR
diff --git a/LibOVR/Src/Kernel/OVR_SysFile.cpp b/LibOVR/Src/Kernel/OVR_SysFile.cpp
new file mode 100644
index 0000000..604527a
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_SysFile.cpp
@@ -0,0 +1,138 @@
+/**************************************************************************
+
+Filename    :   OVR_SysFile.cpp
+Content     :   File wrapper class implementation (Win32)
+
+Created     :   April 5, 1999
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+**************************************************************************/
+
+#define  GFILE_CXX
+
+// Standard C library (Captain Obvious guarantees!)
+#include <stdio.h>
+
+#include "OVR_SysFile.h"
+#include "OVR_Log.h"
+
+namespace OVR {
+
+// This is - a dummy file that fails on all calls.
+
+class UnopenedFile : public File
+{
+public:
+    UnopenedFile()  { }
+    ~UnopenedFile() { }
+
+    virtual const char* GetFilePath()               { return 0; }
+
+    // ** File Information
+    virtual bool        IsValid()                   { return 0; }
+    virtual bool        IsWritable()                { return 0; }
+
+    // Return position / file size
+    virtual int         Tell()                      { return 0; }
+    virtual SInt64      LTell()                     { return 0; }
+    virtual int         GetLength()                 { return 0; }
+    virtual SInt64      LGetLength()                { return 0; }
+
+//  virtual bool        Stat(FileStats *pfs)        { return 0; }
+    virtual int         GetErrorCode()              { return Error_FileNotFound; }
+
+    // ** Stream implementation & I/O
+    virtual int         Write(const UByte *pbuffer, int numBytes)     { return -1; OVR_UNUSED2(pbuffer, numBytes); }
+    virtual int         Read(UByte *pbuffer, int numBytes)            { return -1; OVR_UNUSED2(pbuffer, numBytes); }
+    virtual int         SkipBytes(int numBytes)                       { return 0;  OVR_UNUSED(numBytes); }
+    virtual int         BytesAvailable()                              { return 0; }
+    virtual bool        Flush()                                       { return 0; }
+    virtual int         Seek(int offset, int origin)                  { return -1; OVR_UNUSED2(offset, origin); }
+    virtual SInt64      LSeek(SInt64 offset, int origin)              { return -1; OVR_UNUSED2(offset, origin); }
+    
+    virtual int         CopyFromStream(File *pstream, int byteSize)   { return -1; OVR_UNUSED2(pstream, byteSize); }
+    virtual bool        Close()                                       { return 0; }    
+};
+
+
+
+// ***** System File
+
+// System file is created to access objects on file system directly
+// This file can refer directly to path
+
+// ** Constructor
+SysFile::SysFile() : DelegatedFile(0)
+{
+    pFile = *new UnopenedFile;
+}
+
+Ptr<File> FileFILEOpen(const String& path, int flags, int mode);
+
+// Opens a file
+SysFile::SysFile(const String& path, int flags, int mode) : DelegatedFile(0)
+{
+    Open(path, flags, mode);
+}
+
+
+// ** Open & management
+// Will fail if file's already open
+bool SysFile::Open(const String& path, int flags, int mode)
+{
+    pFile = FileFILEOpen(path, flags, mode);
+    if ((!pFile) || (!pFile->IsValid()))
+    {
+        pFile = *new UnopenedFile;
+        OVR_DEBUG_LOG(("Failed to open file: %s", path.ToCStr()));
+        return 0;
+    }
+    //pFile = *OVR_NEW DelegatedFile(pFile); // MA Testing
+    if (flags & Open_Buffered)
+        pFile = *new BufferedFile(pFile);
+    return 1;
+}
+
+
+// ** Overrides
+
+int SysFile::GetErrorCode()
+{
+    return pFile ? pFile->GetErrorCode() : Error_FileNotFound;
+}
+
+
+// Overrides to provide re-open support
+bool SysFile::IsValid()
+{
+    return pFile && pFile->IsValid();
+}
+bool SysFile::Close()
+{
+    if (IsValid())
+    {
+        DelegatedFile::Close();
+        pFile = *new UnopenedFile;
+        return 1;
+    }
+    return 0;
+}
+
+} // OVR
diff --git a/LibOVR/Src/Kernel/OVR_SysFile.h b/LibOVR/Src/Kernel/OVR_SysFile.h
new file mode 100644
index 0000000..61ad6e8
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_SysFile.h
@@ -0,0 +1,104 @@
+/************************************************************************************
+
+PublicHeader:   Kernel
+Filename    :   OVR_SysFile.h
+Content     :   Header for all internal file management - functions and structures
+                to be inherited by OS specific subclasses.
+Created     :   September 19, 2012
+Notes       : 
+
+Notes       :   errno may not be preserved across use of GBaseFile member functions
+            :   Directories cannot be deleted while files opened from them are in use
+                (For the GetFullName function)
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_SysFile_h
+#define OVR_SysFile_h
+
+#include "OVR_File.h"
+
+namespace OVR {
+
+// ***** Declared classes
+class   SysFile;
+
+//-----------------------------------------------------------------------------------
+// *** File Statistics
+
+// This class contents are similar to _stat, providing
+// creation, modify and other information about the file.
+struct FileStat
+{
+    // No change or create time because they are not available on most systems
+    SInt64  ModifyTime;
+    SInt64  AccessTime;
+    SInt64  FileSize;
+
+    bool operator== (const FileStat& stat) const
+    {
+        return ( (ModifyTime == stat.ModifyTime) &&
+                 (AccessTime == stat.AccessTime) &&
+                 (FileSize == stat.FileSize) );
+    }
+};
+
+//-----------------------------------------------------------------------------------
+// *** System File
+
+// System file is created to access objects on file system directly
+// This file can refer directly to path.
+// System file can be open & closed several times; however, such use is not recommended
+// This class is realy a wrapper around an implementation of File interface for a 
+// particular platform.
+
+class SysFile : public DelegatedFile
+{
+protected:
+  SysFile(const SysFile &source) : DelegatedFile () { OVR_UNUSED(source); }
+public:
+
+    // ** Constructor
+    SysFile();
+    // Opens a file
+    SysFile(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite); 
+
+    // ** Open & management 
+    bool  Open(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite);
+        
+    OVR_FORCE_INLINE bool  Create(const String& path, int mode = Mode_ReadWrite)
+    { return Open(path, Open_ReadWrite|Open_Create, mode); }
+
+    // Helper function: obtain file statistics information. In OVR, this is used to detect file changes.
+    // Return 0 if function failed, most likely because the file doesn't exist.
+    static bool OVR_CDECL GetFileStat(FileStat* pfileStats, const String& path);
+    
+    // ** Overrides
+    // Overridden to provide re-open support
+    virtual int   GetErrorCode();
+
+    virtual bool  IsValid();
+
+    virtual bool  Close();    
+};
+
+} // Namespace OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_System.cpp b/LibOVR/Src/Kernel/OVR_System.cpp
new file mode 100644
index 0000000..3144ade
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_System.cpp
@@ -0,0 +1,81 @@
+/************************************************************************************
+
+Filename    :   OVR_System.cpp
+Content     :   General kernel initialization/cleanup, including that
+                of the memory allocator.
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_System.h"
+#include "OVR_Threads.h"
+#include "OVR_Timer.h"
+
+namespace OVR {
+
+// *****  OVR::System Implementation
+
+// Initializes System core, installing allocator.
+void System::Init(Log* log, Allocator *palloc)
+{    
+    if (!Allocator::GetInstance())
+    {
+        Log::SetGlobalLog(log);
+        Timer::initializeTimerSystem();
+        Allocator::setInstance(palloc);
+    }
+    else
+    {
+        OVR_DEBUG_LOG(("System::Init failed - duplicate call."));
+    }
+}
+
+void System::Destroy()
+{    
+    if (Allocator::GetInstance())
+    {
+        // Wait for all threads to finish; this must be done so that memory
+        // allocator and all destructors finalize correctly.
+#ifdef OVR_ENABLE_THREADS
+        Thread::FinishAllThreads();
+#endif
+
+        // Shutdown heap and destroy SysAlloc singleton, if any.
+        Allocator::GetInstance()->onSystemShutdown();
+        Allocator::setInstance(0);
+
+        Timer::shutdownTimerSystem();
+        Log::SetGlobalLog(Log::GetDefaultLog());
+    }
+    else
+    {
+        OVR_DEBUG_LOG(("System::Destroy failed - System not initialized."));
+    }
+}
+
+// Returns 'true' if system was properly initialized.
+bool System::IsInitialized()
+{
+    return Allocator::GetInstance() != 0;
+}
+
+} // OVR
+
diff --git a/LibOVR/Src/Kernel/OVR_System.h b/LibOVR/Src/Kernel/OVR_System.h
new file mode 100644
index 0000000..253fe19
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_System.h
@@ -0,0 +1,78 @@
+/************************************************************************************
+
+PublicHeader:   OVR
+Filename    :   OVR_System.h
+Content     :   General kernel initialization/cleanup, including that
+                of the memory allocator.
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_System_h
+#define OVR_System_h
+
+#include "OVR_Allocator.h"
+#include "OVR_Log.h"
+
+namespace OVR {
+
+// ***** System Core Initialization class
+
+// System initialization must take place before any other OVR_Kernel objects are used;
+// this is done my calling System::Init(). Among other things, this is necessary to
+// initialize the memory allocator. Similarly, System::Destroy must be
+// called before program exist for proper cleanup. Both of these tasks can be achieved by
+// simply creating System object first, allowing its constructor/destructor do the work.
+
+// TBD: Require additional System class for Oculus Rift API?
+
+class System
+{
+public:
+
+    // System constructor expects allocator to be specified, if it is being substituted.
+    System(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
+           Allocator* palloc = DefaultAllocator::InitSystemSingleton())
+    {
+        Init(log, palloc);
+    }
+
+    ~System()
+    {
+        Destroy();
+    }
+
+    // Returns 'true' if system was properly initialized.
+    static bool OVR_CDECL IsInitialized();
+
+    // Initializes System core.  Users can override memory implementation by passing
+    // a different Allocator here.
+    static void OVR_CDECL Init(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
+                               Allocator *palloc = DefaultAllocator::InitSystemSingleton());
+
+    // De-initializes System more, finalizing the threading system and destroying
+    // the global memory allocator.
+    static void OVR_CDECL Destroy();    
+};
+
+} // OVR
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_Threads.h b/LibOVR/Src/Kernel/OVR_Threads.h
new file mode 100644
index 0000000..307f107
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Threads.h
@@ -0,0 +1,407 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_Threads.h
+Content     :   Contains thread-related (safe) functionality
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+#ifndef OVR_Threads_h
+#define OVR_Threads_h
+
+#include "OVR_Types.h"
+#include "OVR_Atomic.h"
+#include "OVR_RefCount.h"
+#include "OVR_Array.h"
+
+// Defines the infinite wait delay timeout
+#define OVR_WAIT_INFINITE 0xFFFFFFFF
+
+// To be defined in the project configuration options
+#ifdef OVR_ENABLE_THREADS
+
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ****** Declared classes
+
+// Declared with thread support only
+class   Mutex;
+class   WaitCondition;
+class   Event;
+// Implementation forward declarations
+class MutexImpl;
+class WaitConditionImpl;
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Mutex
+
+// Mutex class represents a system Mutex synchronization object that provides access 
+// serialization between different threads, allowing one thread mutually exclusive access 
+// to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition.
+
+class Mutex
+{
+    friend class WaitConditionImpl;    
+    friend class MutexImpl;
+
+    MutexImpl  *pImpl; 
+
+public:
+    // Constructor/destructor
+    Mutex(bool recursive = 1);
+    ~Mutex();
+
+    // Locking functions
+    void  DoLock();
+    bool  TryLock();
+    void  Unlock();
+
+    // Returns 1 if the mutes is currently locked by another thread
+    // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired. 
+    bool  IsLockedByAnotherThread();
+    
+    // Locker class; Used for automatic locking of a mutex withing scope    
+    class Locker
+    {
+    public:
+        Mutex *pMutex;
+        Locker(Mutex *pmutex)
+            { pMutex = pmutex; pMutex->DoLock(); }
+        ~Locker()
+            { pMutex->Unlock(); }
+    };
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** WaitCondition
+
+/*
+    WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor.
+    Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that
+    call Notify() or NotifyAll().
+
+    The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then 
+    starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same
+    resource, this ensures that any condition checked for while the mutex was locked does not change before
+    the wait on the condition is actually initiated.
+*/
+
+class WaitCondition
+{
+    friend class WaitConditionImpl;
+    // Internal implementation structure
+    WaitConditionImpl *pImpl;
+
+public:
+    // Constructor/destructor
+    WaitCondition();
+    ~WaitCondition();
+
+    // Release mutex and wait for condition. The mutex is re-aquired after the wait.
+    // Delay is specified in milliseconds (1/1000 of a second).
+    bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
+
+    // Notify a condition, releasing at one object waiting
+    void    Notify();
+    // Notify a condition, releasing all objects waiting
+    void    NotifyAll();
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** Event
+
+// Event is a wait-able synchronization object similar to Windows event.
+// Event can be waited on until it's signaled by another thread calling
+// either SetEvent or PulseEvent.
+
+class Event
+{
+    // Event state, its mutex and the wait condition
+    volatile bool   State;
+    volatile bool   Temporary;  
+    mutable Mutex   StateMutex;
+    WaitCondition   StateWaitCondition;
+
+    void updateState(bool newState, bool newTemp, bool mustNotify);
+
+public:    
+    Event(bool setInitially = 0) : State(setInitially), Temporary(false) { }
+    ~Event() { }
+
+    // Wait on an event condition until it is set
+    // Delay is specified in milliseconds (1/1000 of a second).
+    bool  Wait(unsigned delay = OVR_WAIT_INFINITE);
+    
+    // Set an event, releasing objects waiting on it
+    void  SetEvent()
+    { updateState(true, false, true); }
+
+    // Reset an event, un-signaling it
+    void  ResetEvent()
+    { updateState(false, false, false); }
+
+    // Set and then reset an event once a waiter is released.
+    // If threads are already waiting, they will be notified and released
+    // If threads are not waiting, the event is set until the first thread comes in
+    void  PulseEvent()
+    { updateState(true, true, true); }
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** Thread class
+
+// ThreadId uniquely identifies a thread; returned by GetCurrentThreadId() and
+// Thread::GetThreadId.
+typedef void* ThreadId;
+
+
+// *** Thread flags
+
+// Indicates that the thread is has been started, i.e. Start method has been called, and threads
+// OnExit() method has not yet been called/returned.
+#define OVR_THREAD_STARTED               0x01
+// This flag is set once the thread has ran, and finished.
+#define OVR_THREAD_FINISHED              0x02
+// This flag is set temporarily if this thread was started suspended. It is used internally.
+#define OVR_THREAD_START_SUSPENDED       0x08
+// This flag is used to ask a thread to exit. Message driven threads will usually check this flag
+// and finish once it is set.
+#define OVR_THREAD_EXIT                  0x10
+
+
+class Thread : public RefCountBase<Thread>
+{ // NOTE: Waitable must be the first base since it implements RefCountImpl.    
+
+public:
+
+    // *** Callback functions, can be used instead of overriding Run
+
+    // Run function prototypes.    
+    // Thread function and user handle passed to it, executed by the default
+    // Thread::Run implementation if not null.
+    typedef int (*ThreadFn)(Thread *pthread, void* h);
+    
+    // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried
+    ThreadFn    ThreadFunction;    
+    // User handle passes to a thread
+    void*       UserHandle;
+
+    // Thread state to start a thread with
+    enum ThreadState
+    {
+        NotRunning  = 0,
+        Running     = 1,
+        Suspended   = 2
+    };
+
+    // Thread priority
+    enum ThreadPriority
+    {
+        CriticalPriority,
+        HighestPriority,
+        AboveNormalPriority,
+        NormalPriority,
+        BelowNormalPriority,
+        LowestPriority,
+        IdlePriority,
+    };
+
+    // Thread constructor parameters
+    struct CreateParams
+    {
+        CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024, 
+                     int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority)
+                     : threadFunction(func), userHandle(hand), stackSize(ssize), 
+                       processor(proc), initialState(state), priority(prior) {}
+        ThreadFn       threadFunction;   // Thread function
+        void*          userHandle;       // User handle passes to a thread
+        UPInt          stackSize;        // Thread stack size
+        int            processor;        // Thread hardware processor
+        ThreadState    initialState;     // 
+        ThreadPriority priority;         // Thread priority
+    };
+
+    // *** Constructors
+
+    // A default constructor always creates a thread in NotRunning state, because
+    // the derived class has not yet been initialized. The derived class can call Start explicitly.
+    // "processor" parameter specifies which hardware processor this thread will be run on. 
+    // -1 means OS decides this. Implemented only on Win32
+    Thread(UPInt stackSize = 128 * 1024, int processor = -1);
+    // Constructors that initialize the thread with a pointer to function.
+    // An option to start a thread is available, but it should not be used if classes are derived from Thread.
+    // "processor" parameter specifies which hardware processor this thread will be run on. 
+    // -1 means OS decides this. Implemented only on Win32
+    Thread(ThreadFn threadFunction, void*  userHandle = 0, UPInt stackSize = 128 * 1024,
+           int processor = -1, ThreadState initialState = NotRunning);
+    // Constructors that initialize the thread with a create parameters structure.
+    explicit Thread(const CreateParams& params);
+
+    // Destructor.
+    virtual ~Thread();
+
+    // Waits for all Threads to finish; should be called only from the root
+    // application thread. Once this function returns, we know that all other
+    // thread's references to Thread object have been released.
+    static  void OVR_CDECL FinishAllThreads();
+
+
+    // *** Overridable Run function for thread processing
+
+    // - returning from this method will end the execution of the thread
+    // - return value is usually 0 for success 
+    virtual int   Run();
+    // Called after return/exit function
+    virtual void  OnExit();
+
+
+    // *** Thread management
+
+    // Starts the thread if its not already running
+    // - internally sets up the threading and calls Run()
+    // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing
+    // - returns the exit code
+    virtual bool  Start(ThreadState initialState = Running);
+
+    // Quits with an exit code
+    virtual void  Exit(int exitCode=0);
+
+    // Suspend the thread until resumed
+    // Returns 1 for success, 0 for failure.
+    bool  Suspend();
+    // Resumes currently suspended thread
+    // Returns 1 for success, 0 for failure.
+    bool  Resume();
+
+    // Static function to return a pointer to the current thread
+    //static Thread* GetThread();
+
+
+    // *** Thread status query functions
+
+    bool          GetExitFlag() const;
+    void          SetExitFlag(bool exitFlag);
+
+    // Determines whether the thread was running and is now finished
+    bool          IsFinished() const;
+    // Determines if the thread is currently suspended
+    bool          IsSuspended() const;
+    // Returns current thread state
+    ThreadState   GetThreadState() const;
+
+    // Returns the number of available CPUs on the system 
+    static int    GetCPUCount();
+
+    // Returns the thread exit code. Exit code is initialized to 0,
+    // and set to the return value if Run function after the thread is finished.
+    inline int    GetExitCode() const { return ExitCode; }
+    // Returns an OS handle 
+#if defined(OVR_OS_WIN32)
+    void*          GetOSHandle() const { return ThreadHandle; }
+#else
+    pthread_t      GetOSHandle() const { return ThreadHandle; }
+#endif
+
+#if defined(OVR_OS_WIN32)
+    ThreadId       GetThreadId() const { return IdValue; }
+#else
+    ThreadId       GetThreadId() const { return (ThreadId)GetOSHandle(); }
+#endif
+
+    static int      GetOSPriority(ThreadPriority);
+    // *** Sleep
+
+    // Sleep secs seconds
+    static bool    Sleep(unsigned secs);
+    // Sleep msecs milliseconds
+    static bool    MSleep(unsigned msecs);
+
+
+    // *** Debugging functionality
+#if defined(OVR_OS_WIN32)
+    virtual void    SetThreadName( const char* name );
+#else
+    virtual void    SetThreadName( const char* name ) { OVR_UNUSED(name); }
+#endif
+
+private:
+#if defined(OVR_OS_WIN32)
+    friend unsigned WINAPI Thread_Win32StartFn(void *pthread);
+
+#else
+    friend void *Thread_PthreadStartFn(void * phandle);
+
+    static int            InitAttr;
+    static pthread_attr_t Attr;
+#endif
+
+protected:    
+    // Thread state flags
+    AtomicInt<UInt32>   ThreadFlags;
+    AtomicInt<SInt32>   SuspendCount;
+    UPInt               StackSize;
+
+    // Hardware processor which this thread is running on.
+    int            Processor;
+    ThreadPriority Priority;
+
+#if defined(OVR_OS_WIN32)
+    void*               ThreadHandle;
+    volatile ThreadId   IdValue;
+
+    // System-specific cleanup function called from destructor
+    void                CleanupSystemThread();
+
+#else
+    pthread_t           ThreadHandle;
+#endif
+
+    // Exit code of the thread, as returned by Run.
+    int                 ExitCode;
+
+    // Internal run function.
+    int                 PRun();    
+    // Finishes the thread and releases internal reference to it.
+    void                FinishAndRelease();
+
+    void                Init(const CreateParams& params);
+
+    // Protected copy constructor
+    Thread(const Thread &source) : RefCountBase<Thread>() { OVR_UNUSED(source); }
+
+};
+
+// Returns the unique Id of a thread it is called on, intended for
+// comparison purposes.
+ThreadId GetCurrentThreadId();
+
+
+} // OVR
+
+#endif // OVR_ENABLE_THREADS
+#endif // OVR_Threads_h
diff --git a/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp b/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp
new file mode 100644
index 0000000..da483d5
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_ThreadsPthread.cpp
@@ -0,0 +1,787 @@
+/************************************************************************************
+
+Filename    :   OVR_ThreadsPthread.cpp
+Content     :   
+Created     :   
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_Threads.h"
+#include "OVR_Hash.h"
+
+#ifdef OVR_ENABLE_THREADS
+
+#include "OVR_Timer.h"
+#include "OVR_Log.h"
+
+#include <pthread.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <errno.h>
+
+
+namespace OVR {
+
+// ***** Mutex implementation
+
+
+// *** Internal Mutex implementation structure
+
+class MutexImpl : public NewOverrideBase
+{
+    // System mutex or semaphore
+    pthread_mutex_t   SMutex;
+    bool          Recursive;
+    unsigned      LockCount;
+    pthread_t     LockedBy;
+
+    friend class WaitConditionImpl;
+
+public:
+    // Constructor/destructor
+    MutexImpl(Mutex* pmutex, bool recursive = 1);
+    ~MutexImpl();
+
+    // Locking functions
+    void                DoLock();
+    bool                TryLock();
+    void                Unlock(Mutex* pmutex);
+    // Returns 1 if the mutes is currently locked
+    bool                IsLockedByAnotherThread(Mutex* pmutex);        
+    bool                IsSignaled() const;
+};
+
+pthread_mutexattr_t Lock::RecursiveAttr;
+bool Lock::RecursiveAttrInit = 0;
+
+// *** Constructor/destructor
+MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
+{   
+    OVR_UNUSED(pmutex);
+    Recursive           = recursive;
+    LockCount           = 0;
+
+    if (Recursive)
+    {
+        if (!Lock::RecursiveAttrInit)
+        {
+            pthread_mutexattr_init(&Lock::RecursiveAttr);
+            pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
+            Lock::RecursiveAttrInit = 1;
+        }
+
+        pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
+    }
+    else
+        pthread_mutex_init(&SMutex, 0);
+}
+
+MutexImpl::~MutexImpl()
+{
+    pthread_mutex_destroy(&SMutex);
+}
+
+
+// Lock and try lock
+void MutexImpl::DoLock()
+{
+    while (pthread_mutex_lock(&SMutex))
+        ;
+    LockCount++;
+    LockedBy = pthread_self();
+}
+
+bool MutexImpl::TryLock()
+{
+    if (!pthread_mutex_trylock(&SMutex))
+    {
+        LockCount++;
+        LockedBy = pthread_self();
+        return 1;
+    }
+    
+    return 0;
+}
+
+void MutexImpl::Unlock(Mutex* pmutex)
+{
+    OVR_UNUSED(pmutex);
+    OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
+
+    unsigned lockCount;
+    LockCount--;
+    lockCount = LockCount;
+
+    pthread_mutex_unlock(&SMutex);
+}
+
+bool    MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
+{
+    OVR_UNUSED(pmutex);
+    // There could be multiple interpretations of IsLocked with respect to current thread
+    if (LockCount == 0)
+        return 0;
+    if (pthread_self() != LockedBy)
+        return 1;
+    return 0;
+}
+
+bool    MutexImpl::IsSignaled() const
+{
+    // An mutex is signaled if it is not locked ANYWHERE
+    // Note that this is different from IsLockedByAnotherThread function,
+    // that takes current thread into account
+    return LockCount == 0;
+}
+
+
+// *** Actual Mutex class implementation
+
+Mutex::Mutex(bool recursive)
+{
+    // NOTE: RefCount mode already thread-safe for all waitables.
+    pImpl = new MutexImpl(this, recursive);
+}
+
+Mutex::~Mutex()
+{
+    delete pImpl;
+}
+
+// Lock and try lock
+void Mutex::DoLock()
+{
+    pImpl->DoLock();
+}
+bool Mutex::TryLock()
+{
+    return pImpl->TryLock();
+}
+void Mutex::Unlock()
+{
+    pImpl->Unlock(this);
+}
+bool    Mutex::IsLockedByAnotherThread()
+{
+    return pImpl->IsLockedByAnotherThread(this);
+}
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Event
+
+bool Event::Wait(unsigned delay)
+{
+    Mutex::Locker lock(&StateMutex);
+
+    // Do the correct amount of waiting
+    if (delay == OVR_WAIT_INFINITE)
+    {
+        while(!State)
+            StateWaitCondition.Wait(&StateMutex);
+    }
+    else if (delay)
+    {
+        if (!State)
+            StateWaitCondition.Wait(&StateMutex, delay);
+    }
+
+    bool state = State;
+    // Take care of temporary 'pulsing' of a state
+    if (Temporary)
+    {
+        Temporary   = false;
+        State       = false;
+    }
+    return state;
+}
+
+void Event::updateState(bool newState, bool newTemp, bool mustNotify)
+{
+    Mutex::Locker lock(&StateMutex);
+    State       = newState;
+    Temporary   = newTemp;
+    if (mustNotify)
+        StateWaitCondition.NotifyAll();    
+}
+
+
+
+// ***** Wait Condition Implementation
+
+// Internal implementation class
+class WaitConditionImpl : public NewOverrideBase
+{
+    pthread_mutex_t     SMutex;
+    pthread_cond_t      Condv;
+
+public:
+
+    // Constructor/destructor
+    WaitConditionImpl();
+    ~WaitConditionImpl();
+
+    // Release mutex and wait for condition. The mutex is re-aqured after the wait.
+    bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
+
+    // Notify a condition, releasing at one object waiting
+    void    Notify();
+    // Notify a condition, releasing all objects waiting
+    void    NotifyAll();
+};
+
+
+WaitConditionImpl::WaitConditionImpl()
+{
+    pthread_mutex_init(&SMutex, 0);
+    pthread_cond_init(&Condv, 0);
+}
+
+WaitConditionImpl::~WaitConditionImpl()
+{
+    pthread_mutex_destroy(&SMutex);
+    pthread_cond_destroy(&Condv);
+}    
+
+bool    WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
+{
+    bool            result = 1;
+    unsigned            lockCount = pmutex->pImpl->LockCount;
+
+    // Mutex must have been locked
+    if (lockCount == 0)
+        return 0;
+
+    pthread_mutex_lock(&SMutex);
+
+    // Finally, release a mutex or semaphore
+    if (pmutex->pImpl->Recursive)
+    {
+        // Release the recursive mutex N times
+        pmutex->pImpl->LockCount = 0;
+        for(unsigned i=0; i<lockCount; i++)
+            pthread_mutex_unlock(&pmutex->pImpl->SMutex);
+    }
+    else
+    {
+        pmutex->pImpl->LockCount = 0;
+        pthread_mutex_unlock(&pmutex->pImpl->SMutex);
+    }
+
+    // Note that there is a gap here between mutex.Unlock() and Wait().
+    // The other mutex protects this gap.
+
+    if (delay == OVR_WAIT_INFINITE)
+        pthread_cond_wait(&Condv,&SMutex);
+    else
+    {
+        timespec ts;
+
+        struct timeval tv;
+        gettimeofday(&tv, 0);
+
+        ts.tv_sec = tv.tv_sec + (delay / 1000);
+        ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
+
+        if (ts.tv_nsec > 999999999)
+        {
+            ts.tv_sec++;
+            ts.tv_nsec -= 1000000000;
+        }
+        int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
+        OVR_ASSERT(r == 0 || r == ETIMEDOUT);
+        if (r)
+            result = 0;
+    }
+
+    pthread_mutex_unlock(&SMutex);
+
+    // Re-aquire the mutex
+    for(unsigned i=0; i<lockCount; i++)
+        pmutex->DoLock(); 
+
+    // Return the result
+    return result;
+}
+
+// Notify a condition, releasing the least object in a queue
+void    WaitConditionImpl::Notify()
+{
+    pthread_mutex_lock(&SMutex);
+    pthread_cond_signal(&Condv);
+    pthread_mutex_unlock(&SMutex);
+}
+
+// Notify a condition, releasing all objects waiting
+void    WaitConditionImpl::NotifyAll()
+{
+    pthread_mutex_lock(&SMutex);
+    pthread_cond_broadcast(&Condv);
+    pthread_mutex_unlock(&SMutex);
+}
+
+
+
+// *** Actual implementation of WaitCondition
+
+WaitCondition::WaitCondition()
+{
+    pImpl = new WaitConditionImpl;
+}
+WaitCondition::~WaitCondition()
+{
+    delete pImpl;
+}
+    
+bool    WaitCondition::Wait(Mutex *pmutex, unsigned delay)
+{
+    return pImpl->Wait(pmutex, delay);
+}
+// Notification
+void    WaitCondition::Notify()
+{
+    pImpl->Notify();
+}
+void    WaitCondition::NotifyAll()
+{
+    pImpl->NotifyAll();
+}
+
+
+// ***** Current thread
+
+// Per-thread variable
+/*
+static __thread Thread* pCurrentThread = 0;
+
+// Static function to return a pointer to the current thread
+void    Thread::InitCurrentThread(Thread *pthread)
+{
+    pCurrentThread = pthread;
+}
+
+// Static function to return a pointer to the current thread
+Thread*    Thread::GetThread()
+{
+    return pCurrentThread;
+}
+*/
+
+
+// *** Thread constructors.
+
+Thread::Thread(UPInt stackSize, int processor)
+{
+    // NOTE: RefCount mode already thread-safe for all Waitable objects.
+    CreateParams params;
+    params.stackSize = stackSize;
+    params.processor = processor;
+    Init(params);
+}
+
+Thread::Thread(Thread::ThreadFn threadFunction, void*  userHandle, UPInt stackSize,
+                 int processor, Thread::ThreadState initialState)
+{
+    CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
+    Init(params);
+}
+
+Thread::Thread(const CreateParams& params)
+{
+    Init(params);
+}
+
+void Thread::Init(const CreateParams& params)
+{
+    // Clear the variables    
+    ThreadFlags     = 0;
+    ThreadHandle    = 0;
+    ExitCode        = 0;
+    SuspendCount    = 0;
+    StackSize       = params.stackSize;
+    Processor       = params.processor;
+    Priority        = params.priority;
+
+    // Clear Function pointers
+    ThreadFunction  = params.threadFunction;
+    UserHandle      = params.userHandle;
+    if (params.initialState != NotRunning)
+        Start(params.initialState);
+}
+
+Thread::~Thread()
+{
+    // Thread should not running while object is being destroyed,
+    // this would indicate ref-counting issue.
+    //OVR_ASSERT(IsRunning() == 0);
+
+    // Clean up thread.    
+    ThreadHandle = 0;
+}
+
+
+
+// *** Overridable User functions.
+
+// Default Run implementation
+int    Thread::Run()
+{
+    // Call pointer to function, if available.    
+    return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
+}
+void    Thread::OnExit()
+{   
+}
+
+
+// Finishes the thread and releases internal reference to it.
+void    Thread::FinishAndRelease()
+{
+    // Note: thread must be US.
+    ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
+    ThreadFlags |= OVR_THREAD_FINISHED;
+
+    // Release our reference; this is equivalent to 'delete this'
+    // from the point of view of our thread.
+    Release();
+}
+
+
+
+// *** ThreadList - used to track all created threads
+
+class ThreadList : public NewOverrideBase
+{
+    //------------------------------------------------------------------------
+    struct ThreadHashOp
+    {
+        size_t operator()(const Thread* ptr)
+        {
+            return (((size_t)ptr) >> 6) ^ (size_t)ptr;
+        }
+    };
+
+    HashSet<Thread*, ThreadHashOp>        ThreadSet;
+    Mutex                                 ThreadMutex;
+    WaitCondition                         ThreadsEmpty;
+    // Track the root thread that created us.
+    pthread_t                             RootThreadId;
+
+    static ThreadList* volatile pRunningThreads;
+
+    void addThread(Thread *pthread)
+    {
+        Mutex::Locker lock(&ThreadMutex);
+        ThreadSet.Add(pthread);
+    }
+
+    void removeThread(Thread *pthread)
+    {
+        Mutex::Locker lock(&ThreadMutex);
+        ThreadSet.Remove(pthread);
+        if (ThreadSet.GetSize() == 0)
+            ThreadsEmpty.Notify();
+    }
+
+    void finishAllThreads()
+    {
+        // Only original root thread can call this.
+        OVR_ASSERT(pthread_self() == RootThreadId);
+
+        Mutex::Locker lock(&ThreadMutex);
+        while (ThreadSet.GetSize() != 0)
+            ThreadsEmpty.Wait(&ThreadMutex);
+    }
+
+public:
+
+    ThreadList()
+    {
+        RootThreadId = pthread_self();
+    }
+    ~ThreadList() { }
+
+
+    static void AddRunningThread(Thread *pthread)
+    {
+        // Non-atomic creation ok since only the root thread
+        if (!pRunningThreads)
+        {
+            pRunningThreads = new ThreadList;
+            OVR_ASSERT(pRunningThreads);
+        }
+        pRunningThreads->addThread(pthread);
+    }
+
+    // NOTE: 'pthread' might be a dead pointer when this is
+    // called so it should not be accessed; it is only used
+    // for removal.
+    static void RemoveRunningThread(Thread *pthread)
+    {
+        OVR_ASSERT(pRunningThreads);        
+        pRunningThreads->removeThread(pthread);
+    }
+
+    static void FinishAllThreads()
+    {
+        // This is ok because only root thread can wait for other thread finish.
+        if (pRunningThreads)
+        {           
+            pRunningThreads->finishAllThreads();
+            delete pRunningThreads;
+            pRunningThreads = 0;
+        }        
+    }
+};
+
+// By default, we have no thread list.
+ThreadList* volatile ThreadList::pRunningThreads = 0;
+
+
+// FinishAllThreads - exposed publicly in Thread.
+void Thread::FinishAllThreads()
+{
+    ThreadList::FinishAllThreads();
+}
+
+// *** Run override
+
+int    Thread::PRun()
+{
+    // Suspend us on start, if requested
+    if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
+    {
+        Suspend();
+        ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
+    }
+
+    // Call the virtual run function
+    ExitCode = Run();    
+    return ExitCode;
+}
+
+
+
+
+// *** User overridables
+
+bool    Thread::GetExitFlag() const
+{
+    return (ThreadFlags & OVR_THREAD_EXIT) != 0;
+}       
+
+void    Thread::SetExitFlag(bool exitFlag)
+{
+    // The below is atomic since ThreadFlags is AtomicInt.
+    if (exitFlag)
+        ThreadFlags |= OVR_THREAD_EXIT;
+    else
+        ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
+}
+
+
+// Determines whether the thread was running and is now finished
+bool    Thread::IsFinished() const
+{
+    return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
+}
+// Determines whether the thread is suspended
+bool    Thread::IsSuspended() const
+{   
+    return SuspendCount > 0;
+}
+// Returns current thread state
+Thread::ThreadState Thread::GetThreadState() const
+{
+    if (IsSuspended())
+        return Suspended;    
+    if (ThreadFlags & OVR_THREAD_STARTED)
+        return Running;    
+    return NotRunning;
+}
+/*
+static const char* mapsched_policy(int policy)
+{
+    switch(policy)
+    {
+    case SCHED_OTHER:
+        return "SCHED_OTHER";
+    case SCHED_RR:
+        return "SCHED_RR";
+    case SCHED_FIFO:
+        return "SCHED_FIFO";
+
+    }
+    return "UNKNOWN";
+}
+    int policy;
+    sched_param sparam;
+    pthread_getschedparam(pthread_self(), &policy, &sparam);
+    int max_prior = sched_get_priority_max(policy);
+    int min_prior = sched_get_priority_min(policy);
+    printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior);
+#include <stdio.h>
+*/
+// ***** Thread management
+
+// The actual first function called on thread start
+void* Thread_PthreadStartFn(void* phandle)
+{
+    Thread* pthread = (Thread*)phandle;
+    int     result = pthread->PRun();
+    // Signal the thread as done and release it atomically.
+    pthread->FinishAndRelease();
+    // At this point Thread object might be dead; however we can still pass
+    // it to RemoveRunningThread since it is only used as a key there.   
+    ThreadList::RemoveRunningThread(pthread);
+    return reinterpret_cast<void*>(result);
+}
+
+int Thread::InitAttr = 0;
+pthread_attr_t Thread::Attr; 
+
+/* static */
+int Thread::GetOSPriority(ThreadPriority p)
+//static inline int MapToSystemPrority(Thread::ThreadPriority p)
+{
+    OVR_UNUSED(p);
+    return -1;
+}
+
+bool    Thread::Start(ThreadState initialState)
+{
+    if (initialState == NotRunning)
+        return 0;
+    if (GetThreadState() != NotRunning)
+    {
+        OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
+        return 0;
+    }
+
+    if (!InitAttr)
+    {
+        pthread_attr_init(&Attr);
+        pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
+        pthread_attr_setstacksize(&Attr, 128 * 1024);
+        sched_param sparam;
+        sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
+        pthread_attr_setschedparam(&Attr, &sparam);
+        InitAttr = 1;
+    }
+
+    ExitCode        = 0;
+    SuspendCount    = 0;
+    ThreadFlags     = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
+
+    // AddRef to us until the thread is finished
+    AddRef();
+    ThreadList::AddRunningThread(this);
+
+    int result;
+    if (StackSize != 128 * 1024 || Priority != NormalPriority)
+    {
+        pthread_attr_t attr;
+
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+        pthread_attr_setstacksize(&attr, StackSize);
+        sched_param sparam;
+        sparam.sched_priority = Thread::GetOSPriority(Priority);
+        pthread_attr_setschedparam(&attr, &sparam);
+        result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
+        pthread_attr_destroy(&attr);
+    }
+    else
+        result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
+
+    if (result)
+    {
+        ThreadFlags = 0;
+        Release();
+        ThreadList::RemoveRunningThread(this);
+        return 0;
+    }
+    return 1;
+}
+
+
+// Suspend the thread until resumed
+bool    Thread::Suspend()
+{
+    OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
+    return 0;
+}
+
+// Resumes currently suspended thread
+bool    Thread::Resume()
+{
+    return 0;
+}
+
+
+// Quits with an exit code  
+void    Thread::Exit(int exitCode)
+{
+    // Can only exist the current thread
+   // if (GetThread() != this)
+   //     return;
+
+    // Call the virtual OnExit function
+    OnExit();   
+
+    // Signal this thread object as done and release it's references.
+    FinishAndRelease();
+    ThreadList::RemoveRunningThread(this);
+
+    pthread_exit(reinterpret_cast<void*>(exitCode));
+}
+
+ThreadId GetCurrentThreadId()
+{
+    return (void*)pthread_self();
+}
+
+// *** Sleep functions
+
+/* static */
+bool    Thread::Sleep(unsigned secs)
+{
+    sleep(secs);
+    return 1;
+}
+/* static */
+bool    Thread::MSleep(unsigned msecs)
+{
+    usleep(msecs*1000);
+    return 1;
+}
+
+/* static */
+int     Thread::GetCPUCount()
+{
+    return 1;
+}
+
+}
+
+#endif  // OVR_ENABLE_THREADS
diff --git a/LibOVR/Src/Kernel/OVR_Timer.cpp b/LibOVR/Src/Kernel/OVR_Timer.cpp
new file mode 100644
index 0000000..a8de47d
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Timer.cpp
@@ -0,0 +1,287 @@
+/************************************************************************************
+
+Filename    :   OVR_Timer.cpp
+Content     :   Provides static functions for precise timing
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_Timer.h"
+#include "OVR_Log.h"
+
+#if defined (OVR_OS_WIN32)
+#include <windows.h>
+#elif defined(OVR_OS_ANDROID)
+#include <time.h>
+#include <android/log.h>
+
+#else
+#include <sys/time.h>
+#endif
+
+namespace OVR {
+
+// For recorded data playback
+bool   Timer::useFakeSeconds  = false; 
+double Timer::FakeSeconds     = 0;
+
+
+//------------------------------------------------------------------------
+// *** Timer - Platform Independent functions
+
+// Returns global high-resolution application timer in seconds.
+double Timer::GetSeconds()
+{
+	if(useFakeSeconds)
+		return FakeSeconds;
+
+    return double(Timer::GetTicksNanos()) * 0.000000001;
+}
+
+
+#ifndef OVR_OS_WIN32
+
+// Unused on OSs other then Win32.
+void Timer::initializeTimerSystem()
+{
+}
+void Timer::shutdownTimerSystem()
+{
+}
+
+#endif
+
+
+
+//------------------------------------------------------------------------
+// *** Android Specific Timer
+
+#if defined(OVR_OS_ANDROID)
+
+UInt64 Timer::GetTicksNanos()
+{
+    if (useFakeSeconds)
+        return (UInt64) (FakeSeconds * NanosPerSecond);
+
+    // Choreographer vsync timestamp is based on.
+    struct timespec tp;
+    const int       status = clock_gettime(CLOCK_MONOTONIC, &tp);
+
+    if (status != 0)
+    {
+        OVR_DEBUG_LOG(("clock_gettime status=%i", status ));
+    }
+    const UInt64 result = (UInt64)tp.tv_sec * (UInt64)(1000 * 1000 * 1000) + UInt64(tp.tv_nsec);
+    return result;
+}
+
+
+//------------------------------------------------------------------------
+// *** Win32 Specific Timer
+
+#elif defined (OVR_OS_WIN32)
+
+
+// This helper class implements high-resolution wrapper that combines timeGetTime() output
+// with QueryPerformanceCounter.  timeGetTime() is lower precision but drives the high bits,
+// as it's tied to the system clock.
+struct PerformanceTimer
+{
+    PerformanceTimer()
+        : OldMMTimeMs(0), MMTimeWrapCounter(0), PrefFrequency(0),
+          LastResultNanos(0), PerfMinusTicksDeltaNanos(0)
+    { }
+    
+    enum {
+        MMTimerResolutionNanos = 1000000
+    };
+   
+    void    Initialize();
+    void    Shutdown();
+
+    UInt64  GetTimeNanos();
+
+
+    UINT64 getFrequency()
+    {
+        if (PrefFrequency == 0)
+        {
+            LARGE_INTEGER freq;
+            QueryPerformanceFrequency(&freq);
+            PrefFrequency = freq.QuadPart;
+        }        
+        return PrefFrequency;
+    }
+    
+
+    CRITICAL_SECTION TimeCS;
+    // timeGetTime() support with wrap.
+    UInt32          OldMMTimeMs;
+    UInt32          MMTimeWrapCounter;
+    // Cached performance frequency result.
+    UInt64          PrefFrequency;
+    
+    // Computed as (perfCounterNanos - ticksCounterNanos) initially,
+    // and used to adjust timing.
+    UInt64          PerfMinusTicksDeltaNanos;
+    // Last returned value in nanoseconds, to ensure we don't back-step in time.
+    UInt64          LastResultNanos;
+};
+
+PerformanceTimer Win32_PerfTimer;
+
+
+void PerformanceTimer::Initialize()
+{
+    timeBeginPeriod(1);
+    InitializeCriticalSection(&TimeCS);
+    MMTimeWrapCounter = 0;
+    getFrequency();
+}
+
+void PerformanceTimer::Shutdown()
+{
+    DeleteCriticalSection(&TimeCS);
+    timeEndPeriod(1);
+}
+
+UInt64 PerformanceTimer::GetTimeNanos()
+{
+    UInt64          resultNanos;
+    LARGE_INTEGER   li;
+    DWORD           mmTimeMs;
+
+    // On Win32 QueryPerformanceFrequency is unreliable due to SMP and
+    // performance levels, so use this logic to detect wrapping and track
+    // high bits.
+    ::EnterCriticalSection(&TimeCS);
+
+    // Get raw value and perf counter "At the same time".
+    mmTimeMs = timeGetTime();
+    QueryPerformanceCounter(&li);
+
+    if (OldMMTimeMs > mmTimeMs)
+        MMTimeWrapCounter++;
+    OldMMTimeMs = mmTimeMs;
+
+    // Normalize to nanoseconds.
+    UInt64  mmCounterNanos     = ((UInt64(MMTimeWrapCounter) << 32) | mmTimeMs) * 1000000;
+    UInt64  frequency          = getFrequency();
+    UInt64  perfCounterSeconds = UInt64(li.QuadPart) / frequency;
+    UInt64  perfRemainderNanos = ( (UInt64(li.QuadPart) - perfCounterSeconds * frequency) *
+                                   Timer::NanosPerSecond ) / frequency;
+    UInt64  perfCounterNanos   = perfCounterSeconds * Timer::NanosPerSecond + perfRemainderNanos;
+
+    if (PerfMinusTicksDeltaNanos == 0)
+        PerfMinusTicksDeltaNanos = perfCounterNanos - mmCounterNanos;
+ 
+
+    // Compute result before snapping. 
+    //
+    // On first call, this evaluates to:
+    //          resultNanos = mmCounterNanos.    
+    // Next call, assuming no wrap:
+    //          resultNanos = prev_mmCounterNanos + (perfCounterNanos - prev_perfCounterNanos).        
+    // After wrap, this would be:
+    //          resultNanos = snapped(prev_mmCounterNanos +/- 1ms) + (perfCounterNanos - prev_perfCounterNanos).
+    //
+    resultNanos = perfCounterNanos - PerfMinusTicksDeltaNanos;    
+
+    // Snap the range so that resultNanos never moves further apart then its target resolution.
+    // It's better to allow more slack on the high side as timeGetTime() may be updated at sporadically 
+    // larger then 1 ms intervals even when 1 ms resolution is requested.
+    if (resultNanos > (mmCounterNanos + MMTimerResolutionNanos*2))
+    {
+        resultNanos = mmCounterNanos + MMTimerResolutionNanos*2;
+        if (resultNanos < LastResultNanos)
+            resultNanos = LastResultNanos;
+        PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos;
+    }
+    else if (resultNanos < (mmCounterNanos - MMTimerResolutionNanos))
+    {
+        resultNanos = mmCounterNanos - MMTimerResolutionNanos;
+        if (resultNanos < LastResultNanos)
+            resultNanos = LastResultNanos;
+        PerfMinusTicksDeltaNanos = perfCounterNanos - resultNanos;
+    }
+
+    LastResultNanos = resultNanos;
+    ::LeaveCriticalSection(&TimeCS);
+
+	//Tom's addition, to keep precision
+	static UInt64      initial_time = 0;
+	if (!initial_time) initial_time = resultNanos;
+	resultNanos -= initial_time;
+
+
+    return resultNanos;
+}
+
+
+// Delegate to PerformanceTimer.
+UInt64 Timer::GetTicksNanos()
+{
+    if (useFakeSeconds)
+        return (UInt64) (FakeSeconds * NanosPerSecond);
+
+    return Win32_PerfTimer.GetTimeNanos();
+}
+void Timer::initializeTimerSystem()
+{
+    Win32_PerfTimer.Initialize();
+
+}
+void Timer::shutdownTimerSystem()
+{
+    Win32_PerfTimer.Shutdown();
+}
+
+#else   // !OVR_OS_WIN32 && !OVR_OS_ANDROID
+
+
+//------------------------------------------------------------------------
+// *** Standard OS Timer     
+
+UInt64 Timer::GetTicksNanos()
+{
+    if (useFakeSeconds)
+        return (UInt64) (FakeSeconds * NanosPerSecond);
+
+    // TODO: prefer rdtsc when available?
+	UInt64 result;
+
+    // Return microseconds.
+    struct timeval tv;
+
+    gettimeofday(&tv, 0);
+
+    result = (UInt64)tv.tv_sec * 1000000;
+    result += tv.tv_usec;
+
+    return result * 1000;
+}
+
+#endif  // OS-specific
+
+
+
+} // OVR
+
diff --git a/LibOVR/Src/Kernel/OVR_Timer.h b/LibOVR/Src/Kernel/OVR_Timer.h
new file mode 100644
index 0000000..12cba3b
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Timer.h
@@ -0,0 +1,88 @@
+/************************************************************************************
+
+PublicHeader:   OVR
+Filename    :   OVR_Timer.h
+Content     :   Provides static functions for precise timing
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Timer_h
+#define OVR_Timer_h
+
+#include "OVR_Types.h"
+
+namespace OVR {
+    
+//-----------------------------------------------------------------------------------
+// ***** Timer
+
+// Timer class defines a family of static functions used for application
+// timing and profiling.
+
+class Timer
+{
+public:
+    enum {
+        MsPerSecond     = 1000, // Milliseconds in one second.
+        NanosPerSecond  = MsPerSecond * 1000 * 1000,
+        MksPerSecond    = MsPerSecond * 1000
+    };
+
+    // ***** Timing APIs for Application    
+
+    // These APIs should be used to guide animation and other program functions
+    // that require precision.
+
+    // Returns global high-resolution application timer in seconds.
+    static double  OVR_STDCALL GetSeconds();    
+
+    // Returns time in Nanoseconds, using highest possible system resolution.
+    static UInt64  OVR_STDCALL GetTicksNanos();
+
+    // Kept for compatibility.
+    // Returns ticks in milliseconds, as a 32-bit number. May wrap around every 49.2 days.
+    // Use either time difference of two values of GetTicks to avoid wrap-around.
+    static UInt32  OVR_STDCALL GetTicksMs()
+    { return  UInt32(GetTicksNanos() / 1000000); }
+
+    // for recorded data playback
+    static void SetFakeSeconds(double fakeSeconds) 
+    { 
+        FakeSeconds = fakeSeconds; 
+        useFakeSeconds = true; 
+    }
+
+private:
+    friend class System;
+    // System called during program startup/shutdown.
+    static void initializeTimerSystem();
+    static void shutdownTimerSystem();
+
+    // for recorded data playback
+    static double FakeSeconds;
+    static bool   useFakeSeconds; 
+};
+
+
+} // OVR::Timer
+
+#endif
diff --git a/LibOVR/Src/Kernel/OVR_Types.h b/LibOVR/Src/Kernel/OVR_Types.h
new file mode 100644
index 0000000..8f2b3f3
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_Types.h
@@ -0,0 +1,474 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Types.h
+Content     :   Standard library defines and simple types
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Types_H
+#define OVR_Types_H
+
+//-----------------------------------------------------------------------------------
+// ****** Operating System
+//
+// Type definitions exist for the following operating systems: (OVR_OS_x)
+//
+//    WIN32    - Win32 (Windows 95/98/ME and Windows NT/2000/XP)
+//    DARWIN   - Darwin OS (Mac OS X)
+//    LINUX    - Linux
+//    ANDROID  - Android
+//    IPHONE   - iPhone
+
+#if (defined(__APPLE__) && (defined(__GNUC__) ||\
+     defined(__xlC__) || defined(__xlc__))) || defined(__MACOS__)
+#  if (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) || defined(__IPHONE_OS_VERSION_MIN_REQUIRED))
+#    define OVR_OS_IPHONE
+#  else
+#    define OVR_OS_DARWIN
+#    define OVR_OS_MAC
+#  endif
+#elif (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
+#  define OVR_OS_WIN32
+#elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
+#  define OVR_OS_WIN32
+#elif defined(__linux__) || defined(__linux)
+#  define OVR_OS_LINUX
+#else
+#  define OVR_OS_OTHER
+#endif
+
+#if defined(ANDROID)
+#  define OVR_OS_ANDROID
+#endif
+
+
+//-----------------------------------------------------------------------------------
+// ***** CPU Architecture
+//
+// The following CPUs are defined: (OVR_CPU_x)
+//
+//    X86        - x86 (IA-32)
+//    X86_64     - x86_64 (amd64)
+//    PPC        - PowerPC
+//    PPC64      - PowerPC64
+//    MIPS       - MIPS
+//    OTHER      - CPU for which no special support is present or needed
+
+
+#if defined(__x86_64__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
+#  define OVR_CPU_X86_64
+#  define OVR_64BIT_POINTERS
+#elif defined(__i386__) || defined(OVR_OS_WIN32)
+#  define OVR_CPU_X86
+#elif defined(__powerpc64__)
+#  define OVR_CPU_PPC64
+#elif defined(__ppc__)
+#  define OVR_CPU_PPC
+#elif defined(__mips__) || defined(__MIPSEL__)
+#  define OVR_CPU_MIPS
+#elif defined(__arm__)
+#  define OVR_CPU_ARM
+#else
+#  define OVR_CPU_OTHER
+#endif
+
+//-----------------------------------------------------------------------------------
+// ***** Co-Processor Architecture
+//
+// The following co-processors are defined: (OVR_CPU_x)
+//
+//    SSE        - Available on all modern x86 processors.
+//    Altivec    - Available on all modern ppc processors.
+//    Neon       - Available on some armv7+ processors.
+
+#if defined(__SSE__) || defined(OVR_OS_WIN32)
+#  define  OVR_CPU_SSE
+#endif // __SSE__
+
+#if defined( __ALTIVEC__ )
+#  define OVR_CPU_ALTIVEC
+#endif // __ALTIVEC__
+
+#if defined(__ARM_NEON__)
+#  define OVR_CPU_ARM_NEON
+#endif // __ARM_NEON__
+
+
+//-----------------------------------------------------------------------------------
+// ***** Compiler
+//
+//  The following compilers are defined: (OVR_CC_x)
+//
+//     MSVC     - Microsoft Visual C/C++
+//     INTEL    - Intel C++ for Linux / Windows
+//     GNU      - GNU C++
+//     ARM      - ARM C/C++
+
+#if defined(__INTEL_COMPILER)
+// Intel 4.0                    = 400
+// Intel 5.0                    = 500
+// Intel 6.0                    = 600
+// Intel 8.0                    = 800
+// Intel 9.0                    = 900
+#  define OVR_CC_INTEL       __INTEL_COMPILER
+
+#elif defined(_MSC_VER)
+// MSVC 5.0                     = 1100
+// MSVC 6.0                     = 1200
+// MSVC 7.0 (VC2002)            = 1300
+// MSVC 7.1 (VC2003)            = 1310
+// MSVC 8.0 (VC2005)            = 1400
+// MSVC 9.0 (VC2008)            = 1500
+// MSVC 10.0 (VC2010)           = 1600
+// MSVC 11.0 (VC2012)           = 1700
+// MSVC 12.0 (VC2013)           = 1800
+#  define OVR_CC_MSVC        _MSC_VER
+
+#elif defined(__GNUC__)
+#  define OVR_CC_GNU
+
+#elif defined(__CC_ARM)
+#  define OVR_CC_ARM
+
+#else
+#  error "Oculus does not support this Compiler"
+#endif
+
+
+//-----------------------------------------------------------------------------------
+// ***** Compiler Warnings
+
+// Disable MSVC warnings
+#if defined(OVR_CC_MSVC)
+#  pragma warning(disable : 4127)    // Inconsistent dll linkage
+#  pragma warning(disable : 4530)    // Exception handling
+#  if (OVR_CC_MSVC<1300)
+#    pragma warning(disable : 4514)  // Unreferenced inline function has been removed
+#    pragma warning(disable : 4710)  // Function not inlined
+#    pragma warning(disable : 4714)  // _force_inline not inlined
+#    pragma warning(disable : 4786)  // Debug variable name longer than 255 chars
+#  endif // (OVR_CC_MSVC<1300)
+#endif // (OVR_CC_MSVC)
+
+
+
+// *** Linux Unicode - must come before Standard Includes
+
+#ifdef OVR_OS_LINUX
+// Use glibc unicode functions on linux.
+#  ifndef  _GNU_SOURCE
+#    define _GNU_SOURCE
+#  endif
+#endif
+
+//-----------------------------------------------------------------------------------
+// ***** Standard Includes
+//
+#include    <stddef.h>
+#include    <limits.h>
+#include    <float.h>
+
+
+// MSVC Based Memory Leak checking - for now
+#if defined(OVR_CC_MSVC) && defined(OVR_BUILD_DEBUG)
+#  define _CRTDBG_MAP_ALLOC
+#  include <stdlib.h>
+#  include <crtdbg.h>
+
+#if 0
+// Uncomment this to help debug memory leaks under Visual Studio in OVR apps only.
+// This shouldn't be defined in customer releases.
+#  ifndef OVR_DEFINE_NEW
+#    define OVR_DEFINE_NEW new(__FILE__, __LINE__)
+#    define new OVR_DEFINE_NEW
+#  endif
+#endif
+
+#endif
+
+
+//-----------------------------------------------------------------------------------
+// ***** Type definitions for Common Systems
+
+namespace OVR {
+
+typedef char            Char;
+
+// Pointer-sized integer
+typedef size_t          UPInt;
+typedef ptrdiff_t       SPInt;
+
+
+#if defined(OVR_OS_WIN32)
+
+typedef char            SByte;  // 8 bit Integer (Byte)
+typedef unsigned char   UByte;
+typedef short           SInt16; // 16 bit Integer (Word)
+typedef unsigned short  UInt16;
+typedef long            SInt32; // 32 bit Integer
+typedef unsigned long   UInt32;
+typedef __int64         SInt64; // 64 bit Integer (QWord)
+typedef unsigned __int64 UInt64;
+
+ 
+#elif defined(OVR_OS_MAC) || defined(OVR_OS_IPHONE) || defined(OVR_CC_GNU)
+
+typedef int             SByte  __attribute__((__mode__ (__QI__)));
+typedef unsigned int    UByte  __attribute__((__mode__ (__QI__)));
+typedef int             SInt16 __attribute__((__mode__ (__HI__)));
+typedef unsigned int    UInt16 __attribute__((__mode__ (__HI__)));
+typedef int             SInt32 __attribute__((__mode__ (__SI__)));
+typedef unsigned int    UInt32 __attribute__((__mode__ (__SI__)));
+typedef int             SInt64 __attribute__((__mode__ (__DI__)));
+typedef unsigned int    UInt64 __attribute__((__mode__ (__DI__)));
+
+#else
+
+#include <sys/types.h>
+typedef int8_t          SByte;
+typedef uint8_t         UByte;
+typedef int16_t         SInt16;
+typedef uint16_t        UInt16;
+typedef int32_t         SInt32;
+typedef uint32_t        UInt32;
+typedef int64_t         SInt64;
+typedef uint64_t        UInt64;
+
+#endif
+
+
+// ***** BaseTypes Namespace
+
+// BaseTypes namespace is explicitly declared to allow base types to be used
+// by customers directly without other contents of OVR namespace.
+//
+// Its is expected that OVR samples will declare 'using namespace OVR::BaseTypes'
+// to allow using these directly without polluting the target scope with other
+// OVR declarations, such as Ptr<>, String or Mutex.
+namespace BaseTypes
+{
+    using OVR::UPInt;
+    using OVR::SPInt;
+    using OVR::UByte;
+    using OVR::SByte;
+    using OVR::UInt16;
+    using OVR::SInt16;
+    using OVR::UInt32;
+    using OVR::SInt32;
+    using OVR::UInt64;
+    using OVR::SInt64;
+} // OVR::BaseTypes
+
+} // OVR
+
+
+//-----------------------------------------------------------------------------------
+// ***** Macro Definitions
+//
+// We define the following:
+//
+//  OVR_BYTE_ORDER      - Defined to either OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN
+//  OVR_FORCE_INLINE    - Forces inline expansion of function
+//  OVR_ASM             - Assembly language prefix
+//  OVR_STR             - Prefixes string with L"" if building unicode
+// 
+//  OVR_STDCALL         - Use stdcall calling convention (Pascal arg order)
+//  OVR_CDECL           - Use cdecl calling convention (C argument order)
+//  OVR_FASTCALL        - Use fastcall calling convention (registers)
+//
+
+// Byte order constants, OVR_BYTE_ORDER is defined to be one of these.
+#define OVR_LITTLE_ENDIAN       1
+#define OVR_BIG_ENDIAN          2
+
+
+// Force inline substitute - goes before function declaration
+#if defined(OVR_CC_MSVC)
+#  define OVR_FORCE_INLINE  __forceinline
+#elif defined(OVR_CC_GNU)
+#  define OVR_FORCE_INLINE  __attribute__((always_inline)) inline
+#else
+#  define OVR_FORCE_INLINE  inline
+#endif  // OVR_CC_MSVC
+
+
+#if defined(OVR_OS_WIN32)
+    
+    // ***** Win32
+
+    // Byte order
+    #define OVR_BYTE_ORDER    OVR_LITTLE_ENDIAN
+
+    // Calling convention - goes after function return type but before function name
+    #ifdef __cplusplus_cli
+    #  define OVR_FASTCALL      __stdcall
+    #else
+    #  define OVR_FASTCALL      __fastcall
+    #endif
+
+    #define OVR_STDCALL         __stdcall
+    #define OVR_CDECL           __cdecl
+
+
+    // Assembly macros
+    #if defined(OVR_CC_MSVC)
+    #  define OVR_ASM           _asm
+    #else
+    #  define OVR_ASM           asm
+    #endif // (OVR_CC_MSVC)
+
+    #ifdef UNICODE
+    #  define OVR_STR(str)      L##str
+    #else
+    #  define OVR_STR(str)      str
+    #endif // UNICODE
+
+#else
+
+    // **** Standard systems
+
+    #if (defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN))|| \
+        (defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN))
+    #  define OVR_BYTE_ORDER    OVR_BIG_ENDIAN
+    #elif (defined(__ARMEB__) || defined(OVR_CPU_PPC) || defined(OVR_CPU_PPC64))
+    #  define OVR_BYTE_ORDER    OVR_BIG_ENDIAN
+    #else
+    #  define OVR_BYTE_ORDER    OVR_LITTLE_ENDIAN
+    #endif
+    
+    // Assembly macros
+    #define OVR_ASM                  __asm__
+    #define OVR_ASM_PROC(procname)   OVR_ASM
+    #define OVR_ASM_END              OVR_ASM
+    
+    // Calling convention - goes after function return type but before function name
+    #define OVR_FASTCALL
+    #define OVR_STDCALL
+    #define OVR_CDECL
+
+#endif // defined(OVR_OS_WIN32)
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** OVR_DEBUG_BREAK, OVR_ASSERT
+//
+// If not in debug build, macros do nothing
+#ifndef OVR_BUILD_DEBUG
+
+#  define OVR_DEBUG_CODE(c) c
+#  define OVR_DEBUG_BREAK  ((void)0)
+#  define OVR_ASSERT(p)    ((void)0)
+
+#else 
+
+// Microsoft Win32 specific debugging support
+#if defined(OVR_OS_WIN32)
+#  ifdef OVR_CPU_X86
+#    if defined(__cplusplus_cli)
+#      define OVR_DEBUG_BREAK   do { __debugbreak(); } while(0)
+#    elif defined(OVR_CC_GNU)
+#      define OVR_DEBUG_BREAK   do { OVR_ASM("int $3\n\t"); } while(0)
+#    else
+#      define OVR_DEBUG_BREAK   do { OVR_ASM int 3 } while (0)
+#    endif
+#  else
+#    define OVR_DEBUG_BREAK     do { __debugbreak(); } while(0)
+#  endif
+// Unix specific debugging support
+#elif defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)
+#  define OVR_DEBUG_BREAK       do { OVR_ASM("int $3\n\t"); } while(0)
+#else
+#  define OVR_DEBUG_BREAK       do { *((int *) 0) = 1; } while(0)
+#endif
+
+#define OVR_DEBUG_CODE(c)
+
+// This will cause compiler breakpoint
+#define OVR_ASSERT(p)           do { if (!(p))  { OVR_DEBUG_BREAK; } } while(0)
+
+#endif // OVR_BUILD_DEBUG
+
+
+// Compile-time assert; produces compiler error if condition is false
+#define OVR_COMPILER_ASSERT(x)  { int zero = 0; switch(zero) {case 0: case x:;} }
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** OVR_UNUSED - Unused Argument handling
+
+// Macro to quiet compiler warnings about unused parameters/variables.
+#if defined(OVR_CC_GNU)
+#  define   OVR_UNUSED(a)   do {__typeof__ (&a) __attribute__ ((unused)) __tmp = &a; } while(0)
+#else
+#  define   OVR_UNUSED(a)   (a)
+#endif
+
+#define     OVR_UNUSED1(a1) OVR_UNUSED(a1)
+#define     OVR_UNUSED2(a1,a2) OVR_UNUSED(a1); OVR_UNUSED(a2)
+#define     OVR_UNUSED3(a1,a2,a3) OVR_UNUSED2(a1,a2); OVR_UNUSED(a3)
+#define     OVR_UNUSED4(a1,a2,a3,a4) OVR_UNUSED3(a1,a2,a3); OVR_UNUSED(a4)
+#define     OVR_UNUSED5(a1,a2,a3,a4,a5) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED(a5)
+#define     OVR_UNUSED6(a1,a2,a3,a4,a5,a6) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED2(a5,a6)
+#define     OVR_UNUSED7(a1,a2,a3,a4,a5,a6,a7) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED3(a5,a6,a7)
+#define     OVR_UNUSED8(a1,a2,a3,a4,a5,a6,a7,a8) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED4(a5,a6,a7,a8)
+#define     OVR_UNUSED9(a1,a2,a3,a4,a5,a6,a7,a8,a9) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED5(a5,a6,a7,a8,a9)
+
+
+//-----------------------------------------------------------------------------------
+// ***** Configuration Macros
+
+// SF Build type
+#ifdef OVR_BUILD_DEBUG
+#  define OVR_BUILD_STRING  "Debug"
+#else
+#  define OVR_BUILD_STRING  "Release"
+#endif
+
+
+//// Enables SF Debugging information
+//# define OVR_BUILD_DEBUG
+
+// OVR_DEBUG_STATEMENT injects a statement only in debug builds.
+// OVR_DEBUG_SELECT injects first argument in debug builds, second argument otherwise.
+#ifdef OVR_BUILD_DEBUG
+#define OVR_DEBUG_STATEMENT(s)   s
+#define OVR_DEBUG_SELECT(d, nd)  d
+#else
+#define OVR_DEBUG_STATEMENT(s)
+#define OVR_DEBUG_SELECT(d, nd)  nd
+#endif
+
+
+#define OVR_ENABLE_THREADS
+//
+// Prevents OVR from defining new within
+// type macros, so developers can override
+// new using the #define new new(...) trick
+// - used with OVR_DEFINE_NEW macro
+//# define OVR_BUILD_DEFINE_NEW
+//
+
+
+#endif  // OVR_Types_h
diff --git a/LibOVR/Src/Kernel/OVR_UTF8Util.cpp b/LibOVR/Src/Kernel/OVR_UTF8Util.cpp
new file mode 100644
index 0000000..f8aa697
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_UTF8Util.cpp
@@ -0,0 +1,556 @@
+/**************************************************************************
+
+Filename    :   OVR_UTF8Util.cpp
+Content     :   UTF8 Unicode character encoding/decoding support
+Created     :   September 19, 2012
+Notes       : 
+Notes       :   Much useful info at "UTF-8 and Unicode FAQ"
+                http://www.cl.cam.ac.uk/~mgk25/unicode.html
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_UTF8Util.h"
+
+namespace OVR { namespace UTF8Util {
+
+SPInt OVR_STDCALL GetLength(const char* buf, SPInt buflen)
+{
+    const char* p = buf;
+    SPInt length = 0;
+
+    if (buflen != -1)
+    {
+        while (p - buf < buflen)
+        {
+            // We should be able to have ASStrings with 0 in the middle.
+            UTF8Util::DecodeNextChar_Advance0(&p);
+            length++;
+        }
+    }
+    else
+    {
+        while (UTF8Util::DecodeNextChar_Advance0(&p))
+            length++;
+    }
+    
+    return length;
+}
+
+UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length)
+{
+    const char* buf = putf8str;
+    UInt32  c = 0;
+
+    if (length != -1)
+    {
+        while (buf - putf8str < length)
+        {           
+            c = UTF8Util::DecodeNextChar_Advance0(&buf);
+            if (index == 0)
+                return c;
+            index--;
+        }
+
+        return c;
+    }
+
+    do 
+    {
+        c = UTF8Util::DecodeNextChar_Advance0(&buf);
+        index--;
+
+        if (c == 0)
+        {
+            // We've hit the end of the string; don't go further.
+            OVR_ASSERT(index == 0);
+            return c;
+        }
+    } while (index >= 0);
+
+    return c;
+}
+
+SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length)
+{
+    const char* buf = putf8str;
+
+    if (length != -1)
+    {
+        while ((buf - putf8str) < length && index > 0)
+        {
+            UTF8Util::DecodeNextChar_Advance0(&buf);
+            index--;
+        }
+
+        return buf-putf8str;
+    }
+
+    while (index > 0) 
+    {
+        UInt32 c = UTF8Util::DecodeNextChar_Advance0(&buf);
+        index--;
+
+        if (c == 0)
+            return buf-putf8str;
+    };
+
+    return buf-putf8str;
+}
+
+int OVR_STDCALL GetEncodeCharSize(UInt32 ucs_character)
+{
+    if (ucs_character <= 0x7F)
+        return 1;
+    else if (ucs_character <= 0x7FF)
+        return 2;
+    else if (ucs_character <= 0xFFFF)
+        return 3;
+    else if (ucs_character <= 0x1FFFFF)
+        return 4;
+    else if (ucs_character <= 0x3FFFFFF)
+        return 5;
+    else if (ucs_character <= 0x7FFFFFFF)
+        return 6;
+    else
+        return 0;
+}
+
+UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer)
+{
+    UInt32  uc;
+    char    c;
+    
+    // Security considerations:
+    //
+    // Changed, this is now only the case for DecodeNextChar:
+    //  - If we hit a zero byte, we want to return 0 without stepping
+    //    the buffer pointer past the 0. th
+    //
+    // If we hit an "overlong sequence"; i.e. a character encoded
+    // in a longer multibyte string than is necessary, then we
+    // need to discard the character.  This is so attackers can't
+    // disguise dangerous characters or character sequences --
+    // there is only one valid encoding for each character.
+    //
+    // If we decode characters { 0xD800 .. 0xDFFF } or { 0xFFFE,
+    // 0xFFFF } then we ignore them; they are not valid in UTF-8.
+    
+    // This isn't actually an invalid character; it's a valid char that
+    // looks like an inverted question mark.
+#define INVALID_CHAR 0x0FFFD
+    
+#define FIRST_BYTE(mask, shift)     \
+    uc = (c & (mask)) << (shift);
+    
+#define NEXT_BYTE(shift) \
+    c = **putf8Buffer;   \
+    if (c == 0) return 0; /* end of buffer, do not advance */   \
+    if ((c & 0xC0) != 0x80) return INVALID_CHAR; /* standard check */  \
+    (*putf8Buffer)++;    \
+    uc |= (c & 0x3F) << shift;
+    
+    c = **putf8Buffer;
+    (*putf8Buffer)++;
+    if (c == 0)
+        return 0;   // End of buffer.
+    
+    if ((c & 0x80) == 0) return (UInt32) c; // Conventional 7-bit ASCII.
+    
+    // Multi-byte sequences.
+    if ((c & 0xE0) == 0xC0)
+    {
+        // Two-byte sequence.
+        FIRST_BYTE(0x1F, 6);
+        NEXT_BYTE(0);
+        if (uc < 0x80) return INVALID_CHAR;  // overlong
+        return uc;
+    }
+    else if ((c & 0xF0) == 0xE0)
+    {
+        // Three-byte sequence.
+        FIRST_BYTE(0x0F, 12);
+        NEXT_BYTE(6);
+        NEXT_BYTE(0);
+        if (uc < 0x800) return INVALID_CHAR; // overlong
+        // Not valid ISO 10646, but Flash requires these to work
+        // see AS3 test e15_5_3_2_3 for String.fromCharCode().charCodeAt(0)
+        // if (uc >= 0x0D800 && uc <= 0x0DFFF) return INVALID_CHAR;
+        // if (uc == 0x0FFFE || uc == 0x0FFFF) return INVALID_CHAR; // not valid ISO 10646
+        return uc;
+    }
+    else if ((c & 0xF8) == 0xF0)
+    {
+        // Four-byte sequence.
+        FIRST_BYTE(0x07, 18);
+        NEXT_BYTE(12);
+        NEXT_BYTE(6);
+        NEXT_BYTE(0);
+        if (uc < 0x010000) return INVALID_CHAR;  // overlong
+        return uc;
+    }
+    else if ((c & 0xFC) == 0xF8)
+    {
+        // Five-byte sequence.
+        FIRST_BYTE(0x03, 24);
+        NEXT_BYTE(18);
+        NEXT_BYTE(12);
+        NEXT_BYTE(6);
+        NEXT_BYTE(0);
+        if (uc < 0x0200000) return INVALID_CHAR; // overlong
+        return uc;
+    }
+    else if ((c & 0xFE) == 0xFC)
+    {
+        // Six-byte sequence.
+        FIRST_BYTE(0x01, 30);
+        NEXT_BYTE(24);
+        NEXT_BYTE(18);
+        NEXT_BYTE(12);
+        NEXT_BYTE(6);
+        NEXT_BYTE(0);
+        if (uc < 0x04000000) return INVALID_CHAR;    // overlong
+        return uc;
+    }
+    else
+    {
+        // Invalid.
+        return INVALID_CHAR;
+    }
+}
+
+
+void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* pindex, UInt32 ucs_character)
+{
+    if (ucs_character <= 0x7F)
+    {
+        // Plain single-byte ASCII.
+        pbuffer[(*pindex)++] = (char) ucs_character;
+    }
+    else if (ucs_character <= 0x7FF)
+    {
+        // Two bytes.
+        pbuffer[(*pindex)++] = 0xC0 | (char)(ucs_character >> 6);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
+    }
+    else if (ucs_character <= 0xFFFF)
+    {
+        // Three bytes.
+        pbuffer[(*pindex)++] = 0xE0 | (char)(ucs_character >> 12);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
+    }
+    else if (ucs_character <= 0x1FFFFF)
+    {
+        // Four bytes.
+        pbuffer[(*pindex)++] = 0xF0 | (char)(ucs_character >> 18);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
+    }
+    else if (ucs_character <= 0x3FFFFFF)
+    {
+        // Five bytes.
+        pbuffer[(*pindex)++] = 0xF8 | (char)(ucs_character >> 24);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
+    }
+    else if (ucs_character <= 0x7FFFFFFF)
+    {
+        // Six bytes.
+        pbuffer[(*pindex)++] = 0xFC | (char)(ucs_character >> 30);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 24) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
+        pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
+    }
+    else
+    {
+        // Invalid char; don't encode anything.
+    }
+}
+
+SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length)
+{
+    SPInt len = 0;
+    if (length != -1)
+        for (int i = 0; i < length; i++)
+        {
+            len += GetEncodeCharSize(pchar[i]);
+        }
+    else
+        for (int i = 0;; i++)
+        {
+            if (pchar[i] == 0)
+                return len;
+            len += GetEncodeCharSize(pchar[i]);
+        }
+    return len;
+}
+
+void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length)
+{
+    SPInt ofs = 0;
+    if (length != -1)
+    {
+        for (int i = 0; i < length; i++)
+        {            
+            EncodeChar(pbuff, &ofs, pchar[i]);
+        }
+    }
+    else
+    {
+        for (int i = 0;; i++)
+        {
+            if (pchar[i] == 0)
+                break;
+            EncodeChar(pbuff, &ofs, pchar[i]);
+        }
+    }
+    pbuff[ofs] = 0;
+}
+
+UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen)
+{
+    wchar_t *pbegin = pbuff;
+    if (bytesLen == -1)
+    {
+        while (1)
+        {
+            UInt32 ch = DecodeNextChar_Advance0(&putf8str);
+            if (ch == 0)
+                break;
+            else if (ch >= 0xFFFF)
+                ch = 0xFFFD;
+            *pbuff++ = wchar_t(ch);
+        }
+    }
+    else
+    {
+        const char* p = putf8str;
+        while ((p - putf8str) < bytesLen)
+        {
+            UInt32 ch = DecodeNextChar_Advance0(&p);
+            if (ch >= 0xFFFF)
+                ch = 0xFFFD;
+            *pbuff++ = wchar_t(ch);
+        }
+    }
+
+    *pbuff = 0;
+    return pbuff - pbegin;
+}
+
+
+#ifdef UTF8_UNIT_TEST
+
+// Compile this test case with something like:
+//
+// gcc utf8.cpp -g -I.. -DUTF8_UNIT_TEST -lstdc++ -o utf8_test
+//
+//    or
+//
+// cl utf8.cpp -Zi -Od -DUTF8_UNIT_TEST -I..
+//
+// If possible, try running the test program with the first arg
+// pointing at the file:
+//
+// http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
+// 
+// and examine the results by eye to make sure they are acceptable to
+// you.
+
+
+#include "base/utility.h"
+#include <stdio.h>
+
+
+bool    check_equal(const char* utf8_in, const UInt32* ucs_in)
+{
+    for (;;)
+    {
+        UInt32  next_ucs = *ucs_in++;
+        UInt32  next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in);
+        if (next_ucs != next_ucs_from_utf8)
+        {
+            return false;
+        }
+        if (next_ucs == 0)
+        {
+            OVR_ASSERT(next_ucs_from_utf8 == 0);
+            break;
+        }
+    }
+    
+    return true;
+}
+
+
+void    log_ascii(const char* line)
+{
+    for (;;)
+    {
+        unsigned char   c = (unsigned char) *line++;
+        if (c == 0)
+        {
+            // End of line.
+            return;
+        }
+        else if (c != '\n'
+            && (c < 32 || c > 127))
+        {
+            // Non-printable as plain ASCII.
+            printf("<0x%02X>", (int) c);
+        }
+        else
+        {
+            printf("%c", c);
+        }
+    }
+}
+
+
+void    log_ucs(const UInt32* line)
+{
+    for (;;)
+    {
+        UInt32  uc = *line++;
+        if (uc == 0)
+        {
+            // End of line.
+            return;
+        }
+        else if (uc != '\n'
+            && (uc < 32 || uc > 127))
+        {
+            // Non-printable as plain ASCII.
+            printf("<U-%04X>", uc);
+        }
+        else
+        {
+            printf("%c", (char) uc);
+        }
+    }
+}
+
+
+// Simple canned test.
+int main(int argc, const char* argv[])
+{
+    {
+        const char* test8 = "Ignacio Castaño";
+        const UInt32    test32[] =
+        {
+            0x49, 0x67, 0x6E, 0x61, 0x63,
+                0x69, 0x6F, 0x20, 0x43, 0x61,
+                0x73, 0x74, 0x61, 0xF1, 0x6F,
+                0x00
+        };
+        
+        OVR_ASSERT(check_equal(test8, test32));
+    }
+        
+        // If user passed an arg, try reading the file as UTF-8 encoded text.
+        if (argc > 1)
+        {
+            const char* filename = argv[1];
+            FILE*   fp = fopen(filename, "rb");
+            if (fp == NULL)
+            {
+                printf("Can't open file '%s'\n", filename);
+                return 1;
+            }
+            
+            // Read lines from the file, encode/decode them, and highlight discrepancies.
+            const int LINE_SIZE = 200;  // max line size
+            char    line_buffer_utf8[LINE_SIZE];
+            char    reencoded_utf8[6 * LINE_SIZE];
+            UInt32  line_buffer_ucs[LINE_SIZE];
+            
+            int byte_counter = 0;
+            for (;;)
+            {
+                int c = fgetc(fp);
+                if (c == EOF)
+                {
+                    // Done.
+                    break;
+                }
+                line_buffer_utf8[byte_counter++] = c;
+                if (c == '\n' || byte_counter >= LINE_SIZE - 2)
+                {
+                    // End of line.  Process the line.
+                    line_buffer_utf8[byte_counter++] = 0;   // terminate.
+                    
+                    // Decode into UCS.
+                    const char* p = line_buffer_utf8;
+                    UInt32* q = line_buffer_ucs;
+                    for (;;)
+                    {
+                        UInt32  uc = UTF8Util::DecodeNextChar(&p);
+                        *q++ = uc;
+                        
+                        OVR_ASSERT(q < line_buffer_ucs + LINE_SIZE);
+                        OVR_ASSERT(p < line_buffer_utf8 + LINE_SIZE);
+                        
+                        if (uc == 0) break;
+                    }
+                    
+                    // Encode back into UTF-8.
+                    q = line_buffer_ucs;
+                    int index = 0;
+                    for (;;)
+                    {
+                        UInt32  uc = *q++;
+                        OVR_ASSERT(index < LINE_SIZE * 6 - 6);
+                        int last_index = index;
+                        UTF8Util::EncodeChar(reencoded_utf8, &index, uc);
+                        OVR_ASSERT(index <= last_index + 6);
+                        if (uc == 0) break;
+                    }
+                    
+                    // This can be useful for debugging.
+#if 0
+                    // Show the UCS and the re-encoded UTF-8.
+                    log_ucs(line_buffer_ucs);
+                    log_ascii(reencoded_utf8);
+#endif // 0
+                    
+                    OVR_ASSERT(check_equal(line_buffer_utf8, line_buffer_ucs));
+                    OVR_ASSERT(check_equal(reencoded_utf8, line_buffer_ucs));
+                    
+                    // Start next line.
+                    byte_counter = 0;
+                }
+            }
+            
+            fclose(fp);
+        }
+        
+        return 0;
+}
+
+
+#endif // UTF8_UNIT_TEST
+
+}} // namespace UTF8Util::OVR
+
diff --git a/LibOVR/Src/Kernel/OVR_UTF8Util.h b/LibOVR/Src/Kernel/OVR_UTF8Util.h
new file mode 100644
index 0000000..6a596012
--- /dev/null
+++ b/LibOVR/Src/Kernel/OVR_UTF8Util.h
@@ -0,0 +1,99 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_UTF8Util.h
+Content     :   UTF8 Unicode character encoding/decoding support
+Created     :   September 19, 2012
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_UTF8Util_h
+#define OVR_UTF8Util_h
+
+#include "OVR_Types.h"
+
+namespace OVR { namespace UTF8Util {
+
+//-----------------------------------------------------------------------------------
+
+// *** UTF8 string length and indexing.
+
+// Determines the length of UTF8 string in characters.
+// If source length is specified (in bytes), null 0 character is counted properly.
+SPInt    OVR_STDCALL GetLength(const char* putf8str, SPInt length = -1);
+
+// Gets a decoded UTF8 character at index; you can access up to the index returned
+// by GetLength. 0 will be returned for out of bounds access.
+UInt32   OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length = -1);
+
+// Converts UTF8 character index into byte offset.
+// -1 is returned if index was out of bounds.
+SPInt    OVR_STDCALL GetByteIndex(SPInt index, const char* putf8str, SPInt length = -1);
+
+
+// *** 16-bit Unicode string Encoding/Decoding routines.
+
+// Determines the number of bytes necessary to encode a string.
+// Does not count the terminating 0 (null) character.
+SPInt    OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length = -1);
+
+// Encodes a unicode (UCS-2 only) string into a buffer. The size of buffer must be at
+// least GetEncodeStringSize() + 1.
+void     OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length = -1);
+
+// Decode UTF8 into a wchar_t buffer. Must have GetLength()+1 characters available.
+// Characters over 0xFFFF are replaced with 0xFFFD.
+// Returns the length of resulting string (number of characters)
+UPInt    OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen = -1);
+
+
+// *** Individual character Encoding/Decoding.
+
+// Determined the number of bytes necessary to encode a UCS character.
+int      OVR_STDCALL GetEncodeCharSize(UInt32 ucsCharacter);
+
+// Encodes the given UCS character into the given UTF-8 buffer.
+// Writes the data starting at buffer[offset], and 
+// increments offset by the number of bytes written.
+// May write up to 6 bytes, so make sure there's room in the buffer
+void     OVR_STDCALL EncodeChar(char* pbuffer, SPInt* poffset, UInt32 ucsCharacter);
+
+// Return the next Unicode character in the UTF-8 encoded buffer.
+// Invalid UTF-8 sequences produce a U+FFFD character as output.
+// Advances *utf8_buffer past the character returned. Pointer advance
+// occurs even if the terminating 0 character is hit, since that allows
+// strings with middle '\0' characters to be supported.
+UInt32   OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer);
+
+// Safer version of DecodeNextChar, which doesn't advance pointer if
+// null character is hit.
+inline UInt32 DecodeNextChar(const char** putf8Buffer)
+{
+    UInt32 ch = DecodeNextChar_Advance0(putf8Buffer);
+    if (ch == 0)
+        (*putf8Buffer)--;
+    return ch;
+}
+
+
+}} // OVR::UTF8Util
+
+#endif
diff --git a/LibOVR/Src/OVR_CAPI.cpp b/LibOVR/Src/OVR_CAPI.cpp
new file mode 100644
index 0000000..a7f921f
--- /dev/null
+++ b/LibOVR/Src/OVR_CAPI.cpp
@@ -0,0 +1,925 @@
+/************************************************************************************
+
+Filename    :   OVR_CAPI.cpp
+Content     :   Experimental simple C interface to the HMD - version 1.
+Created     :   November 30, 2013
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_CAPI.h"
+#include "Kernel/OVR_Timer.h"
+#include "Kernel/OVR_Math.h"
+#include "Kernel/OVR_System.h"
+#include "OVR_Stereo.h"
+#include "OVR_Profile.h"
+
+#include "CAPI/CAPI_GlobalState.h"
+#include "CAPI/CAPI_HMDState.h"
+#include "CAPI/CAPI_FrameTimeManager.h"
+
+
+using namespace OVR;
+using namespace OVR::Util::Render;
+
+//-------------------------------------------------------------------------------------
+// Math
+namespace OVR {
+
+
+// ***** FovPort
+
+// C-interop support: FovPort <-> ovrFovPort
+FovPort::FovPort(const ovrFovPort &src)
+    : UpTan(src.UpTan), DownTan(src.DownTan), LeftTan(src.LeftTan), RightTan(src.RightTan)
+{ }    
+
+FovPort::operator ovrFovPort () const
+{
+    ovrFovPort result;
+    result.LeftTan  = LeftTan;
+    result.RightTan = RightTan;
+    result.UpTan    = UpTan;
+    result.DownTan  = DownTan;
+    return result;
+}
+
+// Converts Fov Tan angle units to [-1,1] render target NDC space
+Vector2f FovPort::TanAngleToRendertargetNDC(Vector2f const &tanEyeAngle)
+{  
+    ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(*this);
+    return tanEyeAngle * eyeToSourceNDC.Scale + eyeToSourceNDC.Offset;
+}
+
+
+// ***** SensorState
+
+SensorState::SensorState(const ovrSensorState& s)
+{
+    Predicted       = s.Predicted;
+    Recorded        = s.Recorded;
+    Temperature     = s.Temperature;
+    StatusFlags     = s.StatusFlags;
+}
+
+SensorState::operator ovrSensorState() const
+{
+    ovrSensorState result;
+    result.Predicted    = Predicted;
+    result.Recorded     = Recorded;
+    result.Temperature  = Temperature;
+    result.StatusFlags  = StatusFlags;
+    return result;
+}
+
+
+} // namespace OVR
+
+//-------------------------------------------------------------------------------------
+
+using namespace OVR::CAPI;
+
+#ifdef __cplusplus 
+extern "C" {
+#endif
+
+
+// Used to generate projection from ovrEyeDesc::Fov
+OVR_EXPORT ovrMatrix4f ovrMatrix4f_Projection(ovrFovPort fov, float znear, float zfar, ovrBool rightHanded)
+{
+    return CreateProjection(rightHanded ? true : false, fov, znear, zfar);
+}
+
+
+OVR_EXPORT ovrMatrix4f ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale,
+                                                      float orthoDistance, float eyeViewAdjustX)
+{
+
+    float orthoHorizontalOffset = eyeViewAdjustX / orthoDistance;
+
+    // Current projection maps real-world vector (x,y,1) to the RT.
+    // We want to find the projection that maps the range [-FovPixels/2,FovPixels/2] to
+    // the physical [-orthoHalfFov,orthoHalfFov]
+    // Note moving the offset from M[0][2]+M[1][2] to M[0][3]+M[1][3] - this means
+    // we don't have to feed in Z=1 all the time.
+    // The horizontal offset math is a little hinky because the destination is
+    // actually [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]
+    // So we need to first map [-FovPixels/2,FovPixels/2] to
+    //                         [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]:
+    // x1 = x0 * orthoHalfFov/(FovPixels/2) + orthoHorizontalOffset;
+    //    = x0 * 2*orthoHalfFov/FovPixels + orthoHorizontalOffset;
+    // But then we need the sam mapping as the existing projection matrix, i.e.
+    // x2 = x1 * Projection.M[0][0] + Projection.M[0][2];
+    //    = x0 * (2*orthoHalfFov/FovPixels + orthoHorizontalOffset) * Projection.M[0][0] + Projection.M[0][2];
+    //    = x0 * Projection.M[0][0]*2*orthoHalfFov/FovPixels +
+    //      orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2];
+    // So in the new projection matrix we need to scale by Projection.M[0][0]*2*orthoHalfFov/FovPixels and
+    // offset by orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2].
+
+    Matrix4f ortho;
+    ortho.M[0][0] = projection.M[0][0] * orthoScale.x;
+    ortho.M[0][1] = 0.0f;
+    ortho.M[0][2] = 0.0f;
+    ortho.M[0][3] = -projection.M[0][2] + ( orthoHorizontalOffset * projection.M[0][0] );
+
+    ortho.M[1][0] = 0.0f;
+    ortho.M[1][1] = -projection.M[1][1] * orthoScale.y;       // Note sign flip (text rendering uses Y=down).
+    ortho.M[1][2] = 0.0f;
+    ortho.M[1][3] = -projection.M[1][2];
+
+    /*
+    if ( fabsf ( zNear - zFar ) < 0.001f )
+    {
+        ortho.M[2][0] = 0.0f;
+        ortho.M[2][1] = 0.0f;
+        ortho.M[2][2] = 0.0f;
+        ortho.M[2][3] = zFar;
+    }
+    else
+    {
+        ortho.M[2][0] = 0.0f;
+        ortho.M[2][1] = 0.0f;
+        ortho.M[2][2] = zFar / (zNear - zFar);
+        ortho.M[2][3] = (zFar * zNear) / (zNear - zFar);
+    }
+    */
+
+    // MA: Undo effect of sign
+    ortho.M[2][0] = 0.0f;
+    ortho.M[2][1] = 0.0f;
+    //ortho.M[2][2] = projection.M[2][2] * projection.M[3][2] * -1.0f; // reverse right-handedness
+    ortho.M[2][2] = 0.0f;
+    ortho.M[2][3] = 0.0f;
+        //projection.M[2][3];
+
+    // No perspective correction for ortho.
+    ortho.M[3][0] = 0.0f;
+    ortho.M[3][1] = 0.0f;
+    ortho.M[3][2] = 0.0f;
+    ortho.M[3][3] = 1.0f;
+
+    return ortho;
+}
+
+
+OVR_EXPORT double ovr_GetTimeInSeconds()
+{
+    return Timer::GetSeconds();
+}
+
+// Waits until the specified absolute time.
+OVR_EXPORT double ovr_WaitTillTime(double absTime)
+{
+    volatile int i;
+    double       initialTime = ovr_GetTimeInSeconds();
+    double       newTime     = initialTime;
+    
+    while(newTime < absTime)
+    {
+        for (int j = 0; j < 50; j++)
+            i = 0;
+        newTime = ovr_GetTimeInSeconds();
+    }
+
+    // How long we waited
+    return newTime - initialTime;
+}
+
+//-------------------------------------------------------------------------------------
+
+// 1. Init/shutdown.
+
+static ovrBool CAPI_SystemInitCalled = 0;
+
+OVR_EXPORT ovrBool ovr_Initialize()
+{
+    if (OVR::CAPI::GlobalState::pInstance)
+        return 1;
+
+    // We must set up the system for the plugin to work
+    if (!OVR::System::IsInitialized())
+    {        
+        OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All));
+        CAPI_SystemInitCalled = 1;
+    }
+
+    // Constructor detects devices
+    GlobalState::pInstance = new GlobalState;
+    return 1;
+}
+
+OVR_EXPORT void ovr_Shutdown()
+{
+    if (!GlobalState::pInstance)
+       return;
+
+    delete GlobalState::pInstance;
+    GlobalState::pInstance = 0;
+
+    // We should clean up the system to be complete
+    if (CAPI_SystemInitCalled)
+    {
+        OVR::System::Destroy();
+        CAPI_SystemInitCalled = 0;
+    }    
+    return;
+}
+
+
+// There is a thread safety issue with ovrHmd_Detect in that multiple calls from different
+// threads can corrupt the global array state. This would lead to two problems:
+//  a) Create(index) enumerator may miss or overshoot items. Probably not a big deal
+//     as game logic can easily be written to only do Detect(s)/Creates in one place.
+//     The alternative would be to return list handle.
+//  b) TBD: Un-mutexed Detect access from two threads could lead to crash. We should
+//         probably check this.
+//
+
+OVR_EXPORT int ovrHmd_Detect()
+{
+    if (!GlobalState::pInstance)
+        return 0;
+    return GlobalState::pInstance->EnumerateDevices();
+}
+
+
+// ovrHmd_Create us explicitly separated from StartSensor and Configure to allow creation of 
+// a relatively light-weight handle that would reference the device going forward and would 
+// survive future ovrHmd_Detect calls. That is once ovrHMD is returned, index is no longer
+// necessary and can be changed by a ovrHmd_Detect call.
+
+OVR_EXPORT ovrHmd ovrHmd_Create(int index)
+{
+    if (!GlobalState::pInstance)
+        return 0;
+    Ptr<HMDDevice> device = *GlobalState::pInstance->CreateDevice(index);
+    if (!device)
+        return 0;
+
+    HMDState* hmds = new HMDState(device);
+    if (!hmds)
+        return 0;
+
+    return hmds;
+}
+
+OVR_EXPORT ovrHmd ovrHmd_CreateDebug(ovrHmdType type)
+{
+    if (!GlobalState::pInstance)
+        return 0;    
+
+    HMDState* hmds = new HMDState(type);    
+    return hmds;
+}
+
+OVR_EXPORT void ovrHmd_Destroy(ovrHmd hmd)
+{
+    if (!hmd)
+        return;
+    // TBD: Any extra shutdown?
+    HMDState* hmds = (HMDState*)hmd;
+        
+    {   // Thread checker in its own scope, to avoid access after 'delete'.
+        // Essentially just checks that no other RenderAPI function is executing.
+        ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_Destroy");
+    }    
+
+    delete (HMDState*)hmd;
+}
+
+
+OVR_EXPORT const char* ovrHmd_GetLastError(ovrHmd hmd)
+{
+    using namespace OVR;
+    if (!hmd)
+    {
+        if (!GlobalState::pInstance)  
+            return "LibOVR not initialized.";
+        return GlobalState::pInstance->GetLastError();
+    }
+    HMDState* p = (HMDState*)hmd;
+    return p->GetLastError();
+}
+
+
+//-------------------------------------------------------------------------------------
+
+// Returns capability bits that are enabled at this time; described by ovrHmdCapBits.
+// Note that this value is different font ovrHmdDesc::Caps, which describes what
+// capabilities are available.
+OVR_EXPORT unsigned int ovrHmd_GetEnabledCaps(ovrHmd hmd)
+{
+    HMDState* p = (HMDState*)hmd;
+    return p ? p->EnabledHmdCaps : 0;
+}
+
+// Modifies capability bits described by ovrHmdCapBits that can be modified,
+// such as ovrHmd_LowPersistance.
+OVR_EXPORT void ovrHmd_SetEnabledCaps(ovrHmd hmd, unsigned int capsBits)
+{
+    HMDState* p = (HMDState*)hmd;
+    if (p)
+        p->SetEnabledHmdCaps(capsBits);
+}
+
+
+//-------------------------------------------------------------------------------------
+// *** Sensor
+
+// Sensor APIs are separated from Create & Configure for several reasons:
+//  - They need custom parameters that control allocation of heavy resources
+//    such as Vision tracking, which you don't want to create unless necessary.
+//  - A game may want to switch some sensor settings based on user input, 
+//    or at lease enable/disable features such as Vision for debugging.
+//  - The same or syntactically similar sensor interface is likely to be used if we 
+//    introduce controllers.
+//
+//  - Sensor interface functions are all Thread-safe, unlike the frame/render API
+//    functions that have different rules (all frame access functions
+//    must be on render thread)
+
+OVR_EXPORT ovrBool ovrHmd_StartSensor(ovrHmd hmd, unsigned int supportedCaps, unsigned int requiredCaps)
+{
+    HMDState* p = (HMDState*)hmd;
+    // TBD: Decide if we null-check arguments.
+    return p->StartSensor(supportedCaps, requiredCaps);
+}
+
+OVR_EXPORT void ovrHmd_StopSensor(ovrHmd hmd)
+{
+    HMDState* p = (HMDState*)hmd;
+    p->StopSensor();
+}
+
+OVR_EXPORT void ovrHmd_ResetSensor(ovrHmd hmd)
+{
+    HMDState* p = (HMDState*)hmd;
+    p->ResetSensor();
+}
+
+OVR_EXPORT ovrSensorState ovrHmd_GetSensorState(ovrHmd hmd, double absTime)
+{
+    HMDState* p = (HMDState*)hmd;
+    return p->PredictedSensorState(absTime);
+}
+
+// Returns information about a sensor. Only valid after SensorStart.
+OVR_EXPORT ovrBool ovrHmd_GetSensorDesc(ovrHmd hmd, ovrSensorDesc* descOut)
+{
+    HMDState* p = (HMDState*)hmd;
+    return p->GetSensorDesc(descOut) ? 1 : 0;
+}
+
+
+
+//-------------------------------------------------------------------------------------
+// *** General Setup
+
+
+OVR_EXPORT void ovrHmd_GetDesc(ovrHmd hmd, ovrHmdDesc* desc)
+{
+    HMDState* hmds = (HMDState*)hmd;    
+    *desc = hmds->RenderState.GetDesc();
+    desc->Handle = hmd;
+}
+
+// Per HMD -> calculateIdealPixelSize
+OVR_EXPORT ovrSizei ovrHmd_GetFovTextureSize(ovrHmd hmd, ovrEyeType eye, ovrFovPort fov,
+                                             float pixelsPerDisplayPixel)
+{
+    if (!hmd) return Sizei(0);
+    
+    HMDState* hmds = (HMDState*)hmd;
+    return hmds->RenderState.GetFOVTextureSize(eye, fov, pixelsPerDisplayPixel);
+}
+
+
+//-------------------------------------------------------------------------------------
+
+
+OVR_EXPORT 
+ovrBool ovrHmd_ConfigureRendering( ovrHmd hmd,
+                                   const ovrRenderAPIConfig* apiConfig,
+                                   unsigned int distortionCaps,
+                                   const ovrFovPort eyeFovIn[2],
+                                   ovrEyeRenderDesc eyeRenderDescOut[2] )
+{
+    if (!hmd) return 0;
+    return ((HMDState*)hmd)->ConfigureRendering(eyeRenderDescOut, eyeFovIn,
+                                                apiConfig, distortionCaps);
+}
+
+
+
+// TBD: MA - Deprecated, need alternative
+void ovrHmd_SetVsync(ovrHmd hmd, ovrBool vsync)
+{
+    if (!hmd) return;
+
+    return ((HMDState*)hmd)->TimeManager.SetVsync(vsync? true : false);
+}
+
+
+OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrame(ovrHmd hmd, unsigned int frameIndex)
+{           
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmds)
+    {
+        ovrFrameTiming f;
+        memset(&f, 0, sizeof(f));
+        return f;
+    }
+
+    // Check: Proper configure and threading state for the call.
+    hmds->checkRenderingConfigured("ovrHmd_BeginFrame");
+    OVR_ASSERT_LOG(hmds->BeginFrameCalled == false, ("ovrHmd_BeginFrame called multiple times."));
+    ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_BeginFrame");
+    
+    hmds->BeginFrameCalled   = true;
+    hmds->BeginFrameThreadId = OVR::GetCurrentThreadId();
+
+    return ovrHmd_BeginFrameTiming(hmd, frameIndex);
+}
+
+
+// Renders textures to frame buffer
+OVR_EXPORT void ovrHmd_EndFrame(ovrHmd hmd)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmds) return;
+
+    // Debug state checks: Must be in BeginFrame, on the same thread.
+    hmds->checkBeginFrameScope("ovrHmd_EndFrame");
+    ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame");  
+
+    // TBD: Move directly into renderer
+    bool dk2LatencyTest = (hmds->HMDInfo.HmdType == HmdType_DK2) &&
+                           (hmds->EnabledHmdCaps & ovrHmdCap_LatencyTest);
+    if (dk2LatencyTest)
+    {
+        hmds->LatencyTest2DrawColor[0] = hmds->TimeManager.GetFrameLatencyTestDrawColor();
+        hmds->LatencyTest2DrawColor[1] = hmds->LatencyTest2DrawColor[0];
+        hmds->LatencyTest2DrawColor[2] = hmds->LatencyTest2DrawColor[0];
+    }
+
+    if (hmds->pRenderer)
+	{
+		hmds->pRenderer->SaveGraphicsState();
+        hmds->pRenderer->EndFrame(true,
+                                  hmds->LatencyTestActive ? hmds->LatencyTestDrawColor : NULL,
+                            
+                                  // MA: Use this color since we are running DK2 test all the time.
+                                  dk2LatencyTest ? hmds->LatencyTest2DrawColor : 0
+                                  //hmds->LatencyTest2Active ? hmds->LatencyTest2DrawColor : NULL
+								  );
+		hmds->pRenderer->RestoreGraphicsState();
+    }
+    // Call after present
+    ovrHmd_EndFrameTiming(hmd);
+
+    if (dk2LatencyTest)
+    {
+        hmds->TimeManager.UpdateFrameLatencyTrackingAfterEndFrame(
+            hmds->LatencyTest2DrawColor[0], hmds->LatencyUtil2.GetLocklessState());
+    }
+
+    // Out of BeginFrame
+    hmds->BeginFrameThreadId = 0;
+    hmds->BeginFrameCalled   = false;
+}
+
+
+OVR_EXPORT ovrPosef ovrHmd_BeginEyeRender(ovrHmd hmd, ovrEyeType eye)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmds) return ovrPosef();
+    return hmds->BeginEyeRender(eye);
+}
+
+OVR_EXPORT void ovrHmd_EndEyeRender(ovrHmd hmd, ovrEyeType eye,
+                                    ovrPosef renderPose, ovrTexture* eyeTexture)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmds) return;
+    hmds->EndEyeRender(eye, renderPose, eyeTexture);
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** Frame Timing logic
+
+
+OVR_EXPORT ovrFrameTiming ovrHmd_GetFrameTiming(ovrHmd hmd, unsigned int frameIndex)
+{
+    ovrFrameTiming f;
+    memset(&f, 0, sizeof(f));
+
+    HMDState* hmds = (HMDState*)hmd;
+    if (hmds)
+    {
+        FrameTimeManager::Timing frameTiming = hmds->TimeManager.GetFrameTiming(frameIndex);
+
+        f.ThisFrameSeconds     = frameTiming.ThisFrameTime;
+        f.NextFrameSeconds       = frameTiming.NextFrameTime;
+        f.TimewarpPointSeconds  = frameTiming.TimewarpPointTime;
+        f.ScanoutMidpointSeconds= frameTiming.MidpointTime;
+        f.EyeScanoutSeconds[0]  = frameTiming.EyeRenderTimes[0];
+        f.EyeScanoutSeconds[1]  = frameTiming.EyeRenderTimes[1];
+
+         // Compute DeltaSeconds.
+        f.DeltaSeconds = (hmds->LastGetFrameTimeSeconds == 0.0f) ? 0.0f :
+                         (float) (f.ThisFrameSeconds - hmds->LastFrameTimeSeconds);    
+        hmds->LastGetFrameTimeSeconds = f.ThisFrameSeconds;
+        if (f.DeltaSeconds > 1.0f)
+            f.DeltaSeconds = 1.0f;
+    }
+        
+    return f;
+}
+
+OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrameTiming(ovrHmd hmd, unsigned int frameIndex)
+{
+    ovrFrameTiming f;
+    memset(&f, 0, sizeof(f));
+
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmds) return f;
+
+    // Check: Proper state for the call.    
+    OVR_ASSERT_LOG(hmds->BeginFrameTimingCalled == false,
+                    ("ovrHmd_BeginFrameTiming called multiple times."));    
+    hmds->BeginFrameTimingCalled = true;
+
+    double thisFrameTime = hmds->TimeManager.BeginFrame(frameIndex);        
+
+    const FrameTimeManager::Timing &frameTiming = hmds->TimeManager.GetFrameTiming();
+
+    f.ThisFrameSeconds     = thisFrameTime;
+    f.NextFrameSeconds       = frameTiming.NextFrameTime;
+    f.TimewarpPointSeconds  = frameTiming.TimewarpPointTime;
+    f.ScanoutMidpointSeconds= frameTiming.MidpointTime;
+    f.EyeScanoutSeconds[0]  = frameTiming.EyeRenderTimes[0];
+    f.EyeScanoutSeconds[1]  = frameTiming.EyeRenderTimes[1];
+
+    // Compute DeltaSeconds.
+    f.DeltaSeconds = (hmds->LastFrameTimeSeconds == 0.0f) ? 0.0f :
+                     (float) (thisFrameTime - hmds->LastFrameTimeSeconds);    
+    hmds->LastFrameTimeSeconds = thisFrameTime;
+    if (f.DeltaSeconds > 1.0f)
+        f.DeltaSeconds = 1.0f;
+
+    return f;
+}
+
+
+OVR_EXPORT void ovrHmd_EndFrameTiming(ovrHmd hmd)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmds) return;
+
+    // Debug state checks: Must be in BeginFrameTiming, on the same thread.
+    hmds->checkBeginFrameTimingScope("ovrHmd_EndTiming");
+   // MA TBD: Correct chek or not?
+   // ThreadChecker::Scope checkScope(&hmds->RenderAPIThreadChecker, "ovrHmd_EndFrame");
+
+    hmds->TimeManager.EndFrame();   
+    hmds->BeginFrameTimingCalled = false;
+}
+
+
+OVR_EXPORT void ovrHmd_ResetFrameTiming(ovrHmd hmd,  unsigned int frameIndex) 
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmds) return;
+    
+    hmds->TimeManager.ResetFrameTiming(frameIndex, 
+                                       false,
+                                       hmds->RenderingConfigured);
+    hmds->LastFrameTimeSeconds    = 0.0;
+    hmds->LastGetFrameTimeSeconds = 0.0;
+}
+
+
+
+OVR_EXPORT ovrPosef ovrHmd_GetEyePose(ovrHmd hmd, ovrEyeType eye)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmds) return ovrPosef();    
+
+    hmds->checkBeginFrameTimingScope("ovrHmd_GetEyePose");
+    return hmds->TimeManager.GetEyePredictionPose(hmd, eye);
+}
+
+
+OVR_EXPORT void ovrHmd_GetEyeTimewarpMatrices(ovrHmd hmd, ovrEyeType eye,
+                                              ovrPosef renderPose, ovrMatrix4f twmOut[2])
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmd)
+        return;
+
+    // Debug checks: BeginFrame was called, on the same thread.
+    hmds->checkBeginFrameTimingScope("ovrHmd_GetTimewarpEyeMatrices");   
+
+    hmds->TimeManager.GetTimewarpMatrices(hmd, eye, renderPose, twmOut);
+
+    /*
+    // MA: Took this out because new latency test approach just sames
+    //     the sample times in FrameTimeManager.
+    // TODO: if no timewarp, then test latency in begin eye render
+    if (eye == 0)
+    {        
+        hmds->ProcessLatencyTest2(hmds->LatencyTest2DrawColor, -1.0f);
+    }
+    */
+}
+
+
+
+OVR_EXPORT ovrEyeRenderDesc ovrHmd_GetRenderDesc(ovrHmd hmd,
+                                                 ovrEyeType eyeType, ovrFovPort fov)
+{
+    ovrEyeRenderDesc erd;
+   
+    HMDState* hmds = (HMDState*)hmd;
+    if (!hmds)
+    {
+        memset(&erd, 0, sizeof(erd));
+        return erd;
+    }
+
+    return hmds->RenderState.calcRenderDesc(eyeType, fov);
+}
+
+
+
+#define OVR_OFFSET_OF(s, field) ((size_t)&((s*)0)->field)
+
+
+
+// Generate distortion mesh per eye.
+// scaleAndOffsetOut - this will be needed for shader
+OVR_EXPORT ovrBool ovrHmd_CreateDistortionMesh( ovrHmd hmd,
+                                                ovrEyeType eyeType, ovrFovPort fov,
+                                                unsigned int distortionCaps,
+                                                ovrDistortionMesh *meshData )
+{
+    if (!meshData)
+        return 0;
+    HMDState* hmds = (HMDState*)hmd;
+
+    // Not used now, but Chromatic flag or others could possibly be checked for in the future.
+    OVR_UNUSED1(distortionCaps); 
+    
+#if defined (OVR_OS_WIN32)
+    // TBD: We should probably be sharing some C API structures with C++ to avoid this mess...
+    OVR_COMPILER_ASSERT(sizeof(DistortionMeshVertexData)                       == sizeof(ovrDistortionVertex));
+    OVR_COMPILER_ASSERT(OVR_OFFSET_OF(DistortionMeshVertexData, ScreenPosNDC)  == OVR_OFFSET_OF(ovrDistortionVertex, Pos));
+    OVR_COMPILER_ASSERT(OVR_OFFSET_OF(DistortionMeshVertexData, TimewarpLerp)  == OVR_OFFSET_OF(ovrDistortionVertex, TimeWarpFactor));
+    OVR_COMPILER_ASSERT(OVR_OFFSET_OF(DistortionMeshVertexData, Shade)         == OVR_OFFSET_OF(ovrDistortionVertex, VignetteFactor));
+    OVR_COMPILER_ASSERT(OVR_OFFSET_OF(DistortionMeshVertexData, TanEyeAnglesR) == OVR_OFFSET_OF(ovrDistortionVertex, TexR));
+    OVR_COMPILER_ASSERT(OVR_OFFSET_OF(DistortionMeshVertexData, TanEyeAnglesG) == OVR_OFFSET_OF(ovrDistortionVertex, TexG));
+    OVR_COMPILER_ASSERT(OVR_OFFSET_OF(DistortionMeshVertexData, TanEyeAnglesB) == OVR_OFFSET_OF(ovrDistortionVertex, TexB));
+#endif
+
+
+    // *** Calculate a part of "StereoParams" needed for mesh generation
+
+    // Note that mesh distortion generation is invariant of RenderTarget UVs, allowing
+    // render target size and location to be changed after the fact dynamically. 
+    // eyeToSourceUV is computed here for convenience, so that users don't need
+    // to call ovrHmd_GetRenderScaleAndOffset unless changing RT dynamically.
+
+    const HmdRenderInfo&  hmdri          = hmds->RenderState.RenderInfo;    
+    StereoEye             stereoEye      = (eyeType == ovrEye_Left) ? StereoEye_Left : StereoEye_Right;
+
+    const DistortionRenderDesc& distortion = hmds->RenderState.Distortion[eyeType];
+
+    // Find the mapping from TanAngle space to target NDC space.
+    ScaleAndOffset2D      eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(fov);
+
+    int triangleCount = 0;
+    int vertexCount = 0;
+
+    DistortionMeshCreate((DistortionMeshVertexData**)&meshData->pVertexData, (UInt16**)&meshData->pIndexData,
+                          &vertexCount, &triangleCount,
+                          (stereoEye == StereoEye_Right),
+                          hmdri, distortion, eyeToSourceNDC);
+
+    if (meshData->pVertexData)
+    {
+        // Convert to index
+        meshData->IndexCount = triangleCount * 3;
+        meshData->VertexCount = vertexCount;
+        return 1;
+    }
+
+    return 0;
+}
+
+
+// Frees distortion mesh allocated by ovrHmd_GenerateDistortionMesh. meshData elements
+// are set to null and 0s after the call.
+OVR_EXPORT void ovrHmd_DestroyDistortionMesh(ovrDistortionMesh* meshData)
+{
+    if (meshData->pVertexData)
+        DistortionMeshDestroy((DistortionMeshVertexData*)meshData->pVertexData,
+                              meshData->pIndexData);
+    meshData->pVertexData = 0;
+    meshData->pIndexData  = 0;
+    meshData->VertexCount = 0;
+    meshData->IndexCount  = 0;
+}
+
+
+
+// Computes updated 'uvScaleOffsetOut' to be used with a distortion if render target size or
+// viewport changes after the fact. This can be used to adjust render size every frame, if desired.
+OVR_EXPORT void ovrHmd_GetRenderScaleAndOffset( ovrFovPort fov,
+                                                ovrSizei textureSize, ovrRecti renderViewport,
+                                                ovrVector2f uvScaleOffsetOut[2] )
+{        
+    // Find the mapping from TanAngle space to target NDC space.
+    ScaleAndOffset2D  eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov(fov);
+    // Find the mapping from TanAngle space to textureUV space.
+    ScaleAndOffset2D  eyeToSourceUV  = CreateUVScaleAndOffsetfromNDCScaleandOffset(
+                                         eyeToSourceNDC,
+                                         renderViewport, textureSize );
+
+    uvScaleOffsetOut[0] = eyeToSourceUV.Scale;
+    uvScaleOffsetOut[1] = eyeToSourceUV.Offset;
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** Latency Test interface
+
+OVR_EXPORT ovrBool ovrHmd_GetLatencyTestDrawColor(ovrHmd hmd, unsigned char rgbColorOut[3])
+{
+    HMDState* p = (HMDState*)hmd;
+    rgbColorOut[0] = p->LatencyTestDrawColor[0];
+    rgbColorOut[1] = p->LatencyTestDrawColor[1];
+    rgbColorOut[2] = p->LatencyTestDrawColor[2];
+    return p->LatencyTestActive;
+}
+
+OVR_EXPORT const char*  ovrHmd_GetLatencyTestResult(ovrHmd hmd)
+{
+    HMDState* p = (HMDState*)hmd;
+    return p->LatencyUtil.GetResultsString();
+}
+
+OVR_EXPORT double ovrHmd_GetMeasuredLatencyTest2(ovrHmd hmd)
+{
+    HMDState* p = (HMDState*)hmd;
+
+    // MA Test
+    float latencies[3];
+    p->TimeManager.GetLatencyTimings(latencies);
+    return latencies[2];
+  //  return p->LatencyUtil2.GetMeasuredLatency();
+}
+
+
+// -----------------------------------------------------------------------------------
+// ***** Property Access
+
+OVR_EXPORT float ovrHmd_GetFloat(ovrHmd hmd, const char* propertyName, float defaultVal)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (hmds)
+	{
+		return hmds->getFloatValue(propertyName, defaultVal);
+	}
+
+    return defaultVal;
+}
+
+OVR_EXPORT ovrBool ovrHmd_SetFloat(ovrHmd hmd, const char* propertyName, float value)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (hmds)
+    {
+        return hmds->setFloatValue(propertyName, value);
+    }
+    return false;
+}
+
+
+
+OVR_EXPORT unsigned int ovrHmd_GetFloatArray(ovrHmd hmd, const char* propertyName,
+                              float values[], unsigned int arraySize)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (hmds)
+    {       
+		return hmds->getFloatArray(propertyName, values, arraySize);
+    }
+
+    return 0;
+}
+
+
+// Modify float[] property; false if property doesn't exist or is readonly.
+OVR_EXPORT ovrBool ovrHmd_SetFloatArray(ovrHmd hmd, const char* propertyName,
+                                        float values[], unsigned int arraySize)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (hmds)
+    {       
+        return hmds->setFloatArray(propertyName, values, arraySize);
+    }
+
+    return 0;
+}
+
+OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmd, const char* propertyName,
+                                        const char* defaultVal)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (hmds)
+    {
+		return hmds->getString(propertyName, defaultVal);
+    }
+
+    return defaultVal;
+}
+ 
+/* Not needed yet.
+
+// Get array of strings, i.e. const char* [] property.
+// Returns the number of elements filled in, 0 if property doesn't exist.
+// Maximum of arraySize elements will be written.
+// String memory is guaranteed to exist until next call to GetString or GetStringArray, or HMD is destroyed.
+OVR_EXPORT 
+unsigned int ovrHmd_GetStringArray(ovrHmd hmd, const char* propertyName,
+                               const char* values[], unsigned int arraySize)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (hmds && hmds->pHMD && arraySize)
+    {        
+        Profile* p = hmds->pHMD->GetProfile();
+
+        hmds->LastGetStringValue[0] = 0;
+        if (p && p->GetValue(propertyName, hmds->LastGetStringValue, sizeof(hmds->LastGetStringValue)))
+        {
+            values[0] = hmds->LastGetStringValue;
+            return 1;
+        }
+    }
+
+    return 0;
+}
+*/
+
+// Returns array size of a property, 0 if property doesn't exist.
+// Can be used to check existence of a property.
+OVR_EXPORT unsigned int ovrHmd_GetArraySize(ovrHmd hmd, const char* propertyName)
+{
+    HMDState* hmds = (HMDState*)hmd;
+    if (hmds && hmds->pHMD)
+    {
+        // For now, just access the profile.
+        Profile* p = hmds->pHMD->GetProfile();
+        
+        if (p)
+            return p->GetNumValues(propertyName);
+    }
+    return 0;
+}
+
+
+#ifdef __cplusplus 
+} // extern "C"
+#endif
+
+
+//-------------------------------------------------------------------------------------
+// ****** Special access for VRConfig
+
+// Return the sensor fusion object for the purposes of magnetometer calibration.  The
+// function is private and is only exposed through VRConfig header declarations
+OVR::SensorFusion* ovrHmd_GetSensorFusion(ovrHmd hmd)
+{
+    HMDState* p = (HMDState*)hmd;
+    return &p->SFusion;
+}
+
+
diff --git a/LibOVR/Src/OVR_CAPI.h b/LibOVR/Src/OVR_CAPI.h
new file mode 100644
index 0000000..ec4708c
--- /dev/null
+++ b/LibOVR/Src/OVR_CAPI.h
@@ -0,0 +1,790 @@
+/************************************************************************************
+
+Filename    :   OVR_CAPI.h
+Content     :   C Interface to Oculus sensors and rendering.
+Created     :   November 23, 2013
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+#ifndef OVR_CAPI_h
+#define OVR_CAPI_h
+
+#include <stdint.h>
+
+typedef char ovrBool;
+
+//-----------------------------------------------------------------------------------
+// ***** OVR_EXPORT definition
+
+#if !defined(OVR_EXPORT)
+    #if defined(WIN32)    
+        #define OVR_EXPORT __declspec(dllexport)        
+    #else
+        #define OVR_EXPORT
+    #endif
+#endif
+
+//-----------------------------------------------------------------------------------
+// ***** Simple Math Structures
+
+// 2D integer
+typedef struct ovrVector2i_
+{
+    int x, y;
+} ovrVector2i;
+typedef struct ovrSizei_
+{
+    int w, h;
+} ovrSizei;
+typedef struct ovrRecti_
+{
+    ovrVector2i Pos;
+    ovrSizei    Size;
+} ovrRecti;
+
+// 3D
+typedef struct ovrQuatf_
+{
+    float x, y, z, w;  
+} ovrQuatf;
+typedef struct ovrVector2f_
+{
+    float x, y;
+} ovrVector2f;
+typedef struct ovrVector3f_
+{
+    float x, y, z;
+} ovrVector3f;
+typedef struct ovrMatrix4f_
+{
+    float M[4][4];
+} ovrMatrix4f;
+// Position and orientation together.
+typedef struct ovrPosef_
+{
+    ovrQuatf     Orientation;
+    ovrVector3f  Position;    
+} ovrPosef;
+
+// Full pose (rigid body) configuration with first and second derivatives.
+typedef struct ovrPoseStatef_
+{
+    ovrPosef     Pose;
+    ovrVector3f  AngularVelocity;
+    ovrVector3f  LinearVelocity;
+    ovrVector3f  AngularAcceleration;
+    ovrVector3f  LinearAcceleration;
+    double       TimeInSeconds;         // Absolute time of this state sample.
+} ovrPoseStatef;
+
+// Field Of View (FOV) in tangent of the angle units.
+// As an example, for a standard 90 degree vertical FOV, we would 
+// have: { UpTan = tan(90 degrees / 2), DownTan = tan(90 degrees / 2) }.
+typedef struct ovrFovPort_
+{
+    float UpTan;
+    float DownTan;
+    float LeftTan;
+    float RightTan;
+} ovrFovPort;
+
+
+//-----------------------------------------------------------------------------------
+// ***** HMD Types
+
+// Enumerates all HMD types that we support.
+typedef enum
+{
+    ovrHmd_None             = 0,    
+    ovrHmd_DK1              = 3,
+    ovrHmd_DKHD             = 4,
+    ovrHmd_CrystalCoveProto = 5,
+    ovrHmd_DK2              = 6,
+    ovrHmd_Other             // Some HMD other then the one in the enumeration.
+} ovrHmdType;
+
+// HMD capability bits reported by device.
+// 
+typedef enum
+{
+    // Read-only flags.
+    ovrHmdCap_Present           = 0x0001,   //  This HMD exists (as opposed to being unplugged).
+    ovrHmdCap_Available         = 0x0002,   //  HMD and is sensor is available for use
+                                            //  (if not owned by another app).       
+
+    // These flags are intended for use with the new driver display mode.
+    /*
+    ovrHmdCap_ExtendDesktop     = 0x0004,   // Read only, means display driver is in compatibility mode.
+
+    ovrHmdCap_DisplayOff        = 0x0040,   // Turns off Oculus HMD screen and output.
+    ovrHmdCap_NoMirrorToWindow  = 0x2000,   // Disables mirrowing of HMD output to the window;
+                                            // may improve rendering performance slightly.
+    */
+
+    // Modifiable flags (through ovrHmd_SetEnabledCaps).
+    ovrHmdCap_LowPersistence    = 0x0080,   //  Supports low persistence mode.
+	ovrHmdCap_LatencyTest       = 0x0100,   //  Supports pixel reading for continuous latency testing.
+    ovrHmdCap_DynamicPrediction = 0x0200,   //  Adjust prediction dynamically based on DK2 Latency.
+    // Support rendering without VSync for debugging
+    ovrHmdCap_NoVSync           = 0x1000,
+	ovrHmdCap_NoRestore         = 0x4000,
+
+    // These bits can be modified by ovrHmd_SetEnabledCaps.
+    ovrHmdCap_Writable_Mask     = 0x1380
+} ovrHmdCaps;
+
+
+// Sensor capability bits reported by device.
+// Used with ovrHmd_StartSensor.
+typedef enum
+{
+    ovrSensorCap_Orientation    = 0x0010,   //  Supports orientation tracking (IMU).
+    ovrSensorCap_YawCorrection  = 0x0020,   //  Supports yaw correction through magnetometer or other means.
+    ovrSensorCap_Position       = 0x0040,   //  Supports positional tracking.
+
+} ovrSensorCaps;
+
+// Distortion capability bits reported by device.
+// Used with ovrHmd_ConfigureRendering and ovrHmd_CreateDistortionMesh.
+typedef enum
+{        
+    ovrDistortionCap_Chromatic	= 0x01,		//	Supports chromatic aberration correction.
+    ovrDistortionCap_TimeWarp	= 0x02,		//	Supports timewarp.
+    ovrDistortionCap_Vignette	= 0x08		//	Supports vignetting around the edges of the view.
+} ovrDistortionCaps;
+
+
+// Specifies which eye is being used for rendering.
+// This type explicitly does not include a third "NoStereo" option, as such is
+// not required for an HMD-centered API.
+typedef enum
+{
+    ovrEye_Left  = 0,
+    ovrEye_Right = 1,
+    ovrEye_Count = 2
+} ovrEyeType;
+
+
+// Handle to HMD; returned by ovrHmd_Create.
+typedef struct ovrHmdStruct* ovrHmd;
+
+// This is a complete descriptor of the HMD.
+typedef struct ovrHmdDesc_
+{
+    ovrHmd      Handle;  // Handle of this HMD.
+    ovrHmdType  Type;
+    
+    // Name string describing the product: "Oculus Rift DK1", etc.
+    const char* ProductName;    
+    const char* Manufacturer;
+
+    // Capability bits described by ovrHmdCaps.
+    unsigned int HmdCaps;
+	// Capability bits described by ovrSensorCaps.
+    unsigned int SensorCaps;
+    // Capability bits described by ovrDistortionCaps.
+    unsigned int DistortionCaps;
+
+    // Resolution of the entire HMD screen (for both eyes) in pixels.
+    ovrSizei    Resolution;
+    // Where monitor window should be on screen or (0,0).
+    ovrVector2i WindowsPos;     
+
+    // These define the recommended and maximum optical FOVs for the HMD.    
+    ovrFovPort  DefaultEyeFov[ovrEye_Count];
+    ovrFovPort  MaxEyeFov[ovrEye_Count];
+
+    // Preferred eye rendering order for best performance.
+    // Can help reduce latency on sideways-scanned screens.
+    ovrEyeType  EyeRenderOrder[ovrEye_Count];
+    
+    // Display that HMD should present on.
+    // TBD: It may be good to remove this information relying on WidowPos instead.
+    // Ultimately, we may need to come up with a more convenient alternative,
+    // such as a API-specific functions that return adapter, ot something that will
+    // work with our monitor driver.
+
+    // Windows: "\\\\.\\DISPLAY3", etc. Can be used in EnumDisplaySettings/CreateDC.    
+    const char* DisplayDeviceName;
+    // MacOS
+    int        DisplayId;
+} ovrHmdDesc;
+
+// Describes the type of positional tracking being done.
+/*
+typedef enum
+{
+    ovrPose_None,
+    ovrPose_HeadModel,
+    ovrPose_Positional
+} ovrPoseType;
+*/
+
+
+// Bit flags describing the current status of sensor tracking.
+typedef enum
+{
+    ovrStatus_OrientationTracked    = 0x0001,   // Orientation is currently tracked (connected and in use).
+    ovrStatus_PositionTracked       = 0x0002,   // Position is currently tracked (FALSE if out of range).
+    ovrStatus_PositionConnected     = 0x0020,   // Position tracking HW is connected.
+    ovrStatus_HmdConnected          = 0x0080    // HMD Display is available & connected.
+} ovrStatusBits;
+
+
+// State of the sensor at a given absolute time.
+typedef struct ovrSensorState_
+{
+    // Predicted pose configuration at requested absolute time.
+    // One can determine the time difference between predicted and actual
+    // readings by comparing ovrPoseState.TimeInSeconds.
+    ovrPoseStatef  Predicted;
+    // Actual recorded pose configuration based on the sensor sample at a 
+    // moment closest to the requested time.
+    ovrPoseStatef  Recorded;
+
+    // Sensor temperature reading, in degrees Celsius, as sample time.
+    float          Temperature;    
+    // Sensor status described by ovrStatusBits.
+    unsigned int   StatusFlags;
+} ovrSensorState;
+
+// For now.
+// TBD: Decide if this becomes a part of HMDDesc
+typedef struct ovrSensorDesc_
+{
+    // HID Vendor and ProductId of the device.
+    short   VendorId;
+    short   ProductId;
+    // Sensor (and display) serial number.
+    char    SerialNumber[24];
+} ovrSensorDesc;
+
+
+
+// Frame data reported by ovrHmd_BeginFrameTiming().
+typedef struct ovrFrameTiming_
+{
+    // The amount of time that has passed since the previous frame returned
+    // BeginFrameSeconds value, usable for movement scaling.
+    // This will be clamped to no more than 0.1 seconds to prevent
+    // excessive movement after pauses for loading or initialization.
+    float			DeltaSeconds;
+
+    // It is generally expected that the following hold:
+    // ThisFrameSeconds < TimewarpPointSeconds < NextFrameSeconds < 
+    // EyeScanoutSeconds[EyeOrder[0]] <= ScanoutMidpointSeconds <= EyeScanoutSeconds[EyeOrder[1]]
+
+    // Absolute time value of when rendering of this frame began or is expected to
+    // begin; generally equal to NextFrameSeconds of the previous frame. Can be used
+    // for animation timing.
+    double			ThisFrameSeconds;
+    // Absolute point when IMU expects to be sampled for this frame.
+    double			TimewarpPointSeconds;
+    // Absolute time when frame Present + GPU Flush will finish, and the next frame starts.
+    double			NextFrameSeconds;
+
+    // Time when when half of the screen will be scanned out. Can be passes as a prediction
+    // value to ovrHmd_GetSensorState() go get general orientation.
+    double		    ScanoutMidpointSeconds;
+    // Timing points when each eye will be scanned out to display. Used for rendering each eye. 
+    double			EyeScanoutSeconds[2];    
+
+} ovrFrameTiming;
+
+
+
+// Rendering information for each eye, computed by either ovrHmd_ConfigureRendering().
+// or ovrHmd_GetRenderDesc() based on the specified Fov.
+// Note that the rendering viewport is not included here as it can be 
+// specified separately and modified per frame though:
+//    (a) calling ovrHmd_GetRenderScaleAndOffset with game-rendered api,
+// or (b) passing different values in ovrTexture in case of SDK-rendered distortion.
+typedef struct ovrEyeRenderDesc_
+{    
+    ovrEyeType  Eye;
+    ovrFovPort  Fov;
+	ovrRecti	DistortedViewport; 	        // Distortion viewport 
+    ovrVector2f PixelsPerTanAngleAtCenter;  // How many display pixels will fit in tan(angle) = 1.
+    ovrVector3f ViewAdjust;  		        // Translation to be applied to view matrix.
+} ovrEyeRenderDesc;
+
+
+//-----------------------------------------------------------------------------------
+// ***** Platform-independent Rendering Configuration
+
+// These types are used to hide platform-specific details when passing
+// render device, OS and texture data to the APIs.
+//
+// The benefit of having these wrappers vs. platform-specific API functions is
+// that they allow game glue code to be portable. A typical example is an
+// engine that has multiple back ends, say GL and D3D. Portable code that calls
+// these back ends may also use LibOVR. To do this, back ends can be modified
+// to return portable types such as ovrTexture and ovrRenderAPIConfig.
+
+typedef enum
+{
+    ovrRenderAPI_None,
+    ovrRenderAPI_OpenGL,
+    ovrRenderAPI_Android_GLES,  // May include extra native window pointers, etc.
+    ovrRenderAPI_D3D9,
+    ovrRenderAPI_D3D10,
+    ovrRenderAPI_D3D11,
+    ovrRenderAPI_Count
+} ovrRenderAPIType;
+
+// Platform-independent part of rendering API-configuration data.
+// It is a part of ovrRenderAPIConfig, passed to ovrHmd_Configure.
+typedef struct ovrRenderAPIConfigHeader_
+{
+    ovrRenderAPIType API;
+    ovrSizei         RTSize;
+    int              Multisample;
+} ovrRenderAPIConfigHeader;
+
+typedef struct ovrRenderAPIConfig_
+{
+    ovrRenderAPIConfigHeader Header;
+    uintptr_t                PlatformData[8];
+} ovrRenderAPIConfig;
+
+// Platform-independent part of eye texture descriptor.
+// It is a part of ovrTexture, passed to ovrHmd_EndFrame.
+//  - If RenderViewport is all zeros, will be used.
+typedef struct ovrTextureHeader_
+{
+    ovrRenderAPIType API;    
+    ovrSizei         TextureSize;
+    ovrRecti         RenderViewport;  // Pixel viewport in texture that holds eye image.
+} ovrTextureHeader;
+
+typedef struct ovrTexture_
+{
+    ovrTextureHeader Header;
+    uintptr_t        PlatformData[8];
+} ovrTexture;
+
+
+// -----------------------------------------------------------------------------------
+// ***** API Interfaces
+
+// Basic steps to use the API:
+//
+// Setup:
+//  1. ovrInitialize();
+//  2. ovrHMD hmd = ovrHmd_Create(0);  ovrHmd_GetDesc(hmd, &hmdDesc);
+//  3. Use hmdDesc and ovrHmd_GetFovTextureSize() to determine graphics configuration.
+//  4. Call ovrHmd_StartSensor() to configure and initialize tracking.
+//  5. Call ovrHmd_ConfigureRendering() to setup graphics for SDK rendering,
+//     which is the preferred approach.
+//     Please refer to "Game-Side Rendering" below if you prefer to do that instead.
+//  5. Allocate textures as needed.
+//
+// Game Loop:
+//  6. Call ovrHmd_BeginFrame() to get frame timing and orientation information.
+//  7. Render each eye in between ovrHmd_BeginEyeRender and ovrHmd_EndEyeRender calls,
+//     providing the result texture to the API.
+//  8. Call ovrHmd_EndFrame() to render distorted textures to the back buffer
+//     and present them on the Hmd.
+//
+// Shutdown:
+//  9. ovrHmd_Destroy(hmd)
+//  10. ovr_Shutdown()
+//
+
+#ifdef __cplusplus 
+extern "C" {
+#endif
+
+// Library init/shutdown, must be called around all other OVR code.
+// No other functions calls are allowed before ovr_Initialize succeeds or after ovr_Shutdown.
+OVR_EXPORT ovrBool  ovr_Initialize();
+OVR_EXPORT void     ovr_Shutdown();
+
+
+// Detects or re-detects HMDs and reports the total number detected.
+// Users can get information about each HMD by calling ovrHmd_Create with an index.
+OVR_EXPORT int      ovrHmd_Detect();
+
+
+// Creates a handle to an HMD and optionally fills in data about it.
+// Index can [0 .. ovrHmd_Detect()-1]; index mappings can cange after each ovrHmd_Detect call.
+// If not null, returned handle must be freed with ovrHmd_Destroy.
+OVR_EXPORT ovrHmd   ovrHmd_Create(int index);
+OVR_EXPORT void     ovrHmd_Destroy(ovrHmd hmd);
+
+// Creates a "fake" HMD used for debugging only. This is not tied to specific hardware,
+// but may be used to debug some of the related rendering.
+OVR_EXPORT ovrHmd   ovrHmd_CreateDebug(ovrHmdType type);
+
+
+// Returns last error for HMD state. Returns null for no error.
+// String is valid until next call or GetLastError or HMD is destroyed.
+// Pass null hmd to get global error (for create, etc).
+OVR_EXPORT const char* ovrHmd_GetLastError(ovrHmd hmd);
+
+
+//-------------------------------------------------------------------------------------
+
+// Returns capability bits that are enabled at this time; described by ovrHmdCaps.
+// Note that this value is different font ovrHmdDesc::HmdCaps, which describes what
+// capabilities are available.
+OVR_EXPORT unsigned int ovrHmd_GetEnabledCaps(ovrHmd hmd);
+
+// Modifies capability bits described by ovrHmdCaps that can be modified,
+// such as ovrHmd_LowPersistance.
+OVR_EXPORT void         ovrHmd_SetEnabledCaps(ovrHmd hmd, unsigned int hmdCaps);
+
+
+//-------------------------------------------------------------------------------------
+// ***** Sensor Interface
+
+// All sensor interface functions are thread-safe, allowing sensor state to be sampled
+// from different threads.
+// Starts sensor sampling, enabling specified capabilities, described by ovrSensorCaps.
+//  - supportedSensorCaps specifies support that is requested. The function will succeed 
+//	  even if these caps are not available (i.e. sensor or camera is unplugged). Support
+//    will automatically be enabled if such device is plugged in later. Software should
+//    check ovrSensorState.StatusFlags for real-time status.
+//  - requiredSensorCaps specify sensor capabilities required at the time of the call.
+//    If they are not available, the function will fail. Pass 0 if only specifying
+//    supportedSensorCaps.
+OVR_EXPORT ovrBool  ovrHmd_StartSensor(ovrHmd hmd,	unsigned int supportedSensorCaps,
+													unsigned int requiredSensorCaps);
+// Stops sensor sampling, shutting down internal resources.
+OVR_EXPORT void     ovrHmd_StopSensor(ovrHmd hmd);
+// Resets sensor orientation.
+OVR_EXPORT void     ovrHmd_ResetSensor(ovrHmd hmd);
+
+// Returns sensor state reading based on the specified absolute system time.
+// Pass absTime value of 0.0 to request the most recent sensor reading; in this case
+// both PredictedPose and SamplePose will have the same value.
+// ovrHmd_GetEyePredictedSensorState relies on this internally.
+// This may also be used for more refined timing of FrontBuffer rendering logic, etc.
+OVR_EXPORT ovrSensorState ovrHmd_GetSensorState(ovrHmd hmd, double absTime);
+
+// Returns information about a sensor.
+// Only valid after StartSensor.
+OVR_EXPORT ovrBool     ovrHmd_GetSensorDesc(ovrHmd hmd, ovrSensorDesc* descOut);
+
+
+//-------------------------------------------------------------------------------------
+// ***** Graphics Setup
+
+// Fills in description about HMD; this is the same as filled in by ovrHmd_Create.
+OVR_EXPORT void     ovrHmd_GetDesc(ovrHmd hmd, ovrHmdDesc* desc);
+
+// Calculates texture size recommended for rendering one eye within HMD, given FOV cone.
+// Higher FOV will generally require larger textures to maintain quality.
+//  - pixelsPerDisplayPixel specifies that number of render target pixels per display
+//    pixel at center of distortion; 1.0 is the default value. Lower values
+//    can improve performance.
+OVR_EXPORT ovrSizei ovrHmd_GetFovTextureSize(ovrHmd hmd, ovrEyeType eye, ovrFovPort fov,
+                                             float pixelsPerDisplayPixel);
+
+
+
+//-------------------------------------------------------------------------------------
+// *****  Rendering API Thread Safety
+
+//  All of rendering APIs, inclusing Configure and frame functions are *NOT
+//  Thread Safe*.  It is ok to use ConfigureRendering on one thread and handle
+//  frames on another thread, but explicit synchronization must be done since
+//  functions that depend on configured state are not reentrant.
+//
+//  As an extra requirement, any of the following calls must be done on
+//  the render thread, which is the same thread that calls ovrHmd_BeginFrame
+//  or ovrHmd_BeginFrameTiming.
+//    - ovrHmd_EndFrame
+//    - ovrHmd_BeginEyeRender
+//    - ovrHmd_EndEyeRender
+//    - ovrHmd_GetFramePointTime
+//    - ovrHmd_GetEyePose
+//    - ovrHmd_GetEyeTimewarpMatrices
+
+
+//-------------------------------------------------------------------------------------
+// *****  SDK-Rendering Functions
+
+// These functions support rendering of distortion by the SDK through direct
+// access to the underlying rendering HW, such as D3D or GL.
+// This is the recommended approach, as it allows for better support or future
+// Oculus hardware and a range of low-level optimizations.
+
+
+// Configures rendering; fills in computed render parameters.
+// This function can be called multiple times to change rendering settings.
+// The users pass in two eye view descriptors that are used to
+// generate complete rendering information for each eye in eyeRenderDescOut[2].
+//
+//  - apiConfig provides D3D/OpenGL specific parameters. Pass null
+//    to shutdown rendering and release all resources.
+//  - distortionCaps describe distortion settings that will be applied.
+//
+OVR_EXPORT ovrBool ovrHmd_ConfigureRendering( ovrHmd hmd,
+                                              const ovrRenderAPIConfig* apiConfig,                                              
+                                              unsigned int distortionCaps,
+                                              const ovrFovPort eyeFovIn[2],
+                                              ovrEyeRenderDesc eyeRenderDescOut[2] );
+
+
+// Begins a frame, returning timing and orientation information useful for simulation.
+// This should be called in the beginning of game rendering loop (on render thread).
+// This function relies on ovrHmd_BeginFrameTiming for some of its functionality.
+// Pass 0 for frame index if not using GetFrameTiming.
+OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrame(ovrHmd hmd, unsigned int frameIndex);
+
+// Ends frame, rendering textures to frame buffer. This may perform distortion and scaling
+// internally, assuming is it not delegated to another thread. 
+// Must be called on the same thread as BeginFrame. Calls ovrHmd_BeginEndTiming internally.
+// *** This Function will to Present/SwapBuffers and potentially wait for GPU Sync ***.
+OVR_EXPORT void     ovrHmd_EndFrame(ovrHmd hmd);
+
+
+// Marks beginning of eye rendering. Must be called on the same thread as BeginFrame.
+// This function uses ovrHmd_GetEyePose to predict sensor state that should be
+// used rendering the specified eye.
+// This combines current absolute time with prediction that is appropriate for this HMD.
+// It is ok to call ovrHmd_BeginEyeRender() on both eyes before calling ovrHmd_EndEyeRender.
+// If rendering one eye at a time, it is best to render eye specified by
+// HmdDesc.EyeRenderOrder[0] first.
+OVR_EXPORT ovrPosef ovrHmd_BeginEyeRender(ovrHmd hmd, ovrEyeType eye);
+
+// Marks the end of eye rendering and submits the eye texture for display after it is ready.
+// Rendering viewport within the texture can change per frame if necessary.
+// Specified texture may be presented immediately or wait until ovrHmd_EndFrame based
+// on the implementation. The API performs distortion and scaling internally.
+// 'renderPose' will typically be the value returned from ovrHmd_BeginEyeRender, but can
+// be different if a different pose was used for rendering.
+OVR_EXPORT void     ovrHmd_EndEyeRender(ovrHmd hmd, ovrEyeType eye,
+                                        ovrPosef renderPose, ovrTexture* eyeTexture);
+
+
+
+//-------------------------------------------------------------------------------------
+// *****  Game-Side Rendering Functions
+
+// These functions provide distortion data and render timing support necessary to allow
+// game rendering of distortion. Game-side rendering involves the following steps:
+//
+//  1. Setup ovrEyeDesc based on desired texture size and Fov.
+//     Call ovrHmd_GetRenderDesc to get the necessary rendering parameters for each eye.
+// 
+//  2. Use ovrHmd_CreateDistortionMesh to generate distortion mesh.
+//
+//  3. Use ovrHmd_BeginFrameTiming, ovrHmd_GetEyePose and ovrHmd_BeginFrameTiming
+//     in the rendering loop to obtain timing and predicted view orientation for
+//     each eye.
+//      - If relying on timewarp, use ovr_WaitTillTime after rendering+flush, followed
+//        by ovrHmd_GetEyeTimewarpMatrices to obtain timewarp matrices used 
+//        in distortion pixel shader to reduce latency.
+//
+
+// Computes distortion viewport, view adjust and other rendering for the specified
+// eye. This can be used instead of ovrHmd_ConfigureRendering to help setup rendering on
+// the game side.
+OVR_EXPORT ovrEyeRenderDesc ovrHmd_GetRenderDesc(ovrHmd hmd,
+                                                 ovrEyeType eyeType, ovrFovPort fov);
+
+
+// Describes a vertex used for distortion; this is intended to be converted into
+// the engine-specific format.
+// Some fields may be unused based on ovrDistortionCaps selected. TexG and TexB, for example,
+// are not used if chromatic correction is not requested.
+typedef struct ovrDistortionVertex_
+{
+    ovrVector2f Pos;
+    float       TimeWarpFactor;  // Lerp factor between time-warp matrices. Can be encoded in Pos.z.
+    float       VignetteFactor;  // Vignette fade factor. Can be encoded in Pos.w.
+    ovrVector2f TexR;
+    ovrVector2f TexG;
+    ovrVector2f TexB;    
+} ovrDistortionVertex;
+
+// Describes a full set of distortion mesh data, filled in by ovrHmd_CreateDistortionMesh.
+// Contents of this data structure, if not null, should be freed by ovrHmd_DestroyDistortionMesh.
+typedef struct ovrDistortionMesh_
+{
+    ovrDistortionVertex* pVertexData;
+    unsigned short*      pIndexData;
+    unsigned int         VertexCount;
+    unsigned int         IndexCount;
+} ovrDistortionMesh;
+
+// Generate distortion mesh per eye.
+// Distortion capabilities will depend on 'distortionCaps' flags; user should rely on
+// appropriate shaders based on their settings.
+// Distortion mesh data will be allocated and stored into the ovrDistortionMesh data structure,
+// which should be explicitly freed with ovrHmd_DestroyDistortionMesh.
+// Users should call ovrHmd_GetRenderScaleAndOffset to get uvScale and Offset values for rendering.
+// The function shouldn't fail unless theres is a configuration or memory error, in which case
+// ovrDistortionMesh values will be set to null.
+OVR_EXPORT ovrBool  ovrHmd_CreateDistortionMesh( ovrHmd hmd,
+                                                 ovrEyeType eyeType, ovrFovPort fov,
+                                                 unsigned int distortionCaps,
+                                                 ovrDistortionMesh *meshData );
+
+// Frees distortion mesh allocated by ovrHmd_GenerateDistortionMesh. meshData elements
+// are set to null and zeroes after the call.
+OVR_EXPORT void     ovrHmd_DestroyDistortionMesh( ovrDistortionMesh* meshData );
+
+// Computes updated 'uvScaleOffsetOut' to be used with a distortion if render target size or
+// viewport changes after the fact. This can be used to adjust render size every frame, if desired.
+OVR_EXPORT void     ovrHmd_GetRenderScaleAndOffset( ovrFovPort fov,
+                                                    ovrSizei textureSize, ovrRecti renderViewport,
+                                                    ovrVector2f uvScaleOffsetOut[2] );
+
+
+// Thread-safe timing function for the main thread. Caller should increment frameIndex
+// with every frame and pass the index to RenderThread for processing.
+OVR_EXPORT ovrFrameTiming ovrHmd_GetFrameTiming(ovrHmd hmd, unsigned int frameIndex);
+
+// Called at the beginning of the frame on the Render Thread.
+// Pass frameIndex == 0 if ovrHmd_GetFrameTiming isn't being used. Otherwise,
+// pass the same frame index as was used for GetFrameTiming on the main thread.
+OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrameTiming(ovrHmd hmd, unsigned int frameIndex);
+
+// Marks the end of game-rendered frame, tracking the necessary timing information. This
+// function must be called immediately after Present/SwapBuffers + GPU sync. GPU sync is important
+// before this call to reduce latency and ensure proper timing.
+OVR_EXPORT void     ovrHmd_EndFrameTiming(ovrHmd hmd);
+
+// Initializes and resets frame time tracking. This is typically not necessary, but
+// is helpful if game changes vsync state or video mode. vsync is assumed to be on if this
+// isn't called. Resets internal frame index to the specified number.
+OVR_EXPORT void     ovrHmd_ResetFrameTiming(ovrHmd hmd, unsigned int frameIndex);
+
+
+// Predicts and returns Pose that should be used rendering the specified eye.
+// Must be called between ovrHmd_BeginFrameTiming & ovrHmd_EndFrameTiming.
+OVR_EXPORT ovrPosef ovrHmd_GetEyePose(ovrHmd hmd, ovrEyeType eye);
+
+// Computes timewarp matrices used by distortion mesh shader, these are used to adjust
+// for orientation change since the last call to ovrHmd_GetEyePose for this eye.
+// The ovrDistortionVertex::TimeWarpFactor is used to blend between the matrices,
+// usually representing two different sides of the screen.
+// Must be called on the same thread as ovrHmd_BeginFrameTiming.
+OVR_EXPORT void     ovrHmd_GetEyeTimewarpMatrices(ovrHmd hmd, ovrEyeType eye,
+                                                  ovrPosef renderPose, ovrMatrix4f twmOut[2]);
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** Stateless math setup functions
+
+// Used to generate projection from ovrEyeDesc::Fov.
+OVR_EXPORT ovrMatrix4f ovrMatrix4f_Projection( ovrFovPort fov,
+                                               float znear, float zfar, ovrBool rightHanded );
+
+// Used for 2D rendering, Y is down
+// orthoScale = 1.0f / pixelsPerTanAngleAtCenter
+// orthoDistance = distance from camera, such as 0.8m
+OVR_EXPORT ovrMatrix4f ovrMatrix4f_OrthoSubProjection(ovrMatrix4f projection, ovrVector2f orthoScale,
+                                                      float orthoDistance, float eyeViewAdjustX);
+
+// Returns global, absolute high-resolution time in seconds. This is the same
+// value as used in sensor messages.
+OVR_EXPORT double   ovr_GetTimeInSeconds();
+
+// Waits until the specified absolute time.
+OVR_EXPORT double   ovr_WaitTillTime(double absTime);
+
+
+
+// -----------------------------------------------------------------------------------
+// ***** Latency Test interface
+
+// Does latency test processing and returns 'TRUE' if specified rgb color should
+// be used to clear the screen.
+OVR_EXPORT ovrBool      ovrHmd_ProcessLatencyTest(ovrHmd hmd, unsigned char rgbColorOut[3]);
+
+// Returns non-null string once with latency test result, when it is available.
+// Buffer is valid until next call.
+OVR_EXPORT const char*  ovrHmd_GetLatencyTestResult(ovrHmd hmd);
+
+// Returns latency for HMDs that support internal latency testing via the
+// pixel-read back method (-1 for invalid or N/A)
+OVR_EXPORT double       ovrHmd_GetMeasuredLatencyTest2(ovrHmd hmd);
+
+
+// -----------------------------------------------------------------------------------
+// ***** Property Access
+
+// NOTICE: This is experimental part of API that is likely to go away or change.
+
+// These allow accessing different properties of the HMD and profile.
+// Some of the properties may go away with profile/HMD versions, so software should
+// use defaults and/or proper fallbacks.
+// 
+
+// For now, access profile entries; this will change.
+#if !defined(OVR_KEY_USER)
+
+    #define OVR_KEY_USER                        "User"
+    #define OVR_KEY_NAME                        "Name"
+    #define OVR_KEY_GENDER                      "Gender"
+    #define OVR_KEY_PLAYER_HEIGHT               "PlayerHeight"
+    #define OVR_KEY_EYE_HEIGHT                  "EyeHeight"
+    #define OVR_KEY_IPD                         "IPD"
+    #define OVR_KEY_NECK_TO_EYE_HORIZONTAL      "NeckEyeHori"
+    #define OVR_KEY_NECK_TO_EYE_VERTICAL        "NeckEyeVert"
+
+    #define OVR_DEFAULT_GENDER                  "Male"
+    #define OVR_DEFAULT_PLAYER_HEIGHT           1.778f
+    #define OVR_DEFAULT_EYE_HEIGHT              1.675f
+    #define OVR_DEFAULT_IPD                     0.064f
+    #define OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL  0.12f
+    #define OVR_DEFAULT_NECK_TO_EYE_VERTICAL    0.12f
+#endif
+
+
+// Get float property. Returns first element if property is a float array.
+// Returns defaultValue if property doesn't exist.
+OVR_EXPORT float       ovrHmd_GetFloat(ovrHmd hmd, const char* propertyName, float defaultVal);
+
+// Modify float property; false if property doesn't exist or is readonly.
+OVR_EXPORT ovrBool      ovrHmd_SetFloat(ovrHmd hmd, const char* propertyName, float value);
+
+
+// Get float[] property. Returns the number of elements filled in, 0 if property doesn't exist.
+// Maximum of arraySize elements will be written.
+OVR_EXPORT unsigned int ovrHmd_GetFloatArray(ovrHmd hmd, const char* propertyName,
+                                            float values[], unsigned int arraySize);
+
+// Modify float[] property; false if property doesn't exist or is readonly.
+OVR_EXPORT ovrBool      ovrHmd_SetFloatArray(ovrHmd hmd, const char* propertyName,
+                                             float values[], unsigned int arraySize);
+
+// Get string property. Returns first element if property is a string array.
+// Returns defaultValue if property doesn't exist.
+// String memory is guaranteed to exist until next call to GetString or GetStringArray, or HMD is destroyed.
+OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmd, const char* propertyName,
+                                        const char* defaultVal);
+
+// Returns array size of a property, 0 if property doesn't exist.
+// Can be used to check existence of a property.
+OVR_EXPORT unsigned int ovrHmd_GetArraySize(ovrHmd hmd, const char* propertyName);
+
+
+#ifdef __cplusplus 
+} // extern "C"
+#endif
+
+
+#endif	// OVR_CAPI_h
diff --git a/LibOVR/Src/OVR_CAPI_GL.h b/LibOVR/Src/OVR_CAPI_GL.h
new file mode 100644
index 0000000..ceabb74
--- /dev/null
+++ b/LibOVR/Src/OVR_CAPI_GL.h
@@ -0,0 +1,73 @@
+/************************************************************************************
+
+Filename    :   OVR_CAPI_GL.h
+Content     :   GL specific structures used by the CAPI interface.
+Created     :   November 7, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
+
+Use of this software is subject to the terms of the Oculus Inc license
+agreement provided at the time of installation or download, or which
+otherwise accompanies this software in either electronic or hard copy form.
+
+************************************************************************************/
+#ifndef OVR_CAPI_GL_h
+#define OVR_CAPI_GL_h
+
+#include "OVR_CAPI.h"
+
+//-----------------------------------------------------------------------------------
+// ***** GL Specific
+
+#if defined(OVR_OS_WIN32)
+    #include <Windows.h>
+    #include <GL/gl.h>
+    #include <GL/glext.h>
+    #include <GL/wglext.h>
+#elif defined(OVR_OS_MAC)
+    #include <OpenGL/gl3.h>
+    #include <OpenGL/gl3ext.h>
+    #include <OpenGL/OpenGL.h>
+#else
+    #include <GL/gl.h>
+    #include <GL/glext.h>
+    #include <GL/glx.h>
+#endif
+
+
+// Used to configure slave GL rendering (i.e. for devices created externally).
+typedef struct ovrGLConfigData_s
+{
+    // General device settings.
+    ovrRenderAPIConfigHeader Header;
+
+#if defined(OVR_OS_WIN32)
+    HWND   Window;
+#elif defined(OVR_OS_LINUX)
+    Display* Disp;
+    Window  Win;
+#endif
+} ovrGLConfigData;
+
+union ovrGLConfig
+{
+    ovrRenderAPIConfig Config;
+    ovrGLConfigData OGL;
+};
+
+// Used to pass GL eye texture data to ovrHmd_EndFrame.
+typedef struct ovrGLTextureData_s
+{
+    // General device settings.
+    ovrTextureHeader          Header;
+    GLuint           TexId;       
+} ovrGLTextureData;
+
+typedef union ovrGLTexture_s
+{
+    ovrTexture          Texture;
+    ovrGLTextureData	OGL;
+} ovrGLTexture;
+
+#endif	// OVR_CAPI_GL_h
diff --git a/LibOVR/Src/OVR_Common_HMDDevice.cpp b/LibOVR/Src/OVR_Common_HMDDevice.cpp
new file mode 100644
index 0000000..6bedcbe
--- /dev/null
+++ b/LibOVR/Src/OVR_Common_HMDDevice.cpp
@@ -0,0 +1,384 @@
+/************************************************************************************
+
+Filename    :   OVR_Common_HMDDevice.cpp
+Content     :   
+Created     :
+Authors     :
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+// Should be #included from the relevant OVR_YourPlatformHere_HMDDevice.cpp
+
+#include "Kernel/OVR_Alg.h"
+
+//-------------------------------------------------------------------------------------
+// ***** HMDDeviceCreateDesc
+
+DeviceBase* HMDDeviceCreateDesc::NewDeviceInstance()
+{
+    return new HMDDevice(this);
+}
+
+void  HMDDeviceCreateDesc::SetScreenParameters(int x, int y,
+                              int hres, int vres,
+                              float hsize, float vsize,
+                              float vCenterFromTopInMeters, float lensSeparationInMeters)
+{
+    Desktop.X = x;
+    Desktop.Y = y;
+    ResolutionInPixels = Sizei(hres, vres);
+    ScreenSizeInMeters = Sizef(hsize, vsize);
+    VCenterFromTopInMeters = vCenterFromTopInMeters;
+    LensSeparationInMeters = lensSeparationInMeters;
+
+    Contents |= Contents_Screen;
+}
+
+
+void HMDDeviceCreateDesc::SetDistortion(const float* dks)
+{
+    for (int i = 0; i < 4; i++)
+        DistortionK[i] = dks[i];
+    // TODO: add DistortionEqn
+    Contents |= Contents_Distortion;
+}
+
+HmdTypeEnum HMDDeviceCreateDesc::GetHmdType() const
+{
+    // Determine the HMD model
+    // The closest thing we have to a dependable model indicator are the 
+    // the screen characteristics.  Additionally we can check the sensor
+    // (on attached devices) to further refine our guess
+    HmdTypeEnum hmdType = HmdType_Unknown;
+
+    if ( ResolutionInPixels.w == 1280 )
+    {
+        if ( ScreenSizeInMeters.w > 0.1497f && ScreenSizeInMeters.w < 0.1498f )
+            hmdType = HmdType_DK1;
+        else
+            hmdType = HmdType_DKProto;
+    }
+    else if ( ResolutionInPixels.w == 1920 )
+    {
+        // DKHD protoypes, all 1920x1080
+        if ( ScreenSizeInMeters.w > 0.1209f && ScreenSizeInMeters.w < 0.1210f )
+        {
+            // Screen size 0.12096 x 0.06804
+            hmdType = HmdType_DKHDProto;
+        }
+        else if ( ScreenSizeInMeters.w > 0.1257f && ScreenSizeInMeters.w < 0.1258f )
+        {
+            // Screen size 0.125 x 0.071
+            // Could be a HmdType_DKHDProto566Mi, HmdType_CrystalCoveProto, or DK2
+            // - most likely the latter.
+            hmdType = HmdType_DK2;
+
+            // If available, check the sensor to determine exactly which variant this is
+            if (pDevice)
+            {
+                Ptr<SensorDevice> sensor = *((HMDDevice*)pDevice)->GetSensor();
+                
+                SensorInfo sinfo;
+                if (sensor && sensor->GetDeviceInfo(&sinfo))
+                {
+                    if (sinfo.ProductId == 1)
+                    {
+                        hmdType = HmdType_DKHDProto566Mi;
+                    }
+                    else
+                    {   // Crystal Cove uses 0.# firmware, DK2 uses 1.#
+                        int firm_major = Alg::DecodeBCD((sinfo.Version >> 8) & 0x00ff);
+                        int firm_minor = Alg::DecodeBCD(sinfo.Version & 0xff);
+                        OVR_UNUSED(firm_minor);
+                        if (firm_major == 0)
+                            hmdType = HmdType_CrystalCoveProto;
+                        else
+                            hmdType = HmdType_DK2;
+                    }
+                }
+            }
+        }
+        else if (ScreenSizeInMeters.w > 0.1295f && ScreenSizeInMeters.w < 0.1297f)
+        {
+            // Screen size 0.1296 x 0.0729
+            hmdType = HmdType_DKHD2Proto;
+        }
+    }
+    
+    OVR_ASSERT( hmdType != HmdType_Unknown );
+    return hmdType;
+}
+
+bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
+{
+    if ((info->InfoClassType != Device_HMD) &&
+        (info->InfoClassType != Device_None))
+        return false;
+
+    HmdTypeEnum hmdType = GetHmdType();
+    char const* deviceName = "Oculus HMD";
+    switch (hmdType)
+    {
+        case HmdType_DKProto:          deviceName = "Oculus Rift Prototype";    break;
+        case HmdType_DK1:              deviceName = "Oculus Rift DK1";          break;
+        case HmdType_DKHDProto:        deviceName = "Oculus Rift DKHD";         break;
+        case HmdType_DKHD2Proto:       deviceName = "Oculus Rift DKHD2";        break;
+        case HmdType_DKHDProto566Mi:   deviceName = "Oculus Rift DKHD 566 Mi";  break;
+        case HmdType_CrystalCoveProto: deviceName = "Oculus Rift Crystal Cove"; break;
+        case HmdType_DK2:              deviceName = "Oculus Rift DK2";          break;
+        default:                       deviceName = "Oculus HMD";               break;
+    }
+   
+    info->ProductName = deviceName;
+    info->Manufacturer = "Oculus VR";
+    info->Type    = Device_HMD;
+    info->Version = 0;
+
+    // Display detection.
+    if (info->InfoClassType == Device_HMD)
+    {
+        HMDInfo* hmdInfo = static_cast<HMDInfo*>(info);
+
+        hmdInfo->HmdType                = hmdType;
+        hmdInfo->DesktopX               = Desktop.X;
+        hmdInfo->DesktopY               = Desktop.Y;
+        hmdInfo->ResolutionInPixels     = ResolutionInPixels;                
+        hmdInfo->ScreenSizeInMeters     = ScreenSizeInMeters;        // Includes ScreenGapSizeInMeters
+        hmdInfo->ScreenGapSizeInMeters  = 0.0f;
+        hmdInfo->CenterFromTopInMeters  = VCenterFromTopInMeters;
+        hmdInfo->LensSeparationInMeters = LensSeparationInMeters;
+        // TODO: any other information we get from the hardware itself should be added to this list
+
+        switch ( hmdInfo->HmdType )
+        {
+        case HmdType_DKProto:
+            // WARNING - estimated.
+            hmdInfo->Shutter.Type                             = HmdShutter_RollingTopToBottom;
+            hmdInfo->Shutter.VsyncToNextVsync                 = ( 1.0f / 60.0f );
+            hmdInfo->Shutter.VsyncToFirstScanline             = 0.000052f;
+            hmdInfo->Shutter.FirstScanlineToLastScanline      = 0.016580f;
+            hmdInfo->Shutter.PixelSettleTime                  = 0.015f; // estimated.
+            hmdInfo->Shutter.PixelPersistence                 = hmdInfo->Shutter.VsyncToNextVsync; // Full persistence
+            break;
+        case HmdType_DK1:
+            // Data from specs.
+            hmdInfo->Shutter.Type                             = HmdShutter_RollingTopToBottom;
+            hmdInfo->Shutter.VsyncToNextVsync                 = ( 1.0f / 60.0f );
+            hmdInfo->Shutter.VsyncToFirstScanline             = 0.00018226f;
+            hmdInfo->Shutter.FirstScanlineToLastScanline      = 0.01620089f;
+            hmdInfo->Shutter.PixelSettleTime                  = 0.017f; // estimated.
+            hmdInfo->Shutter.PixelPersistence                 = hmdInfo->Shutter.VsyncToNextVsync; // Full persistence
+            break;
+        case HmdType_DKHDProto:
+            // Data from specs.
+            hmdInfo->Shutter.Type                             = HmdShutter_RollingRightToLeft;
+            hmdInfo->Shutter.VsyncToNextVsync                 = ( 1.0f / 60.0f );
+            hmdInfo->Shutter.VsyncToFirstScanline             = 0.0000859f;
+            hmdInfo->Shutter.FirstScanlineToLastScanline      = 0.0164948f;
+            hmdInfo->Shutter.PixelSettleTime                  = 0.012f; // estimated.
+            hmdInfo->Shutter.PixelPersistence                 = hmdInfo->Shutter.VsyncToNextVsync; // Full persistence
+            break;
+        case HmdType_DKHD2Proto:
+            // Data from specs.
+            hmdInfo->Shutter.Type                             = HmdShutter_RollingRightToLeft;
+            hmdInfo->Shutter.VsyncToNextVsync                 = ( 1.0f / 60.0f );
+            hmdInfo->Shutter.VsyncToFirstScanline             = 0.000052f;
+            hmdInfo->Shutter.FirstScanlineToLastScanline      = 0.016580f;
+            hmdInfo->Shutter.PixelSettleTime                  = 0.015f; // estimated.
+            hmdInfo->Shutter.PixelPersistence                 = hmdInfo->Shutter.VsyncToNextVsync; // Full persistence
+            break;
+        case HmdType_DKHDProto566Mi:
+#if 0
+            // Low-persistence global shutter
+            hmdInfo->Shutter.Type                             = HmdShutter_Global;
+            hmdInfo->Shutter.VsyncToNextVsync                 = ( 1.0f / 76.0f );
+            hmdInfo->Shutter.VsyncToFirstScanline             = 0.0000273f + 0.0131033f;    // Global shutter - first visible scan line is actually the last!
+            hmdInfo->Shutter.FirstScanlineToLastScanline      = 0.000f;                     // Global shutter - all visible at once.
+            hmdInfo->Shutter.PixelSettleTime                  = 0.0f;                       // <100us
+            hmdInfo->Shutter.PixelPersistence                 = 0.18f * hmdInfo->Shutter.VsyncToNextVsync;     // Confgurable - currently set to 18% of total frame.
+#else
+            // Low-persistence rolling shutter
+            hmdInfo->Shutter.Type                             = HmdShutter_RollingRightToLeft;
+            hmdInfo->Shutter.VsyncToNextVsync                 = ( 1.0f / 76.0f );
+            hmdInfo->Shutter.VsyncToFirstScanline             = 0.0000273f;
+            hmdInfo->Shutter.FirstScanlineToLastScanline      = 0.0131033f;
+            hmdInfo->Shutter.PixelSettleTime                  = 0.0f;                       // <100us
+            hmdInfo->Shutter.PixelPersistence                 = 0.18f * hmdInfo->Shutter.VsyncToNextVsync;     // Confgurable - currently set to 18% of total frame.
+#endif
+            break;
+        case HmdType_CrystalCoveProto:
+            // Low-persistence rolling shutter
+            hmdInfo->Shutter.Type                             = HmdShutter_RollingRightToLeft;
+            hmdInfo->Shutter.VsyncToNextVsync                 = ( 1.0f / 76.0f );
+            hmdInfo->Shutter.VsyncToFirstScanline             = 0.0000273f;
+            hmdInfo->Shutter.FirstScanlineToLastScanline      = 0.0131033f;
+            hmdInfo->Shutter.PixelSettleTime                  = 0.0f;                       // <100us
+            hmdInfo->Shutter.PixelPersistence                 = 0.18f * hmdInfo->Shutter.VsyncToNextVsync;     // Confgurable - currently set to 18% of total frame.
+            break;
+        case HmdType_DK2:
+            // Low-persistence rolling shutter
+            hmdInfo->Shutter.Type                             = HmdShutter_RollingRightToLeft;
+            hmdInfo->Shutter.VsyncToNextVsync                 = ( 1.0f / 76.0f );
+            hmdInfo->Shutter.VsyncToFirstScanline             = 0.0000273f;
+            hmdInfo->Shutter.FirstScanlineToLastScanline      = 0.0131033f;
+            hmdInfo->Shutter.PixelSettleTime                  = 0.0f;                       // <100us
+            hmdInfo->Shutter.PixelPersistence                 = 0.18f * hmdInfo->Shutter.VsyncToNextVsync;     // Confgurable - currently set to 18% of total frame.
+            break;
+        default: OVR_ASSERT ( false ); break;
+        }
+
+
+        OVR_strcpy(hmdInfo->DisplayDeviceName, sizeof(hmdInfo->DisplayDeviceName),
+                   DisplayDeviceName.ToCStr());
+#if   defined(OVR_OS_WIN32)
+        // Nothing special for Win32.
+#elif defined(OVR_OS_MAC)
+        hmdInfo->DisplayId = DisplayId;
+#elif defined(OVR_OS_LINUX)
+        hmdInfo->DisplayId = DisplayId;
+#elif defined(OVR_OS_ANDROID)
+        hmdInfo->DisplayId = DisplayId;
+#else
+#error Unknown platform
+#endif
+
+    }
+
+    return true;
+}
+
+
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** HMDDevice
+
+HMDDevice::HMDDevice(HMDDeviceCreateDesc* createDesc)
+    : OVR::DeviceImpl<OVR::HMDDevice>(createDesc, 0)
+{
+}
+HMDDevice::~HMDDevice()
+{
+}
+
+bool HMDDevice::Initialize(DeviceBase* parent)
+{
+    pParent = parent;
+    return true;
+}
+void HMDDevice::Shutdown()
+{
+    ProfileName.Clear();
+    pCachedProfile.Clear();
+    pParent.Clear();
+}
+
+Profile* HMDDevice::GetProfile()
+{    
+    // Loads and returns a cached profile based on this device and current user
+    if (pCachedProfile == NULL)
+    {
+        ProfileManager* mgr = GetManager()->GetProfileManager();
+        const char* profile_name = GetProfileName();
+        if (profile_name && profile_name[0])
+            pCachedProfile = *mgr->GetProfile(this, profile_name);
+
+        if (pCachedProfile == NULL)
+            pCachedProfile = *mgr->GetDefaultProfile(this);
+        
+    }
+    return pCachedProfile.GetPtr();
+}
+
+const char* HMDDevice::GetProfileName()
+{
+    if (ProfileName.IsEmpty())
+    {   // If the profile name has not been initialized then
+        // retrieve the stored default user for this specific device
+        ProfileManager* mgr = GetManager()->GetProfileManager();
+        const char* name = mgr->GetDefaultUser(this);
+        ProfileName = name;
+    }
+    
+    return ProfileName.ToCStr();
+}
+
+bool HMDDevice::SetProfileName(const char* name)
+{
+    if (ProfileName == name)
+        return true;   // already set
+    
+    // Flush the old profile
+    pCachedProfile.Clear();
+    if (!name)
+    {
+        ProfileName.Clear();
+        return false;
+    }
+
+    // Set the name and attempt to cache the profile
+    ProfileName = name;
+    if (GetProfile())
+    {
+        return true;
+    }
+    else
+    {
+        ProfileName.Clear();
+        return false;
+    }
+}
+
+OVR::SensorDevice* HMDDevice::GetSensor()
+{
+    // Just return first sensor found since we have no way to match it yet.    
+
+	// Create DK2 sensor if it exists otherwise create first DK1 sensor.
+    SensorDevice* sensor = NULL;
+
+    DeviceEnumerator<SensorDevice> enumerator = GetManager()->EnumerateDevices<SensorDevice>();
+
+    while(enumerator.GetType() != Device_None)
+    {
+        SensorInfo info;
+        enumerator.GetDeviceInfo(&info);
+      
+        if (info.ProductId == Device_Tracker2_ProductId)
+        {
+            sensor = enumerator.CreateDevice();
+            break;
+        }
+
+        enumerator.Next();
+    }
+
+    if (sensor == NULL)
+    {
+        sensor = GetManager()->EnumerateDevices<SensorDevice>().CreateDevice();
+    }    
+
+    if (sensor)
+	{
+        sensor->SetCoordinateFrame(SensorDevice::Coord_HMD);
+	}
+
+    return sensor;
+}
diff --git a/LibOVR/Src/OVR_Device.h b/LibOVR/Src/OVR_Device.h
new file mode 100644
index 0000000..52a41f9
--- /dev/null
+++ b/LibOVR/Src/OVR_Device.h
@@ -0,0 +1,1135 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Device.h
+Content     :   Definition of HMD-related Device interfaces
+Created     :   September 21, 2012
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Device_h
+#define OVR_Device_h
+
+#include "OVR_DeviceConstants.h"
+#include "OVR_DeviceHandle.h"
+#include "OVR_DeviceMessages.h"
+#include "OVR_HIDDeviceBase.h"
+
+#include "Kernel/OVR_Atomic.h"
+#include "Kernel/OVR_RefCount.h"
+#include "Kernel/OVR_String.h"
+
+
+namespace OVR {
+
+// Declared externally
+class Profile;
+class ProfileManager; // << Should be renamed for consistency
+
+// Forward declarations
+class SensorDevice;
+class DeviceCommon;
+class DeviceManager;
+
+// MessageHandler is a base class from which users derive to receive messages,
+// its OnMessage handler will be called for messages once it is installed on
+// a device. Same message handler can be installed on multiple devices.
+class MessageHandler
+{
+    friend class MessageHandlerImpl;
+public:
+    MessageHandler();
+    virtual ~MessageHandler();
+
+    // Returns 'true' if handler is currently installed on any devices.
+    bool        IsHandlerInstalled() const;
+
+    // Should be called from derived class destructor to avoid handler
+    // being called after it exits.
+    void        RemoveHandlerFromDevices();
+
+    // Returns a pointer to the internal lock object that is locked by a
+    // background thread while OnMessage() is called.
+    // This lock guaranteed to survive until ~MessageHandler.
+    Lock*       GetHandlerLock() const;
+
+
+    virtual void OnMessage(const Message&) { }
+
+    // Determines if handler supports a specific message type. Can
+    // be used to filter out entire message groups. The result
+    // returned by this function shouldn't change after handler creation.
+    virtual bool SupportsMessageType(MessageType) const { return true; }    
+
+private:    
+    UPInt Internal[8];
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceBase
+
+// DeviceBase is the base class for all OVR Devices. It provides the following basic
+// functionality:
+//   - Reports device type, manager, and associated parent (if any).
+//   - Supports installable message handlers, which are notified of device events.
+//   - Device objects are created through DeviceHandle::CreateDevice or more commonly
+//     through DeviceEnumerator<>::CreateDevice.
+//   - Created devices are reference counted, starting with RefCount of 1.
+//   - Device is resources are cleaned up when it is Released, although its handles
+//     may survive longer if referenced.
+
+class DeviceBase : public NewOverrideBase
+{    
+    friend class DeviceHandle;  
+    friend class DeviceManagerImpl;
+public:
+
+    // Enumerating DeviceBase enumerates all devices.
+    enum { EnumDeviceType = Device_All };
+
+    virtual ~DeviceBase() { }
+    virtual void            AddRef();
+    virtual void            Release();
+    
+    virtual DeviceBase*     GetParent() const;
+    virtual DeviceManager*  GetManager() const;  
+
+    virtual void            AddMessageHandler(MessageHandler* handler);
+
+    virtual DeviceType      GetType() const;
+    virtual bool            GetDeviceInfo(DeviceInfo* info) const;
+
+    // Returns true if device is connected and usable
+    virtual bool            IsConnected();
+
+    // returns the MessageHandler's lock
+    Lock*                   GetHandlerLock() const;
+protected:
+    // Internal
+    virtual DeviceCommon*   getDeviceCommon() const = 0;
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceInfo
+
+// DeviceInfo describes a device and its capabilities, obtained by calling
+// GetDeviceInfo. This base class only contains device-independent functionality;
+// users will normally use a derived HMDInfo or SensorInfo classes for more
+// extensive device info.
+
+class DeviceInfo
+{
+public:
+    DeviceInfo() : InfoClassType(Device_None), Type(Device_None), Version(0)
+    {}
+    
+    // Type of device for which DeviceInfo is intended.
+    // This will be set to Device_HMD for HMDInfo structure, note that this may be
+    // different form the actual device type since (Device_None) is valid.
+    const DeviceType    InfoClassType;
+    // Type of device this describes. This must be the same as InfoClassType when
+    // InfoClassType != Device_None.
+    DeviceType          Type;
+    // Name string describing the product: "Oculus Rift DK1", etc.
+    String              ProductName;    
+    String              Manufacturer;
+    unsigned            Version;
+    
+protected:
+    DeviceInfo(DeviceType type) : InfoClassType(type), Type(type), Version(0)
+    {}
+    void operator = (const DeviceInfo&) { OVR_ASSERT(0); } // Assignment not allowed.
+};
+
+
+//-------------------------------------------------------------------------------------
+// DeviceEnumerationArgs provides device enumeration argumenrs for DeviceManager::EnumerateDevicesEx.
+class DeviceEnumerationArgs
+{
+public:
+    DeviceEnumerationArgs(DeviceType enumType, bool availableOnly)
+        : EnumType(enumType), AvailableOnly(availableOnly)
+    { }
+
+    // Helper; returns true if args match our enumeration criteria.
+    bool         MatchRule(DeviceType type, bool available) const
+    {
+        return ((EnumType == type) || (EnumType == Device_All)) &&
+                (available || !AvailableOnly);
+    }
+
+protected:    
+    DeviceType   EnumType;
+    bool         AvailableOnly;
+};
+
+
+// DeviceEnumerator<> is used to enumerate and create devices of specified class,
+// it is returned by calling MeviceManager::EnumerateDevices. Initially, the enumerator will
+// refer to the first device of specified type. Additional devices can be accessed by
+// calling Next().
+
+template<class T = DeviceBase>
+class DeviceEnumerator : public DeviceHandle
+{
+    friend class DeviceManager;
+    friend class DeviceManagerImpl;
+public:
+    DeviceEnumerator()
+        : DeviceHandle(), EnumArgs(Device_None, true) { }
+
+    // Next advances enumeration to the next device that first criteria.
+    // Returns false if no more devices exist that match enumeration criteria.
+    bool    Next()          { return enumerateNext(EnumArgs); }
+
+    // Creates an instance of the device referenced by enumerator; returns null
+    // if enumerator does not refer to a valid device or device is unavailable.
+    // If device was already created, the same object with incremented ref-count is returned.
+    T*      CreateDevice()  { return static_cast<T*>(DeviceHandle::CreateDevice()); }
+
+protected:
+    DeviceEnumerator(const DeviceHandle &dev, const DeviceEnumerationArgs& args)
+        : DeviceHandle(dev), EnumArgs(args)
+    { }
+
+    DeviceEnumerationArgs EnumArgs;
+};
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceManager
+
+// DeviceManager maintains and provides access to devices supported by OVR, such as
+// HMDs and sensors. A single instance of DeviceManager is normally created at
+// program startup, allowing devices to be enumerated and created. DeviceManager is
+// reference counted and is AddRefed by its created child devices, causing it to
+// always be the last object that is released.
+//
+// Install MessageHandler on DeviceManager to detect when devices are inserted or removed.
+//
+// The following code will create the manager and its first available HMDDevice,
+// and then release it when not needed:
+//
+//  DeviceManager* manager = DeviceManager::Create();
+//  HMDDevice*     hmd = manager->EnumerateDevices<HMDDevice>().CreateDevice();
+//
+//  if (hmd) hmd->Release();
+//  if (manager) manager->Release();
+
+
+class DeviceManager : public DeviceBase
+{
+public:
+  
+    DeviceManager()
+    { }
+
+    // DeviceBase implementation.
+    virtual DeviceType      GetType() const     { return Device_Manager; }
+    virtual DeviceManager*  GetManager() const  { return const_cast<DeviceManager*>(this); }
+
+    // Every DeviceManager has an associated profile manager, which us used to store
+    // user settings that may affect device behavior. 
+    virtual ProfileManager* GetProfileManager() const = 0;
+
+
+    // EnumerateDevices enumerates all of the available devices of the specified class,
+    // returning an enumerator that references the first device. An empty enumerator is
+    // returned if no devices are available. The following APIs are exposed through
+    // DeviceEnumerator:
+    //   DeviceEnumerator::GetType()        - Check device type. Returns Device_None 
+    //                                        if no device was found/pointed to.
+    //   DeviceEnumerator::GetDeviceInfo()  - Get more information on device.
+    //   DeviceEnumerator::CreateDevice()   - Create an instance of device.
+    //   DeviceEnumerator::Next()           - Move onto next device.
+    template<class D>
+    DeviceEnumerator<D>     EnumerateDevices(bool availableOnly = true)
+    {
+        // TBD: A cleaner (but less efficient) alternative is though enumeratorFromHandle.
+        DeviceEnumerator<> e = EnumerateDevicesEx(DeviceEnumerationArgs((DeviceType)D::EnumDeviceType, availableOnly));
+        return *reinterpret_cast<DeviceEnumerator<D>*>(&e);
+    }
+  
+    // EnumerateDevicesEx provides internal implementation for device enumeration, enumerating
+    // devices based on dynamically specified DeviceType in DeviceEnumerationArgs.
+    // End users should call DeumerateDevices<>() instead.
+    virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args) = 0;
+
+    // Creates a new DeviceManager. Only one instance of DeviceManager should be created at a time.
+    static   DeviceManager* Create();
+
+    // Static constant for this device type, used in template cast type checks.
+    enum { EnumDeviceType = Device_Manager };
+
+
+
+    // Adds a device (DeviceCreateDesc*) into Devices. Returns NULL, 
+    // if unsuccessful or device is already in the list.
+    virtual Ptr<DeviceCreateDesc> AddDevice_NeedsLock(const DeviceCreateDesc& createDesc) = 0;
+
+protected:
+    DeviceEnumerator<> enumeratorFromHandle(const DeviceHandle& h, const DeviceEnumerationArgs& args)
+    { return DeviceEnumerator<>(h, args); }
+
+    DeviceManager* getThis() { return this; }
+};
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** HMDInfo 
+
+// This structure describes various aspects of the HMD allowing us to configure rendering.
+//
+//  Currently included data:
+//   - Physical screen dimensions, resolution, and eye distances.
+//     (some of these will be configurable with a tool in the future).
+//     These arguments allow us to properly setup projection across HMDs.
+//   - DisplayDeviceName for identifying HMD screen; system-specific interpretation.
+//
+// TBD:
+//  - Power on/ off?
+//  - Sensor rates and capabilities
+//  - Distortion radius/variables    
+//  - Screen update frequency
+//  - Distortion needed flag
+//  - Update modes:
+//      Set update mode: Stereo (both sides together), mono (same in both eyes),
+//                       Alternating, Alternating scan-lines.
+
+class HMDInfo : public DeviceInfo
+{
+public:
+    // Characteristics of the HMD screen and enclosure
+    HmdTypeEnum HmdType;
+    Size<int>   ResolutionInPixels;
+    Size<float> ScreenSizeInMeters;
+    float       ScreenGapSizeInMeters;
+    float       CenterFromTopInMeters;
+    float       LensSeparationInMeters;
+
+    // Timing & shutter data. All values in seconds.
+    struct ShutterInfo
+    {
+        HmdShutterTypeEnum  Type;
+        float               VsyncToNextVsync;                // 1/framerate
+        float               VsyncToFirstScanline;            // for global shutter, vsync->shutter open.
+        float               FirstScanlineToLastScanline;     // for global shutter, will be zero.
+        float               PixelSettleTime;                 // estimated.
+        float               PixelPersistence;                // Full persistence = 1/framerate.
+    }                   Shutter;
+
+    // Desktop coordinate position of the screen (can be negative; may not be present on all platforms)
+    int                 DesktopX;
+    int                 DesktopY;
+    
+    // Windows:
+    // "\\\\.\\DISPLAY3", etc. Can be used in EnumDisplaySettings/CreateDC.
+    char      DisplayDeviceName[32];
+    
+    // MacOS:
+    int      DisplayId;
+
+
+    // Constructor initializes all values to 0s.
+    // To create a "virtualized" HMDInfo, use CreateDebugHMDInfo instead.
+    HMDInfo()
+        : DeviceInfo(Device_HMD),
+          HmdType(HmdType_None),
+          ResolutionInPixels(0),
+          ScreenSizeInMeters(0.0f),
+          ScreenGapSizeInMeters(0.0f),
+          CenterFromTopInMeters(0),
+          LensSeparationInMeters(0),
+          DisplayId(0)
+    {
+        DesktopX = 0;
+        DesktopY = 0;
+        DisplayDeviceName[0] = 0;
+        Shutter.Type = HmdShutter_LAST;
+        Shutter.VsyncToNextVsync = 0.0f;
+        Shutter.VsyncToFirstScanline = 0.0f;
+        Shutter.FirstScanlineToLastScanline = 0.0f;
+        Shutter.PixelSettleTime = 0.0f;
+        Shutter.PixelPersistence = 0.0f;
+    }
+
+    // Operator = copies local fields only (base class must be correct already)
+    void operator = (const HMDInfo& src)
+    {        
+        HmdType                          = src.HmdType;
+        ResolutionInPixels               = src.ResolutionInPixels;      
+        ScreenSizeInMeters               = src.ScreenSizeInMeters;
+        ScreenGapSizeInMeters            = src.ScreenGapSizeInMeters;
+        CenterFromTopInMeters            = src.CenterFromTopInMeters;
+        LensSeparationInMeters           = src.LensSeparationInMeters;
+        DesktopX                         = src.DesktopX;
+        DesktopY                         = src.DesktopY;
+        Shutter                          = src.Shutter;
+        memcpy(DisplayDeviceName, src.DisplayDeviceName, sizeof(DisplayDeviceName));
+
+        DisplayId                        = src.DisplayId;
+    }
+
+    bool IsSameDisplay(const HMDInfo& o) const
+    {
+        return DisplayId == o.DisplayId &&
+               String::CompareNoCase(DisplayDeviceName, 
+                                     o.DisplayDeviceName) == 0;
+    }
+
+};
+
+
+// HMDDevice represents an Oculus HMD device unit. An instance of this class
+// is typically created from the DeviceManager.
+//  After HMD device is created, we its sensor data can be obtained by 
+//  first creating a Sensor object and then.
+
+//  TBD:
+//  - Configure Sensor
+//  - APIs to set On-Screen message, other states?
+
+class HMDDevice : public DeviceBase
+{
+public:
+    HMDDevice()
+    { }
+
+    // Static constant for this device type, used in template cast type checks.
+    enum { EnumDeviceType = Device_HMD };
+
+    virtual DeviceType      GetType() const   { return Device_HMD; }  
+
+    // Creates a sensor associated with this HMD.
+    virtual SensorDevice*   GetSensor() = 0;
+
+
+    // Requests the currently used profile. This profile affects the
+    // settings reported by HMDInfo. 
+    virtual Profile*    GetProfile() = 0;
+    // Obtains the currently used profile name. This is initialized to the default
+    // profile name, if any; it can then be changed per-device by SetProfileName.    
+    virtual const char* GetProfileName() = 0;
+    // Sets the profile user name, changing the data returned by GetProfileInfo.
+    virtual bool        SetProfileName(const char* name) = 0;
+
+
+    // Disconnects from real HMD device. This HMDDevice remains as 'fake' HMD.
+    // SensorDevice ptr is used to restore the 'fake' HMD (can be NULL).
+    HMDDevice*  Disconnect(SensorDevice*);
+    
+    // Returns 'true' if HMD device is a 'fake' HMD (was created this way or 
+    // 'Disconnect' method was called).
+    bool        IsDisconnected() const;
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** SensorRange & SensorInfo
+
+// SensorRange specifies maximum value ranges that SensorDevice hardware is configured
+// to detect. Although this range doesn't affect the scale of MessageBodyFrame values,
+// physical motions whose positive or negative magnitude is outside the specified range
+// may get clamped or misreported. Setting lower values may result in higher precision
+// tracking.
+struct SensorRange
+{
+    SensorRange(float maxAcceleration = 0.0f, float maxRotationRate = 0.0f,
+                float maxMagneticField = 0.0f)
+        : MaxAcceleration(maxAcceleration), MaxRotationRate(maxRotationRate),
+          MaxMagneticField(maxMagneticField)
+    { }
+
+    // Maximum detected acceleration in m/s^2. Up to 8*G equivalent support guaranteed,
+    // where G is ~9.81 m/s^2.
+    // Oculus DK1 HW has thresholds near: 2, 4 (default), 8, 16 G.
+    float   MaxAcceleration;  
+    // Maximum detected angular velocity in rad/s. Up to 8*Pi support guaranteed.
+    // Oculus DK1 HW thresholds near: 1, 2, 4, 8 Pi (default).
+    float   MaxRotationRate;
+    // Maximum detectable Magnetic field strength in Gauss. Up to 2.5 Gauss support guaranteed.
+    // Oculus DK1 HW thresholds near: 0.88, 1.3, 1.9, 2.5 gauss.
+    float   MaxMagneticField;
+};
+
+// SensorInfo describes capabilities of the sensor device.
+class SensorInfo : public DeviceInfo
+{
+public:
+    SensorInfo() : DeviceInfo(Device_Sensor), VendorId(0), ProductId(0)
+    {
+    }
+
+    // HID Vendor and ProductId of the device.
+    UInt16      VendorId;
+    UInt16      ProductId;
+    // MaxRanges report maximum sensor range values supported by HW.
+    SensorRange MaxRanges;
+    // Sensor (and display) serial number.
+    String      SerialNumber;
+
+private:
+    void operator = (const SensorInfo&) { OVR_ASSERT(0); } // Assignment not allowed.
+};
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Serial Number feature report. (DK1)
+struct SerialReport
+{
+    static const int SERIAL_NUMBER_SIZE = 12;  // Serial Number size = 12 bytes. (Refer 'Tracker Firmware Specification Section 4.9, Pg 18)
+
+	SerialReport()
+        : CommandId(0)
+	{
+        memset(SerialNumberValue, 0, sizeof(SerialNumberValue));
+    }
+                
+    SerialReport(UInt16 commandId,
+                UByte SNo[SERIAL_NUMBER_SIZE])
+        :	    CommandId(commandId)
+    { 
+        for (int i=0; i < SERIAL_NUMBER_SIZE; i++)
+        {
+            SerialNumberValue[i] = SNo[i];
+        }
+    }
+
+    UInt16      CommandId;
+	UByte	    SerialNumberValue[SERIAL_NUMBER_SIZE];          // See 'Tracker Firmware Specification' document for
+													  // a description of Serial Report.
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+//Added Serial Report Implementation.
+
+struct SerialImpl
+{
+    enum  { PacketSize = 15 };
+    UByte   Buffer[PacketSize];
+
+    SerialReport Settings;
+
+	SerialImpl()
+	{
+	memset(Buffer, 0, sizeof(Buffer));
+	Buffer[0] = 10;
+	}
+
+	SerialImpl(const SerialReport& settings)
+			:Settings(settings)
+	{
+		Pack();
+	}
+
+	void  Pack()
+	{
+    Buffer[0] = 10;
+    Alg::EncodeUInt16(Buffer+1, Settings.CommandId);
+	for (int i = 0; i < Settings.SERIAL_NUMBER_SIZE; ++i)
+		Buffer[3 + i] = Settings.SerialNumberValue[i];
+	}
+
+	void Unpack()
+	{
+		Settings.CommandId = Alg::DecodeUInt16(Buffer+1);
+		for (int i = 0; i < Settings.SERIAL_NUMBER_SIZE; ++i)
+			Settings.SerialNumberValue[i] = Buffer[3 + i];
+	}
+
+};
+
+
+// Tracking settings (DK2).
+struct TrackingReport
+{
+	TrackingReport()
+      : CommandId(0), Pattern(0), 
+        Enable(0), Autoincrement(0), UseCarrier(0), 
+        SyncInput(0), VsyncLock(0), CustomPattern(0),
+        ExposureLength(0), FrameInterval(0), 
+        VsyncOffset(0), DutyCycle(0)
+	{}
+
+    TrackingReport( UInt16 commandId, 
+                    UByte pattern,
+                    bool enable, 
+					bool autoincrement, 
+					bool useCarrier, 
+                    bool syncInput, 
+					bool vsyncLock, 
+					bool customPattern, 
+                    UInt16 exposureLength, 
+                    UInt16 frameInterval, 
+                    UInt16 vsyncOffset, 
+                    UByte dutyCycle)
+        :	    CommandId(commandId), Pattern(pattern), 
+                Enable(enable), Autoincrement(autoincrement), UseCarrier(useCarrier), 
+                SyncInput(syncInput), VsyncLock(vsyncLock), CustomPattern(customPattern),
+			    ExposureLength(exposureLength), FrameInterval(frameInterval), 
+			    VsyncOffset(vsyncOffset), DutyCycle(dutyCycle)
+    { }
+
+    UInt16  CommandId;
+	UByte	Pattern;            // Tracking LED pattern index.
+    bool    Enable;             // Enables the tracking LED exposure and updating.
+    bool    Autoincrement;      // Autoincrement pattern after each exposure.
+    bool    UseCarrier;         // Modulate tracking LEDs at 85kHz.
+    bool    SyncInput;          // Trigger LED exposure from wired sync signal.
+    bool    VsyncLock;          // Trigger LED exposure from panel Vsync.
+    bool    CustomPattern;      // Use custom LED sequence.
+    UInt16	ExposureLength;     // Tracking LED illumination (and exposure) length in microseconds.
+	UInt16	FrameInterval;      // LED exposure interval in microseconds when in 
+                                // 'internal timer' mode (when SyncInput = VsyncLock = false).
+    UInt16	VsyncOffset;        // Exposure offset in microseconds from vsync when in 
+                                // 'vsync lock' mode (when VsyncLock = true).
+	UByte	DutyCycle;          // Duty cycle of 85kHz modulation when in 'use carrier' mode 
+                                // (when UseCarrier = true). 128 = 50% duty cycle.
+};
+
+// Display settings (DK2).
+struct DisplayReport
+{
+    enum ShutterTypeEnum
+    {
+        // These are not yet defined.
+        ShutterType_Default     = 0,
+    };
+
+    enum CurrentLimitEnum
+    {
+        // These are not yet defined.
+        CurrentLimit_Default     = 0,
+    };
+
+	DisplayReport()
+      :	CommandId(0), Brightness(0), 
+        ShutterType(ShutterType_Default), CurrentLimit(CurrentLimit_Default), UseRolling(0), 
+        ReverseRolling(0), HighBrightness(0), SelfRefresh(0),
+        ReadPixel(0), DirectPentile(0), 
+        Persistence(0), LightingOffset(0),
+        PixelSettle(0), TotalRows(0)
+	{}
+
+    DisplayReport(  UInt16 commandId,
+                    UByte brightness,
+                    ShutterTypeEnum shutterType,
+                    CurrentLimitEnum currentLimit,
+                    bool useRolling,
+                    bool reverseRolling, 
+                    bool highBrightness, 
+                    bool selfRefresh,
+                    bool readPixel, 
+                    bool directPentile,
+                    UInt16 persistence,
+                    UInt16 lightingOffset,
+                    UInt16 pixelSettle,
+                    UInt16 totalRows)
+        :	    CommandId(commandId), Brightness(brightness), 
+                ShutterType(shutterType), CurrentLimit(currentLimit), UseRolling(useRolling), 
+                ReverseRolling(reverseRolling), HighBrightness(highBrightness), SelfRefresh(selfRefresh),
+			    ReadPixel(readPixel), DirectPentile(directPentile), 
+			    Persistence(persistence), LightingOffset(lightingOffset),
+			    PixelSettle(pixelSettle), TotalRows(totalRows)
+    { }
+
+    UInt16              CommandId;
+	UByte	            Brightness;         // See 'DK2 Firmware Specification' document for a description of
+    ShutterTypeEnum     ShutterType;        // display settings.
+    CurrentLimitEnum    CurrentLimit;
+    bool                UseRolling;
+    bool                ReverseRolling;
+    bool                HighBrightness;
+    bool                SelfRefresh;
+    bool                ReadPixel;
+    bool                DirectPentile;
+    UInt16	            Persistence;
+	UInt16	            LightingOffset;
+    UInt16	            PixelSettle;
+	UInt16	            TotalRows;
+};
+
+// MagCalibration matrix (DK2).
+struct MagCalibrationReport
+{
+	MagCalibrationReport()
+        :	    CommandId(0), Version(0), Calibration()
+	{}
+
+    MagCalibrationReport(   UInt16 commandId,
+                            UByte version,
+                            const Matrix4f& calibration)
+        :	    CommandId(commandId), Version(version), Calibration(calibration)
+    { }
+
+    UInt16      CommandId;
+	UByte	    Version;            // Version of the calibration procedure used to generate the calibration matrix.
+    Matrix4f    Calibration;        // Calibration matrix. Note only the first three rows are used by the feature report.
+};
+
+// PositionCalibration values (DK2).
+// - Sensor interface versions before 5 do not support Normal and Rotation.
+struct PositionCalibrationReport
+{
+    enum PositionTypeEnum
+    {
+        PositionType_LED     = 0,
+        PositionType_IMU     = 1
+    };
+
+    PositionCalibrationReport()
+      :	CommandId(0), Version(0), 
+        Position(0), Normal(0), Angle(0),
+        PositionIndex(0), NumPositions(0), PositionType(PositionType_LED)
+	{}
+
+    PositionCalibrationReport(UInt16 commandId,
+                        UByte version,
+                        const Vector3d& position,
+						const Vector3d& normal,
+						double rotation,
+                        UInt16 positionIndex,
+                        UInt16 numPositions,
+                        PositionTypeEnum positionType)
+        :	    CommandId(commandId), Version(version), 
+				Position(position),	Normal(normal), Angle(rotation),
+                PositionIndex(positionIndex), NumPositions(numPositions), PositionType(positionType)
+    {
+	}
+
+    UInt16			CommandId;
+	UByte			Version;            // The version of the calibration procedure used to generate the stored positions.
+    Vector3d        Position;           // Position of the LED or inertial tracker in meters. This is relative to the 
+										// center of the emitter plane of the display at nominal focus.
+	Vector3d        Normal;				// Normal of the LED or inertial tracker. This is a signed integer in 
+										// meters. The normal is relative to the position. 
+	double          Angle;			    // The rotation about the normal. This is in radians.
+    UInt16			PositionIndex;      // The current position being read or written to. Autoincrements on reads, gets set
+										// to the written value on writes.
+    UInt16			NumPositions;       // The read-only number of items with positions stored. The last position is that of
+										// the inertial tracker, all others are LED positions.
+    PositionTypeEnum PositionType;      // The type of the item which has its position reported in the current report
+};
+
+// CustomPattern values (DK2).
+struct CustomPatternReport
+{
+	CustomPatternReport()
+      :	CommandId(0), SequenceLength(0), Sequence(0),
+        LEDIndex(0), NumLEDs(0)
+	{}
+
+    CustomPatternReport(UInt16 commandId,
+                        UByte sequenceLength,
+                        UInt32 sequence,
+                        UInt16 ledIndex,
+                        UInt16 numLEDs)
+        :	    CommandId(commandId), SequenceLength(sequenceLength), Sequence(sequence),
+                LEDIndex(ledIndex), NumLEDs(numLEDs)
+    { }
+
+    UInt16      CommandId;
+	UByte	    SequenceLength;     // See 'DK2 Firmware Specification' document for a description of
+    UInt32      Sequence;           // LED custom patterns.
+    UInt16      LEDIndex;
+    UInt16      NumLEDs;
+};
+
+// KeepAliveMux settings (DK2).
+struct KeepAliveMuxReport
+{
+	KeepAliveMuxReport()
+        : CommandId(0), INReport(0), Interval(0)
+	{}
+
+    KeepAliveMuxReport( UInt16 commandId,
+                        UByte inReport,
+                        UInt16 interval)
+        :	    CommandId(commandId), INReport(inReport), Interval(interval)
+    { }
+
+    UInt16      CommandId;
+	UByte	    INReport;           // Requested IN report type (1 = DK1, 11 = DK2).
+    UInt16      Interval;           // Keep alive period in milliseconds.
+};
+
+// Manufacturing test result (DK2).
+struct ManufacturingReport
+{
+	ManufacturingReport()
+      : CommandId(0), NumStages(0), Stage(0),
+        StageVersion(0), StageLocation(0), StageTime(0), Result(0)
+	{}
+
+    ManufacturingReport(    UInt16 commandId,
+                            UByte numStages,
+                            UByte stage,
+							UByte  version,
+                            UInt16 stageLocation,
+                            UInt32 stageTime,
+                            UInt32 result)
+        :	    CommandId(commandId), NumStages(numStages), Stage(stage),
+                StageVersion(version), StageLocation(stageLocation), StageTime(stageTime), Result(result)
+    { }
+
+    UInt16      CommandId;
+	UByte	    NumStages;          // See 'DK2 Firmware Specification' document for a description of
+	UByte	    Stage;              // manufacturing test results.
+	UByte		StageVersion;
+	UInt16	    StageLocation;
+	UInt32	    StageTime;
+    UInt32      Result;
+};
+
+// UUID (DK2).
+struct UUIDReport
+{
+    static const int UUID_SIZE = 20;
+
+	UUIDReport()
+        : CommandId(0)
+	{
+        memset(UUIDValue, 0, sizeof(UUIDValue));
+    }
+                
+    UUIDReport( UInt16 commandId,
+                UByte uuid[UUID_SIZE])
+        :	    CommandId(commandId)
+    { 
+        for (int i=0; i<UUID_SIZE; i++)
+        {
+            UUIDValue[i] = uuid[i];
+        }
+    }
+
+    UInt16      CommandId;
+	UByte	    UUIDValue[UUID_SIZE];          // See 'DK2 Firmware Specification' document for
+                                        // a description of UUID.
+};
+
+// Lens Distortion (DK2).
+struct LensDistortionReport
+{
+	LensDistortionReport()
+      :	CommandId(0),
+        NumDistortions(0),
+        DistortionIndex(0),
+        Bitmask(0),
+        LensType(0),
+        Version(0),
+        EyeRelief(0),
+        MaxR(0),
+        MetersPerTanAngleAtCenter(0)
+	{}
+                
+    LensDistortionReport( UInt16 commandId,
+						  UByte numDistortions,
+						  UByte distortionIndex,
+                          UByte bitmask,
+                          UInt16 lensType,
+                          UInt16 version,
+                          UInt16 eyeRelief,
+                          UInt16 kCoefficients[11],
+                          UInt16 maxR,
+                          UInt16 metersPerTanAngleAtCenter,
+                          UInt16 chromaticAberration[4])
+        :	    CommandId(commandId),
+				NumDistortions(numDistortions),
+				DistortionIndex(distortionIndex),
+				Bitmask(bitmask),
+				LensType(lensType),
+				Version(version),
+				EyeRelief(eyeRelief),
+				MaxR(maxR),
+				MetersPerTanAngleAtCenter(metersPerTanAngleAtCenter)
+    {
+		memcpy(KCoefficients, kCoefficients, sizeof(KCoefficients));
+		memcpy(ChromaticAberration, chromaticAberration, sizeof(ChromaticAberration));
+    }
+
+    UInt16      CommandId;
+	UByte		NumDistortions;
+	UByte		DistortionIndex;
+	UByte		Bitmask;
+	UInt16		LensType;
+	UInt16		Version;
+	UInt16		EyeRelief;
+	UInt16		KCoefficients[11];
+	UInt16		MaxR;
+	UInt16		MetersPerTanAngleAtCenter;
+	UInt16		ChromaticAberration[4];
+};
+
+// Temperature calibration result (DK2).
+struct TemperatureReport
+{
+    TemperatureReport()
+      :	CommandId(0), Version(0), 
+        NumBins(0), Bin(0), NumSamples(0), Sample(0), 
+        TargetTemperature(0), ActualTemperature(0),
+        Time(0), Offset(0)
+    {}
+
+    TemperatureReport(  UInt16 commandId,
+                        UByte  version,
+                        UByte  numBins,
+                        UByte  bin,
+                        UByte  numSamples,
+                        UByte  sample,
+                        double targetTemperature,
+                        double actualTemperature,
+                        UInt32 time,
+                        Vector3d offset)
+        :	    CommandId(commandId), Version(version), 
+                NumBins(numBins), Bin(bin), NumSamples(numSamples), Sample(sample), 
+                TargetTemperature(targetTemperature), ActualTemperature(actualTemperature),
+                Time(time), Offset(offset)
+    { }
+
+    UInt16      CommandId;
+    UByte	    Version;          // See 'DK2 Firmware Specification' document for a description of
+    UByte	    NumBins;          // temperature calibration data.
+    UByte	    Bin;
+    UByte	    NumSamples;
+    UByte	    Sample;
+    double	    TargetTemperature;
+    double	    ActualTemperature;
+    UInt32      Time;             // Better hope nobody tries to use this in 2038
+    Vector3d    Offset;
+};
+
+// Gyro autocalibration result (DK2).
+struct GyroOffsetReport
+{
+    enum VersionEnum
+    {
+        // These are not yet defined.
+        Version_NoOffset     = 0,
+        Version_ShortAvg     = 1,
+        Version_LongAvg      = 2
+    };
+
+    GyroOffsetReport()
+      :	CommandId(0), Version(Version_NoOffset), 
+        Offset(0), Temperature(0)
+    {}
+
+    GyroOffsetReport(	UInt16		commandId,
+						VersionEnum version,
+						Vector3d	offset,
+						double		temperature)
+		:		CommandId(commandId), Version(version), 
+				Offset(offset), Temperature(temperature)
+    {}
+
+    UInt16      CommandId;
+    VersionEnum Version;
+    Vector3d    Offset;
+    double      Temperature;
+};
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** SensorDevice
+
+// SensorDevice is an interface to sensor data.
+// Install a MessageHandler of SensorDevice instance to receive MessageBodyFrame
+// notifications.
+//
+// TBD: Add Polling API? More HID interfaces?
+
+class SensorDevice : public HIDDeviceBase, public DeviceBase
+{
+public:
+    SensorDevice() 
+    { }
+
+    // Static constant for this device type, used in template cast type checks.
+    enum { EnumDeviceType = Device_Sensor };
+
+    virtual DeviceType GetType() const   { return Device_Sensor; }
+
+	virtual UByte GetDeviceInterfaceVersion() = 0;
+
+
+    // CoordinateFrame defines whether messages come in the coordinate frame
+    // of the sensor device or HMD, which has a different internal sensor.
+    // Sensors obtained form the HMD will automatically use HMD coordinates.
+    enum CoordinateFrame
+    {
+        Coord_Sensor = 0,
+        Coord_HMD    = 1
+    };
+
+    virtual void            SetCoordinateFrame(CoordinateFrame coordframe) = 0;
+    virtual CoordinateFrame GetCoordinateFrame() const = 0;
+
+    // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call). 
+    // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be 
+    // called twice or thrice at the same 'tick'. 
+    // If the rate is  < 333 then the OnMessage / MessageBodyFrame will be called three
+    // times for each 'tick': the first call will contain averaged values, the second
+    // and third calls will provide with most recent two recorded samples.
+    virtual void        SetReportRate(unsigned rateHz) = 0;
+    // Returns currently set report rate, in Hz. If 0 - error occurred.
+    // Note, this value may be different from the one provided for SetReportRate. The return
+    // value will contain the actual rate.
+    virtual unsigned	GetReportRate() const = 0;
+
+    // Sets maximum range settings for the sensor described by SensorRange.    
+    // The function will fail if you try to pass values outside Maximum supported
+    // by the HW, as described by SensorInfo.
+    // Pass waitFlag == true to wait for command completion. For waitFlag == true,
+    // returns true if the range was applied successfully (no HW error).
+    // For waitFlag = false, return 'true' means that command was enqueued successfully.
+    virtual bool		SetRange(const SensorRange& range, bool waitFlag = false) = 0;
+
+    // Return the current sensor range settings for the device. These may not exactly
+    // match the values applied through SetRange.
+    virtual void		GetRange(SensorRange* range) const = 0;
+
+    // Return the factory calibration parameters for the IMU
+    virtual void        GetFactoryCalibration(Vector3f* AccelOffset, Vector3f* GyroOffset,
+                                              Matrix4f* AccelMatrix, Matrix4f* GyroMatrix, 
+                                              float* Temperature) = 0;
+    // Enable/disable onboard IMU calibration
+    // If set to false, the device will return raw values
+    virtual void        SetOnboardCalibrationEnabled(bool enabled) = 0;
+    // Return true if the mag is calibrated
+    virtual bool        IsMagCalibrated() { return false; }
+
+	// Get/set feature reports from DK1 added to DK2. See 'Tracker Firmware Specification' document for details.
+	virtual bool		SetSerialReport(const SerialReport&) { return false; }
+	virtual bool		GetSerialReport(SerialReport*) { return false; }
+
+    // Get/set feature reports added to DK2. See 'DK2 Firmware Specification' document for details.
+    virtual bool		SetTrackingReport(const TrackingReport&) { return false; }
+	virtual bool		GetTrackingReport(TrackingReport*) { return false; }
+
+    virtual bool		SetDisplayReport(const DisplayReport&) { return false; }
+	virtual bool		GetDisplayReport(DisplayReport*) { return false; }
+
+    virtual bool		SetMagCalibrationReport(const MagCalibrationReport&) { return false; }
+	virtual bool		GetMagCalibrationReport(MagCalibrationReport*) { return false; }
+
+    virtual bool		SetPositionCalibrationReport(const PositionCalibrationReport&) { return false; }
+	virtual bool		GetAllPositionCalibrationReports(Array<PositionCalibrationReport>*) { return false; }
+
+    virtual bool		SetCustomPatternReport(const CustomPatternReport&) { return false; }
+	virtual bool		GetCustomPatternReport(CustomPatternReport*) { return false; }
+
+    virtual bool		SetKeepAliveMuxReport(const KeepAliveMuxReport&) { return false; }
+	virtual bool		GetKeepAliveMuxReport(KeepAliveMuxReport*) { return false; }
+
+    virtual bool		SetManufacturingReport(const ManufacturingReport&) { return false; }
+	virtual bool		GetManufacturingReport(ManufacturingReport*) { return false; }
+
+    virtual bool		SetUUIDReport(const UUIDReport&) { return false; }
+	virtual bool		GetUUIDReport(UUIDReport*) { return false; }
+
+    virtual bool		SetTemperatureReport(const TemperatureReport&) { return false; }
+    virtual bool        GetAllTemperatureReports(Array<Array<TemperatureReport> >*) { return false; }
+
+    virtual bool        GetGyroOffsetReport(GyroOffsetReport*) { return false; }
+
+    virtual bool		SetLensDistortionReport(const LensDistortionReport&) { return false; }
+    virtual bool		GetLensDistortionReport(LensDistortionReport*) { return false; }
+};
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTestConfiguration
+// LatencyTestConfiguration specifies configuration information for the Oculus Latency Tester device.
+struct LatencyTestConfiguration
+{
+    LatencyTestConfiguration(const Color& threshold, bool sendSamples = false)
+        : Threshold(threshold), SendSamples(sendSamples) 
+    {
+    }
+
+    // The color threshold for triggering a detected display change.
+    Color    Threshold;
+    // Flag specifying whether we wish to receive a stream of color values from the sensor.
+    bool        SendSamples;
+};
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTestDisplay
+// LatencyTestDisplay sets the mode and contents of the Latency Tester LED display.
+// See the 'Latency Tester Specification' document for more details.
+struct LatencyTestDisplay
+{
+    LatencyTestDisplay(UByte mode, UInt32 value)
+        : Mode(mode), Value(value)
+    {
+    }
+
+    UByte       Mode;       // The display mode that we wish to select.
+    UInt32      Value;      // The value to display.
+};
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTestDevice
+
+// LatencyTestDevice provides an interface to the Oculus Latency Tester which is used to test 'motion to photon' latency.
+class LatencyTestDevice : public HIDDeviceBase, public DeviceBase
+{
+public:
+    LatencyTestDevice()
+    { }
+
+    // Static constant for this device type, used in template cast type checks.
+    enum { EnumDeviceType = Device_LatencyTester };
+
+    virtual DeviceType GetType() const { return Device_LatencyTester; }
+
+    // Specifies configuration information including the threshold for triggering a detected color change,
+    // and a flag to enable a stream of sensor values (typically used for debugging).
+    virtual bool SetConfiguration(const LatencyTestConfiguration& configuration, bool waitFlag = false) = 0;
+
+    // Get configuration information from device.
+    virtual bool GetConfiguration(LatencyTestConfiguration* configuration) = 0;
+
+    // Used to calibrate the latency tester at the start of a test. Display the specified color on the screen
+    // beneath the latency tester and then call this method. Calibration information is lost
+    // when power is removed from the device.
+    virtual bool SetCalibrate(const Color& calibrationColor, bool waitFlag = false) = 0;
+
+    // Triggers the start of a measurement. This starts the millisecond timer on the device and 
+    // causes it to respond with the 'MessageLatencyTestStarted' message.
+    virtual bool SetStartTest(const Color& targetColor, bool waitFlag = false) = 0;
+
+    // Used to set the value displayed on the LED display panel.
+    virtual bool SetDisplay(const LatencyTestDisplay& display, bool waitFlag = false) = 0;
+
+    virtual DeviceBase* GetDevice() { return this; }
+};
+
+} // namespace OVR
+
+
+
+
+#endif
diff --git a/LibOVR/Src/OVR_DeviceConstants.h b/LibOVR/Src/OVR_DeviceConstants.h
new file mode 100644
index 0000000..6b40b7d
--- /dev/null
+++ b/LibOVR/Src/OVR_DeviceConstants.h
@@ -0,0 +1,142 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_DeviceConstants.h
+Content     :   Device constants
+Created     :   February 5, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_DeviceConstants_h
+#define OVR_DeviceConstants_h
+
+namespace OVR {
+
+
+//-------------------------------------------------------------------------------------
+// Different device types supported by OVR; this type is reported by DeviceBase::GetType.
+// 
+enum DeviceType
+{
+    Device_None             = 0,
+    Device_Manager          = 1,
+    Device_HMD              = 2,
+    Device_Sensor           = 3,
+    Device_LatencyTester    = 4,
+    Device_BootLoader       = 5,
+	Device_Camera			= 6,
+	Device_Display			= 7,
+    Device_All              = 0xFF // Set for enumeration only, to enumerate all device types.
+};
+
+
+
+//-------------------------------------------------------------------------------------
+// Different lens distortion types supported by devices.
+// 
+enum DistortionEqnType
+{
+    Distortion_No_Override  = -1,    
+	// These two are leagcy and deprecated.
+    Distortion_Poly4        = 0,    // scale = (K0 + K1*r^2 + K2*r^4 + K3*r^6)
+    Distortion_RecipPoly4   = 1,    // scale = 1/(K0 + K1*r^2 + K2*r^4 + K3*r^6)
+
+    // CatmullRom10 is the preferred distortion format.
+    Distortion_CatmullRom10 = 2,    // scale = Catmull-Rom spline through points (1.0, K[1]...K[9])
+
+    Distortion_LAST                 // For ease of enumeration.
+};
+
+
+//-------------------------------------------------------------------------------------
+// HMD types.
+//
+enum HmdTypeEnum
+{
+    HmdType_None,
+
+    HmdType_DKProto,            // First duct-tape model, never sold.
+    HmdType_DK1,                // DevKit1 - on sale to developers.
+    HmdType_DKHDProto,          // DKHD - shown at various shows, never sold.
+    HmdType_DKHD2Proto,         // DKHD2, 5.85-inch panel, never sold.
+    HmdType_DKHDProto566Mi,     // DKHD, 5.66-inch panel, never sold.
+    HmdType_CrystalCoveProto,   // Crystal Cove, 5.66-inch panel, shown at shows but never sold.
+    HmdType_DK2,
+
+    // Reminder - this header file is public - codenames only!
+
+    HmdType_Unknown,            // Used for unnamed HW lab experiments.
+
+    HmdType_LAST
+};
+
+
+//-------------------------------------------------------------------------------------
+// HMD shutter types.
+//
+enum HmdShutterTypeEnum
+{
+    HmdShutter_Global,
+    HmdShutter_RollingTopToBottom,
+    HmdShutter_RollingLeftToRight,
+    HmdShutter_RollingRightToLeft,
+    // TODO:
+    // color-sequential e.g. LCOS?
+    // alternate eyes?
+    // alternate columns?
+    // outside-in?
+
+    HmdShutter_LAST
+};
+
+
+
+//-------------------------------------------------------------------------------------
+// For headsets that use eye cups
+//
+enum EyeCupType
+{
+    // Public lenses
+    EyeCup_DK1A = 0,
+    EyeCup_DK1B = 1,
+    EyeCup_DK1C = 2,
+
+    EyeCup_DK2A = 3,
+
+    // Internal R&D codenames.
+    // Reminder - this header file is public - codenames only!
+    EyeCup_DKHD2A,
+    EyeCup_OrangeA,
+    EyeCup_RedA,
+    EyeCup_PinkA,
+    EyeCup_BlueA,
+    EyeCup_Delilah1A,
+    EyeCup_Delilah2A,
+    EyeCup_JamesA,
+    EyeCup_SunMandalaA,
+
+    EyeCup_LAST
+};
+
+
+} // namespace OVR
+
+#endif
diff --git a/LibOVR/Src/OVR_DeviceHandle.cpp b/LibOVR/Src/OVR_DeviceHandle.cpp
new file mode 100644
index 0000000..cf6f05f
--- /dev/null
+++ b/LibOVR/Src/OVR_DeviceHandle.cpp
@@ -0,0 +1,185 @@
+/************************************************************************************
+
+Filename    :   OVR_DeviceHandle.cpp
+Content     :   Implementation of device handle class
+Created     :   February 5, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_DeviceHandle.h"
+
+#include "OVR_DeviceImpl.h"
+
+namespace OVR {
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceHandle
+
+DeviceHandle::DeviceHandle(DeviceCreateDesc* impl) : pImpl(impl)
+{
+    if (pImpl)
+        pImpl->AddRef();
+}
+
+DeviceHandle::DeviceHandle(const DeviceHandle& src) : pImpl(src.pImpl)
+{
+    if (pImpl)
+        pImpl->AddRef();
+}    
+
+DeviceHandle::~DeviceHandle()
+{
+    if (pImpl)
+        pImpl->Release();
+}
+
+void DeviceHandle::operator = (const DeviceHandle& src)
+{
+    if (src.pImpl)
+        src.pImpl->AddRef();
+    if (pImpl)
+        pImpl->Release();
+    pImpl = src.pImpl;
+}
+
+DeviceBase* DeviceHandle::GetDevice_AddRef() const
+{ 
+    if (pImpl && pImpl->pDevice)
+    {
+        pImpl->pDevice->AddRef();
+        return pImpl->pDevice;
+    }
+    return NULL;
+}
+
+// Returns true, if the handle contains the same device ptr
+// as specified in the parameter.
+bool DeviceHandle::IsDevice(DeviceBase* pdev) const
+{
+    return (pdev && pImpl && pImpl->pDevice) ? 
+        pImpl->pDevice == pdev : false;
+}
+
+DeviceType  DeviceHandle::GetType() const
+{
+    return pImpl ? pImpl->Type : Device_None;
+}
+
+bool DeviceHandle::GetDeviceInfo(DeviceInfo* info) const
+{
+    return pImpl ? pImpl->GetDeviceInfo(info) : false;
+}
+bool DeviceHandle::IsAvailable() const
+{
+    // This isn't "atomically safe", but the function only returns the
+    // recent state that may change.
+    return pImpl ? (pImpl->Enumerated && pImpl->pLock->pManager) : false;
+}
+
+bool DeviceHandle::IsCreated() const
+{
+    return pImpl ? (pImpl->pDevice != 0) : false;
+}
+
+DeviceBase* DeviceHandle::CreateDevice()
+{       
+    if (!pImpl)
+        return 0;
+    
+    DeviceBase*            device = 0;
+    Ptr<DeviceManagerImpl> manager= 0;
+
+    // Since both manager and device pointers can only be destroyed during a lock,
+    // hold it while checking for availability.
+    // AddRef to manager so that it doesn't get released on us.
+    {
+        Lock::Locker deviceLockScope(pImpl->GetLock());
+
+        if (pImpl->pDevice)
+        {
+            pImpl->pDevice->AddRef();
+            return pImpl->pDevice;
+        }
+        manager = pImpl->GetManagerImpl();
+    }
+
+    if (manager)
+    {
+        if (manager->GetThreadId() != OVR::GetCurrentThreadId())
+        {
+            // Queue up a CreateDevice request. This fills in '&device' with AddRefed value,
+            // or keep it at null.
+            manager->GetThreadQueue()->PushCallAndWaitResult(
+                manager.GetPtr(), &DeviceManagerImpl::CreateDevice_MgrThread,
+                &device, pImpl, (DeviceBase*)0);
+        }
+        else
+            device = manager->CreateDevice_MgrThread(pImpl, (DeviceBase*)0);
+    }
+    return device;
+}
+
+void DeviceHandle::Clear()
+{
+    if (pImpl)
+    {
+        pImpl->Release();
+        pImpl = 0;
+    }
+}
+
+bool DeviceHandle::enumerateNext(const DeviceEnumerationArgs& args)
+{
+    if (GetType() == Device_None)
+        return false;
+    
+    Ptr<DeviceManagerImpl> managerKeepAlive;
+    Lock::Locker           lockScope(pImpl->GetLock());
+    
+    DeviceCreateDesc* next = pImpl;
+    // If manager was destroyed, we get removed from the list.
+    if (!pImpl->pNext)
+        return false;
+
+    managerKeepAlive = next->GetManagerImpl();
+    OVR_ASSERT(managerKeepAlive);
+    
+    do {
+        next = next->pNext;
+
+        if (managerKeepAlive->Devices.IsNull(next))
+        {
+            pImpl->Release();
+            pImpl = 0;
+            return false;
+        }
+
+    } while(!args.MatchRule(next->Type, next->Enumerated));
+
+    next->AddRef();
+    pImpl->Release();
+    pImpl = next;
+
+    return true;
+}
+
+} // namespace OVR
+
diff --git a/LibOVR/Src/OVR_DeviceHandle.h b/LibOVR/Src/OVR_DeviceHandle.h
new file mode 100644
index 0000000..dd3e92b
--- /dev/null
+++ b/LibOVR/Src/OVR_DeviceHandle.h
@@ -0,0 +1,108 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_DeviceHandle.h
+Content     :   Handle to a device that was enumerated
+Created     :   February 5, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_DeviceHandle_h
+#define OVR_DeviceHandle_h
+
+#include "OVR_DeviceConstants.h"
+
+namespace OVR {
+
+class DeviceBase;
+class DeviceInfo;
+
+// Internal
+class DeviceCreateDesc;
+class DeviceEnumerationArgs;
+
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceHandle
+
+// DeviceHandle references a specific device that was enumerated; it can be assigned
+// directly from DeviceEnumerator.
+//
+// Devices represented by DeviceHandle are not necessarily created or available.
+// A device may become unavailable if, for example, it its unplugged. If the device
+// is available, it can be created by calling CreateDevice.
+//
+
+class DeviceHandle
+{    
+	friend class DeviceManager;
+	friend class DeviceManagerImpl;
+    template<class B> friend class HIDDeviceImpl;
+
+public:
+	DeviceHandle() : pImpl(0) { }    
+	DeviceHandle(const DeviceHandle& src);
+	~DeviceHandle();
+
+	void operator = (const DeviceHandle& src);
+
+	bool operator == (const DeviceHandle& other) const { return pImpl == other.pImpl; }
+	bool operator != (const DeviceHandle& other) const { return pImpl != other.pImpl; }
+
+	// operator bool() returns true if Handle/Enumerator points to a valid device.
+	operator bool () const   { return GetType() != Device_None; }
+
+    // Returns existing device, or NULL if !IsCreated. The returned ptr is 
+    // addref-ed.
+    DeviceBase* GetDevice_AddRef() const;
+	DeviceType  GetType() const;
+	bool        GetDeviceInfo(DeviceInfo* info) const;
+	bool        IsAvailable() const;
+	bool        IsCreated() const;
+    // Returns true, if the handle contains the same device ptr
+    // as specified in the parameter.
+    bool        IsDevice(DeviceBase*) const;
+
+	// Creates a device, or returns AddRefed pointer if one is already created.
+	// New devices start out with RefCount of 1.
+	DeviceBase* CreateDevice();
+
+    // Creates a device, or returns AddRefed pointer if one is already created.
+    // New devices start out with RefCount of 1. DeviceT is used to cast the
+    // DeviceBase* to a concreete type.
+    template <class DeviceT>
+    DeviceT* CreateDeviceTyped() const
+    {
+        return static_cast<DeviceT*>(DeviceHandle(*this).CreateDevice());
+    }
+
+	// Resets the device handle to uninitialized state.
+	void        Clear();
+
+protected:
+	explicit DeviceHandle(DeviceCreateDesc* impl);
+	bool     enumerateNext(const DeviceEnumerationArgs& args);
+	DeviceCreateDesc* pImpl;
+};
+
+} // namespace OVR
+
+#endif
diff --git a/LibOVR/Src/OVR_DeviceImpl.cpp b/LibOVR/Src/OVR_DeviceImpl.cpp
new file mode 100644
index 0000000..5b77708
--- /dev/null
+++ b/LibOVR/Src/OVR_DeviceImpl.cpp
@@ -0,0 +1,794 @@
+/************************************************************************************
+
+Filename    :   OVR_DeviceImpl.h
+Content     :   Partial back-end independent implementation of Device interfaces
+Created     :   October 10, 2012
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_DeviceImpl.h"
+#include "Kernel/OVR_Atomic.h"
+#include "Kernel/OVR_Log.h"
+#include "Kernel/OVR_System.h"
+
+#include "OVR_DeviceImpl.h"
+#include "OVR_SensorImpl.h"
+#include "OVR_Profile.h"
+
+namespace OVR {
+
+
+//-------------------------------------------------------------------------------------
+// ***** MessageHandler
+
+// Threading notes:
+// The OnMessage() handler and SetMessageHandler are currently synchronized
+// through a separately stored shared Lock object to avoid calling the handler 
+// from background thread while it's being removed.
+
+static SharedLock MessageHandlerSharedLock;
+
+
+class MessageHandlerImpl
+{
+public:
+    enum
+    {
+        MaxHandlerRefsCount = 4
+    };
+
+    MessageHandlerImpl()
+        : pLock(MessageHandlerSharedLock.GetLockAddRef()), HandlerRefsCount(0)
+    {
+    }
+    ~MessageHandlerImpl()
+    {
+        MessageHandlerSharedLock.ReleaseLock(pLock);
+        pLock = 0;
+    }
+
+    static MessageHandlerImpl* FromHandler(MessageHandler* handler)
+    { return (MessageHandlerImpl*)&handler->Internal; }
+    static const MessageHandlerImpl* FromHandler(const MessageHandler* handler)
+    { return (const MessageHandlerImpl*)&handler->Internal; }
+
+    // This lock is held while calling a handler and when we are applied/
+    // removed from a device.
+    Lock*               pLock;
+    // List of devices we are applied to.
+    int                 HandlerRefsCount;
+    MessageHandlerRef*  pHandlerRefs[MaxHandlerRefsCount];
+};
+
+
+MessageHandlerRef::MessageHandlerRef(DeviceBase* device)
+    : pLock(MessageHandlerSharedLock.GetLockAddRef()), pDevice(device), HandlersCount(0)
+{
+}
+
+MessageHandlerRef::~MessageHandlerRef()
+{
+    {
+        Lock::Locker lockScope(pLock);
+        
+        while (HandlersCount > 0)
+            removeHandler(0);
+    }
+    MessageHandlerSharedLock.ReleaseLock(pLock);
+    pLock = 0;
+}
+
+void MessageHandlerRef::Call(const Message& msg)
+{
+    Lock::Locker lockScope(pLock);
+
+    for (int i = 0; i < HandlersCount; i++)
+        pHandlers[i]->OnMessage(msg);
+}
+
+void MessageHandlerRef::AddHandler(MessageHandler* handler)
+{    
+    OVR_ASSERT(!handler ||
+               MessageHandlerImpl::FromHandler(handler)->pLock == pLock);    
+    Lock::Locker lockScope(pLock);
+    AddHandler_NTS(handler);
+}
+
+void MessageHandlerRef::AddHandler_NTS(MessageHandler* handler)
+{
+    OVR_ASSERT(handler != NULL);
+
+    OVR_ASSERT(HandlersCount < MaxHandlersCount);
+    for (int i = 0; i < HandlersCount; i++)
+        if (pHandlers[i] == handler)
+            // handler already installed - do nothing
+            return;
+    pHandlers[HandlersCount] = handler;
+    HandlersCount++;
+
+    MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(handler);
+    OVR_ASSERT(handlerImpl->HandlerRefsCount < MessageHandlerImpl::MaxHandlerRefsCount);
+    handlerImpl->pHandlerRefs[handlerImpl->HandlerRefsCount] = this;
+    handlerImpl->HandlerRefsCount++;
+
+    // TBD: Call notifier on device?
+}
+
+bool MessageHandlerRef::RemoveHandler(MessageHandler* handler)
+{
+    Lock::Locker lockScope(pLock);
+
+    for (int i = 0; i < HandlersCount; i++)
+    {
+        if (pHandlers[i] == handler)
+            return removeHandler(i);
+    }
+    return false;
+}
+
+bool MessageHandlerRef::removeHandler(int idx)
+{
+    OVR_ASSERT(idx < HandlersCount);
+
+    MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(pHandlers[idx]);
+    for (int i = 0; i < handlerImpl->HandlerRefsCount; i++)
+        if (handlerImpl->pHandlerRefs[i] == this)
+        {
+            handlerImpl->pHandlerRefs[i] = handlerImpl->pHandlerRefs[handlerImpl->HandlerRefsCount - 1];
+            handlerImpl->HandlerRefsCount--;
+
+            pHandlers[idx] = pHandlers[HandlersCount - 1];
+            HandlersCount--;
+
+            return true;
+        }
+
+    // couldn't find a link in the opposite direction, assert in Debug
+    OVR_ASSERT(0);
+
+    pHandlers[idx] = pHandlers[HandlersCount - 1];
+    HandlersCount--;
+    
+    return true;
+}
+
+MessageHandler::MessageHandler()
+{    
+    OVR_COMPILER_ASSERT(sizeof(Internal) > sizeof(MessageHandlerImpl));
+    Construct<MessageHandlerImpl>(Internal);
+}
+
+MessageHandler::~MessageHandler()
+{
+    MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
+    {
+        Lock::Locker lockedScope(handlerImpl->pLock);
+        OVR_ASSERT_LOG(handlerImpl->HandlerRefsCount == 0,
+            ("~MessageHandler %p - Handler still active; call RemoveHandlerFromDevices", this));
+    }
+
+    Destruct<MessageHandlerImpl>(handlerImpl);    
+}
+
+bool MessageHandler::IsHandlerInstalled() const
+{
+    const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);    
+    Lock::Locker lockedScope(handlerImpl->pLock);
+
+    return handlerImpl->HandlerRefsCount > 0;
+}
+
+void MessageHandler::RemoveHandlerFromDevices()
+{
+    MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
+    Lock::Locker lockedScope(handlerImpl->pLock);
+
+    while (handlerImpl->HandlerRefsCount > 0)
+    {
+        MessageHandlerRef* use = handlerImpl->pHandlerRefs[0];
+        use->RemoveHandler(this);
+    }
+}
+
+Lock* MessageHandler::GetHandlerLock() const
+{
+    const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
+    return handlerImpl->pLock;
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceBase
+   
+
+// Delegate relevant implementation to DeviceRectord to avoid re-implementation in
+// every derived Device.
+void DeviceBase::AddRef()
+{
+    getDeviceCommon()->DeviceAddRef();
+}
+void DeviceBase::Release()
+{
+    getDeviceCommon()->DeviceRelease();
+}
+DeviceBase* DeviceBase::GetParent() const
+{
+    return getDeviceCommon()->pParent.GetPtr();
+}
+DeviceManager* DeviceBase::GetManager() const
+{
+    return getDeviceCommon()->pCreateDesc->GetManagerImpl();
+}
+
+void DeviceBase::AddMessageHandler(MessageHandler* handler)
+{
+    getDeviceCommon()->HandlerRef.AddHandler(handler);
+}
+
+DeviceType DeviceBase::GetType() const
+{
+    return getDeviceCommon()->pCreateDesc->Type;
+}
+
+bool DeviceBase::GetDeviceInfo(DeviceInfo* info) const
+{
+    return getDeviceCommon()->pCreateDesc->GetDeviceInfo(info);
+    //info->Name[0] = 0;
+    //return false;
+}
+
+// Returns true if device is connected and usable
+bool DeviceBase::IsConnected()
+{
+    return getDeviceCommon()->ConnectedFlag;
+}
+
+// returns the MessageHandler's lock
+Lock* DeviceBase::GetHandlerLock() const
+{
+    return getDeviceCommon()->HandlerRef.GetLock();
+}
+
+// Derive DeviceManagerCreateDesc to provide abstract function implementation.
+class DeviceManagerCreateDesc : public DeviceCreateDesc
+{
+public:
+    DeviceManagerCreateDesc(DeviceFactory* factory)
+        : DeviceCreateDesc(factory, Device_Manager) { }
+
+    // We don't need there on Manager since it isn't assigned to DeviceHandle.
+    virtual DeviceCreateDesc* Clone() const                        { return 0; }
+    virtual MatchResult MatchDevice(const DeviceCreateDesc&,
+                                    DeviceCreateDesc**) const      { return Match_None; }
+    virtual DeviceBase* NewDeviceInstance()                        { return 0; }
+    virtual bool        GetDeviceInfo(DeviceInfo*) const           { return false; }
+};
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceManagerImpl
+
+DeviceManagerImpl::DeviceManagerImpl()
+    : DeviceImpl<OVR::DeviceManager>(CreateManagerDesc(), 0)
+      //,DeviceCreateDescList(pCreateDesc ? pCreateDesc->pLock : 0)
+{
+    if (pCreateDesc)
+    {
+        pCreateDesc->pLock->pManager = this;
+    }
+}
+
+DeviceManagerImpl::~DeviceManagerImpl()
+{
+    // Shutdown must've been called.
+    OVR_ASSERT(!pCreateDesc->pDevice);
+
+    // Remove all factories
+    while(!Factories.IsEmpty())
+    {
+        DeviceFactory* factory = Factories.GetFirst();
+        factory->RemovedFromManager();
+        factory->RemoveNode();
+    }
+}
+
+DeviceCreateDesc* DeviceManagerImpl::CreateManagerDesc()
+{
+    DeviceCreateDesc* managerDesc = new DeviceManagerCreateDesc(0);
+    if (managerDesc)
+    {
+        managerDesc->pLock = *new DeviceManagerLock;
+    }
+    return managerDesc;
+}
+
+bool DeviceManagerImpl::Initialize(DeviceBase* parent)
+{
+    OVR_UNUSED(parent);
+    if (!pCreateDesc || !pCreateDesc->pLock)
+		return false;
+
+    pProfileManager = *ProfileManager::Create();
+
+    return true;
+}
+
+void DeviceManagerImpl::Shutdown()
+{
+    // Remove all device descriptors from list while the lock is held.
+    // Some descriptors may survive longer due to handles.    
+    while(!Devices.IsEmpty())
+    {     
+        DeviceCreateDesc* devDesc = Devices.GetFirst();
+        OVR_ASSERT(!devDesc->pDevice); // Manager shouldn't be dying while Device exists.
+        devDesc->Enumerated = false;
+        devDesc->RemoveNode();
+        devDesc->pNext = devDesc->pPrev = 0;
+
+        if (devDesc->HandleCount == 0)
+        {
+            delete devDesc;
+        }
+    }
+    Devices.Clear();
+
+    // These must've been cleared by caller.
+    OVR_ASSERT(pCreateDesc->pDevice == 0);
+    OVR_ASSERT(pCreateDesc->pLock->pManager == 0);
+
+    pProfileManager.Clear();
+}
+
+
+// Callbacks for DeviceCreation/Release    
+DeviceBase* DeviceManagerImpl::CreateDevice_MgrThread(DeviceCreateDesc* createDesc, DeviceBase* parent)
+{
+    // Calls to DeviceManagerImpl::CreateDevice are enqueued with wait while holding pManager,
+    // so 'this' must remain valid.
+    OVR_ASSERT(createDesc->pLock->pManager);    
+
+    Lock::Locker devicesLock(GetLock());
+
+    // If device already exists, just AddRef to it.
+    if (createDesc->pDevice)
+    {
+        createDesc->pDevice->AddRef();
+        return createDesc->pDevice;
+    }
+
+    if (!parent)
+        parent = this;
+
+    DeviceBase* device = createDesc->NewDeviceInstance();
+    
+    if (device)
+    {
+        if (device->getDeviceCommon()->Initialize(parent))
+        {
+           createDesc->pDevice = device;
+        }
+        else
+        {
+            // Don't go through Release() to avoid PushCall behaviour,
+            // as it is not needed here.
+            delete device;
+            device = 0;
+        }
+    }
+     
+    return device;
+}
+
+Void DeviceManagerImpl::ReleaseDevice_MgrThread(DeviceBase* device)
+{
+    // descKeepAlive will keep ManagerLock object alive as well,
+    // allowing us to exit gracefully.    
+    Ptr<DeviceCreateDesc>  descKeepAlive;
+    Lock::Locker           devicesLock(GetLock());
+    DeviceCommon*          devCommon = device->getDeviceCommon();
+
+    while(1)
+    {
+        UInt32 refCount = devCommon->RefCount;
+
+        if (refCount > 1)
+        {
+            if (devCommon->RefCount.CompareAndSet_NoSync(refCount, refCount-1))
+            {
+                // We decreented from initial count higher then 1;
+                // nothing else to do.
+                return 0;
+            }        
+        }
+        else if (devCommon->RefCount.CompareAndSet_NoSync(1, 0))
+        {
+            // { 1 -> 0 } decrement succeded. Destroy this device.
+            break;
+        }
+    }
+
+    // At this point, may be releasing the device manager itself.
+    // This does not matter, however, since shutdown logic is the same
+    // in both cases. DeviceManager::Shutdown with begin shutdown process for
+    // the internal manager thread, which will eventually destroy itself.
+    // TBD: Clean thread shutdown.
+    descKeepAlive = devCommon->pCreateDesc;
+    descKeepAlive->pDevice = 0;
+    devCommon->Shutdown();
+    delete device;
+    return 0;
+}
+
+
+
+Void DeviceManagerImpl::EnumerateAllFactoryDevices()
+{
+    // 1. Mark matching devices as NOT enumerated.
+    // 2. Call factory to enumerate all HW devices, adding any device that 
+    //    was not matched.
+    // 3. Remove non-matching devices.
+
+    Lock::Locker deviceLock(GetLock());
+
+    DeviceCreateDesc* devDesc, *nextdevDesc;
+
+    // 1.
+    for(devDesc = Devices.GetFirst();
+        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
+    {
+        //if (devDesc->pFactory == factory)
+            devDesc->Enumerated = false;
+    }
+    
+    // 2.
+    DeviceFactory* factory = Factories.GetFirst();
+    while(!Factories.IsNull(factory))
+    {
+        EnumerateFactoryDevices(factory);
+        factory = factory->pNext;
+    }
+
+    
+    // 3.
+    for(devDesc = Devices.GetFirst();
+        !Devices.IsNull(devDesc);  devDesc = nextdevDesc)
+    {
+        // In case 'devDesc' gets removed.
+        nextdevDesc = devDesc->pNext; 
+
+        // Note, device might be not enumerated since it is opened and
+        // in use! Do NOT notify 'device removed' in this case (!AB)
+        if (!devDesc->Enumerated)
+        {
+            // This deletes the devDesc for HandleCount == 0 due to Release in DeviceHandle.
+            CallOnDeviceRemoved(devDesc);
+
+            /*
+            if (devDesc->HandleCount == 0)
+            {                
+                // Device must be dead if it ever existed, since it AddRefs to us.
+                // ~DeviceCreateDesc removes its node from list.
+                OVR_ASSERT(!devDesc->pDevice);
+                delete devDesc;
+            }
+            */
+        }
+    }
+
+    return 0;
+}
+
+Ptr<DeviceCreateDesc> DeviceManagerImpl::AddDevice_NeedsLock(
+    const DeviceCreateDesc& createDesc)
+{
+    // If found, mark as enumerated and we are done.
+    DeviceCreateDesc* descCandidate = 0;
+
+    for(DeviceCreateDesc* devDesc = Devices.GetFirst();
+        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
+    {
+        DeviceCreateDesc::MatchResult mr = devDesc->MatchDevice(createDesc, &descCandidate);
+        if (mr == DeviceCreateDesc::Match_Found)
+        {
+            devDesc->Enumerated = true;
+            if (!devDesc->pDevice)
+                CallOnDeviceAdded(devDesc);
+            return devDesc;
+        }
+    }
+
+    // Update candidate (this may involve writing fields to HMDDevice createDesc).
+    if (descCandidate)
+    {
+        bool newDevice = false;
+        if (descCandidate->UpdateMatchedCandidate(createDesc, &newDevice))
+        {
+            descCandidate->Enumerated = true;
+            if (!descCandidate->pDevice || newDevice)
+                CallOnDeviceAdded(descCandidate);
+            return descCandidate;
+        }
+    }
+
+    // If not found, add new device.
+    //  - This stores a new descriptor with
+    //    {pDevice = 0, HandleCount = 1, Enumerated = true}
+    DeviceCreateDesc* desc = createDesc.Clone();
+    desc->pLock = pCreateDesc->pLock;
+    Devices.PushBack(desc);
+    desc->Enumerated = true;
+
+    CallOnDeviceAdded(desc);
+
+    return desc;
+}
+
+Ptr<DeviceCreateDesc> DeviceManagerImpl::FindDevice(
+    const String& path, 
+    DeviceType deviceType)
+{
+    Lock::Locker deviceLock(GetLock());
+    DeviceCreateDesc* devDesc;
+
+    for (devDesc = Devices.GetFirst();
+        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
+    {
+        if ((deviceType == Device_None || deviceType == devDesc->Type) &&
+            devDesc->MatchDevice(path))
+            return devDesc;
+    }
+    return NULL;
+}
+
+Ptr<DeviceCreateDesc> DeviceManagerImpl::FindHIDDevice(const HIDDeviceDesc& hidDevDesc, bool created)
+{
+    Lock::Locker deviceLock(GetLock());
+    DeviceCreateDesc* devDesc;
+    
+    for (devDesc = Devices.GetFirst();
+        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
+    {
+        if (created)
+        {   // Search for matching device that is created
+            if (devDesc->MatchHIDDevice(hidDevDesc) && devDesc->pDevice)
+                return devDesc;
+        }
+        else
+        {   // Search for any matching device
+            if (devDesc->MatchHIDDevice(hidDevDesc))
+                return devDesc;
+        }
+    }
+    return NULL;
+}
+  
+void DeviceManagerImpl::DetectHIDDevice(const HIDDeviceDesc& hidDevDesc)
+{
+    Lock::Locker deviceLock(GetLock());
+    DeviceFactory* factory = Factories.GetFirst();
+    while(!Factories.IsNull(factory))
+    {
+        if (factory->DetectHIDDevice(this, hidDevDesc))
+            break;
+        factory = factory->pNext;
+    }
+    
+}
+    
+// Enumerates devices for a particular factory.
+Void DeviceManagerImpl::EnumerateFactoryDevices(DeviceFactory* factory)
+{
+       
+    class FactoryEnumerateVisitor : public DeviceFactory::EnumerateVisitor
+    {        
+        DeviceManagerImpl* pManager;
+        DeviceFactory*     pFactory;
+    public:
+        FactoryEnumerateVisitor(DeviceManagerImpl* manager, DeviceFactory* factory)
+            : pManager(manager), pFactory(factory) { }
+
+        virtual void Visit(const DeviceCreateDesc& createDesc)
+        {
+            pManager->AddDevice_NeedsLock(createDesc);
+        }
+    };
+
+    FactoryEnumerateVisitor newDeviceVisitor(this, factory);
+    factory->EnumerateDevices(newDeviceVisitor);
+
+
+    return 0;
+}
+
+
+DeviceEnumerator<> DeviceManagerImpl::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
+{
+    Lock::Locker deviceLock(GetLock());
+    
+    if (Devices.IsEmpty())
+        return DeviceEnumerator<>();
+
+    DeviceCreateDesc*  firstDeviceDesc = Devices.GetFirst();
+    DeviceEnumerator<> e = enumeratorFromHandle(DeviceHandle(firstDeviceDesc), args);
+
+    if (!args.MatchRule(firstDeviceDesc->Type, firstDeviceDesc->Enumerated))
+    {
+        e.Next();
+    }
+    
+    return e;
+}
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceCommon
+
+void DeviceCommon::DeviceAddRef()
+{
+    RefCount++;
+}
+
+void DeviceCommon::DeviceRelease()
+{
+    while(1)
+    {
+        UInt32 refCount = RefCount;
+        OVR_ASSERT(refCount > 0);
+        
+        if (refCount == 1)
+        {
+            DeviceManagerImpl*  manager = pCreateDesc->GetManagerImpl();
+            ThreadCommandQueue* queue   = manager->GetThreadQueue();
+
+            // Enqueue ReleaseDevice for {1 -> 0} transition with no wait.
+            // We pass our reference ownership into the queue to destroy.
+            // It's in theory possible for another thread to re-steal our device reference,
+            // but that is checked for atomically in DeviceManagerImpl::ReleaseDevice.
+            if (!queue->PushCall(manager, &DeviceManagerImpl::ReleaseDevice_MgrThread,
+                                          pCreateDesc->pDevice))
+            {
+                // PushCall shouldn't fail because background thread runs while manager is
+                // alive and we are holding Manager alive through pParent chain.
+                OVR_ASSERT(false);
+            }
+
+            // Warning! At his point everything, including manager, may be dead.
+            break;
+        }
+        else if (RefCount.CompareAndSet_NoSync(refCount, refCount-1))
+        {
+            break;
+        }
+    }
+}
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceCreateDesc
+
+
+void DeviceCreateDesc::AddRef()
+{
+    // Technically, HandleCount { 0 -> 1 } transition can only happen during Lock,
+    // but we leave this to caller to worry about (happens during enumeration).
+    HandleCount++;
+}
+
+void DeviceCreateDesc::Release()
+{
+    while(1)
+    {
+        UInt32 handleCount = HandleCount;
+        // HandleCount must obviously be >= 1, since we are releasing it.
+        OVR_ASSERT(handleCount > 0);
+
+        // {1 -> 0} transition may cause us to be destroyed, so require a lock.
+        if (handleCount == 1)
+        {       
+            Ptr<DeviceManagerLock>  lockKeepAlive;
+            Lock::Locker            deviceLockScope(GetLock());
+
+            if (!HandleCount.CompareAndSet_NoSync(handleCount, 0))
+                continue;
+            
+            OVR_ASSERT(pDevice == 0);
+
+            // Destroy *this if the manager was destroyed already, or Enumerated
+            // is false (device no longer available).           
+            if (!GetManagerImpl() || !Enumerated)
+            {
+                lockKeepAlive = pLock;
+
+                // Remove from manager list (only matters for !Enumerated).
+                if (pNext)
+                {
+                    RemoveNode();
+                    pNext = pPrev = 0;
+                }
+
+                delete this;
+            }
+
+            // Available DeviceCreateDesc may survive with { HandleCount == 0 },
+            // in case it might be enumerated again later.
+            break;
+        }
+        else if (HandleCount.CompareAndSet_NoSync(handleCount, handleCount-1))
+        {
+            break;
+        }
+    }
+}
+
+HMDDevice* HMDDevice::Disconnect(SensorDevice* psensor)
+{
+    if (!psensor)
+        return NULL;
+
+    OVR::DeviceManager* manager = GetManager();
+    if (manager)
+    {
+        //DeviceManagerImpl* mgrImpl = static_cast<DeviceManagerImpl*>(manager);
+        Ptr<DeviceCreateDesc> desc = getDeviceCommon()->pCreateDesc;
+        if (desc)
+        {
+            class Visitor : public DeviceFactory::EnumerateVisitor
+            {
+                Ptr<DeviceCreateDesc> Desc;
+            public:
+                Visitor(DeviceCreateDesc* desc) : Desc(desc) {}
+                virtual void Visit(const DeviceCreateDesc& createDesc) 
+                {
+                    Lock::Locker lock(Desc->GetLock());
+                    Desc->UpdateMatchedCandidate(createDesc);
+                }
+            } visitor(desc);
+            //SensorDeviceImpl* sImpl = static_cast<SensorDeviceImpl*>(psensor);
+
+            SensorDisplayInfoImpl displayInfo;
+
+            if (psensor->GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize))
+            {
+                displayInfo.Unpack();
+
+                // If we got display info, try to match / create HMDDevice as well
+                // so that sensor settings give preference.
+                if (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt)
+                {
+                    SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(displayInfo, visitor);
+                }
+            }
+        }
+    }
+    return this;
+}
+
+bool  HMDDevice::IsDisconnected() const
+{
+    OVR::HMDInfo info;
+    GetDeviceInfo(&info);
+    // if strlen(info.DisplayDeviceName) == 0 then
+    // this HMD is 'fake' (created using sensor).
+    return (strlen(info.DisplayDeviceName) == 0);
+}
+
+
+} // namespace OVR
+
diff --git a/LibOVR/Src/OVR_DeviceImpl.h b/LibOVR/Src/OVR_DeviceImpl.h
new file mode 100644
index 0000000..8e737a5
--- /dev/null
+++ b/LibOVR/Src/OVR_DeviceImpl.h
@@ -0,0 +1,428 @@
+/************************************************************************************
+
+Filename    :   OVR_DeviceImpl.h
+Content     :   Partial back-end independent implementation of Device interfaces
+Created     :   October 10, 2012
+Authors     :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_DeviceImpl_h
+#define OVR_DeviceImpl_h
+
+#include "OVR_Device.h"
+#include "Kernel/OVR_Atomic.h"
+#include "Kernel/OVR_Log.h"
+#include "Kernel/OVR_System.h"
+
+#include "Kernel/OVR_Threads.h"
+#include "OVR_ThreadCommandQueue.h"
+#include "OVR_HIDDevice.h"
+
+namespace OVR {
+    
+class DeviceManagerImpl;
+class DeviceFactory;
+
+enum
+{
+    Oculus_VendorId = 0x2833,
+    Device_Tracker_ProductId  = 0x0001,
+    Device_Tracker2_ProductId  = 0x0021,
+    Device_KTracker_ProductId = 0x0010,
+};
+
+
+// Wrapper for MessageHandler that includes synchronization logic.
+class MessageHandlerRef
+{   
+    enum
+    {
+        MaxHandlersCount = 4
+    };
+public:
+    MessageHandlerRef(DeviceBase* device);
+    ~MessageHandlerRef();
+
+    bool            HasHandlers() const { return HandlersCount > 0; };
+    void            AddHandler(MessageHandler* handler);
+    // returns false if the handler is not found
+    bool            RemoveHandler(MessageHandler* handler);
+    // Not-thread-safe version
+    void            AddHandler_NTS(MessageHandler* handler);
+    
+    void            Call(const Message& msg);
+
+    Lock*           GetLock() const { return pLock; }
+    DeviceBase*     GetDevice() const  { return pDevice; }
+
+private:
+    Lock*           pLock;   // Cached global handler lock.
+    DeviceBase*     pDevice;
+
+    int             HandlersCount;
+    MessageHandler* pHandlers[MaxHandlersCount];
+
+    bool            removeHandler(int idx);
+};
+
+
+//-------------------------------------------------------------------------------------
+
+// DeviceManagerLock is a synchronization lock used by DeviceManager for Devices
+// and is allocated separately for potentially longer lifetime.
+// 
+// DeviceManagerLock is used for all of the following:
+//  - Adding/removing devices
+//  - Reporting manager lifetime (pManager != 0) for DeviceHandles
+//  - Protecting device creation/shutdown.
+
+class DeviceManagerLock : public RefCountBase<DeviceManagerLock>
+{
+public:
+    Lock                CreateLock;
+    DeviceManagerImpl*  pManager;
+
+    DeviceManagerLock() : pManager(0) { }
+};
+
+
+// DeviceCreateDesc provides all of the information needed to create any device, a derived
+// instance of this class is created by DeviceFactory during enumeration.
+//   - DeviceCreateDesc may or may not be a part of DeviceManager::Devices list (check pNext != 0).
+//   - Referenced and kept alive by DeviceHandle.
+
+class DeviceCreateDesc : public ListNode<DeviceCreateDesc>, public NewOverrideBase
+{    
+    void operator = (const DeviceCreateDesc&) { } // Assign not supported; suppress MSVC warning.
+public:
+    DeviceCreateDesc(DeviceFactory* factory, DeviceType type)
+        : pFactory(factory), Type(type), pLock(0), HandleCount(0), pDevice(0), Enumerated(true)
+    {
+        pNext = pPrev = 0;
+    }
+
+    virtual ~DeviceCreateDesc()
+    {
+        OVR_ASSERT(!pDevice);
+        if (pNext)        
+            RemoveNode();
+    }
+
+    DeviceManagerImpl* GetManagerImpl() const { return pLock->pManager; }
+    Lock*              GetLock() const        { return &pLock->CreateLock; }
+
+    // DeviceCreateDesc reference counting is tied to Devices list management,
+    // see comments for HandleCount.
+    void AddRef();
+    void Release();
+
+
+    // *** Device creation/matching Interface
+
+
+    // Cloning copies us to an allocated object when new device is enumerated.
+    virtual DeviceCreateDesc* Clone() const = 0;
+    // Creates a new device instance without Initializing it; the
+    // later is done my Initialize()/Shutdown() methods of the device itself.
+    virtual DeviceBase*       NewDeviceInstance() = 0;
+    // Override to return device-specific info.
+    virtual bool              GetDeviceInfo(DeviceInfo* info) const = 0;
+
+
+    enum MatchResult
+    {
+        Match_None,
+        Match_Found,
+        Match_Candidate
+    };
+
+    // Override to return Match_Found if descriptor matches our device.
+    // Match_Candidate can be returned, with pcandicate update, if this may be a match
+    // but more searching is necessary. If this is the case UpdateMatchedCandidate will be called.
+    virtual MatchResult       MatchDevice(const DeviceCreateDesc& other,
+                                          DeviceCreateDesc** pcandidate) const = 0;
+    
+    // Called for matched candidate after all potential matches are iterated.
+    // Used to update HMDevice creation arguments from Sensor.
+    // Optional return param 'newDeviceFlag' will be set to true if the 
+    // 'desc' refers to a new device; false, otherwise.
+    // Return 'false' to create new object, 'true' if done with this argument.
+    virtual bool              UpdateMatchedCandidate(
+        const DeviceCreateDesc& desc, bool* newDeviceFlag = NULL) 
+    { OVR_UNUSED2(desc, newDeviceFlag); return false; }
+
+    // Matches HID device to the descriptor.
+    virtual bool              MatchHIDDevice(const HIDDeviceDesc&) const { return false; }
+
+    // Matches device by path.
+    virtual bool              MatchDevice(const String& /*path*/) { return false; }
+//protected:
+    DeviceFactory* const        pFactory;
+    const DeviceType            Type;
+
+    // List in which this descriptor lives. pList->CreateLock required if added/removed.
+    Ptr<DeviceManagerLock>      pLock;    
+
+    // Strong references to us: Incremented by Device, DeviceHandles & Enumerators.
+    // May be 0 if device not created and there are no handles.
+    // Following transitions require pList->CreateLock:
+    //  {1 -> 0}: May delete & remove handle if no longer available.
+    //  {0 -> 1}: Device creation is only possible if manager is still alive.
+    AtomicInt<UInt32>           HandleCount;
+    // If not null, points to our created device instance. Modified during lock only.
+    DeviceBase*                 pDevice;
+    // True if device is marked as available during enumeration.
+    bool                        Enumerated;
+};
+
+
+
+// Common data present in the implementation of every DeviceBase.
+// Injected by DeviceImpl.
+class DeviceCommon
+{
+public:
+    AtomicInt<UInt32>      RefCount;
+    Ptr<DeviceCreateDesc>  pCreateDesc;
+    Ptr<DeviceBase>        pParent;
+    volatile bool          ConnectedFlag;
+    MessageHandlerRef      HandlerRef;
+
+    DeviceCommon(DeviceCreateDesc* createDesc, DeviceBase* device, DeviceBase* parent)
+        : RefCount(1), pCreateDesc(createDesc), pParent(parent),
+          ConnectedFlag(true), HandlerRef(device)
+    {
+    }
+	virtual ~DeviceCommon() {}
+
+    // Device reference counting delegates to Manager thread to actually kill devices.
+    void DeviceAddRef();
+    void DeviceRelease();
+
+    Lock* GetLock() const { return pCreateDesc->GetLock(); }
+
+    virtual bool Initialize(DeviceBase* parent) = 0;
+    virtual void Shutdown() = 0;
+};
+
+
+//-------------------------------------------------------------------------------------
+// DeviceImpl address DeviceRecord implementation to a device base class B.
+// B must be derived form DeviceBase.
+
+template<class B>
+class DeviceImpl : public B, public DeviceCommon
+{
+public:
+    DeviceImpl(DeviceCreateDesc* createDesc, DeviceBase* parent)
+        : DeviceCommon(createDesc, getThis(), parent)        
+    {
+    }
+
+	// Convenience method to avoid manager access typecasts.
+    DeviceManagerImpl*  GetManagerImpl() const      { return pCreateDesc->pLock->pManager; }
+
+    // Inline to avoid warnings.
+    DeviceImpl*         getThis()                   { return this; }
+
+    // Common implementation delegate to avoid virtual inheritance and dynamic casts.
+    virtual DeviceCommon* getDeviceCommon() const   { return (DeviceCommon*)this; }
+
+    /*
+    virtual void            AddRef()                                   { pCreateDesc->DeviceAddRef(); }
+    virtual void            Release()                                  { pCreateDesc->DeviceRelease(); }
+    virtual DeviceBase*     GetParent() const                          { return pParent.GetPtr(); } 
+    virtual DeviceManager*  GetManager() const                         { return pCreateDesc->pLock->pManager;}
+    virtual void            SetMessageHandler(MessageHandler* handler) { HanderRef.SetHandler(handler); }
+    virtual MessageHandler* GetMessageHandler() const                  { return HanderRef.GetHandler(); }
+    virtual DeviceType      GetType() const                            { return pCreateDesc->Type; }
+    virtual DeviceType      GetType() const                            { return pCreateDesc->Type; }
+    */
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceFactory
+
+// DeviceFactory is maintained in DeviceManager for each separately-enumerable
+// device type; factories allow separation of unrelated enumeration code.
+
+class DeviceFactory : public ListNode<DeviceFactory>, public NewOverrideBase
+{    
+public:
+
+    DeviceFactory() : pManager(0)
+    {
+        pNext = pPrev = 0;
+    }
+    virtual ~DeviceFactory() { }
+
+    DeviceManagerImpl* GetManagerImpl() { return pManager; }
+
+    // Notifiers called when we are added to/removed from a device.
+    virtual bool AddedToManager(DeviceManagerImpl* manager)
+    {
+        OVR_ASSERT(pManager == 0);
+        pManager = manager;
+        return true;
+    }
+
+    virtual void RemovedFromManager()
+    {
+        pManager = 0;
+    }
+
+
+    // *** Device Enumeration/Creation Support
+    
+    // Passed to EnumerateDevices to be informed of every device detected.
+    class EnumerateVisitor
+    {
+    public:        
+        virtual void Visit(const DeviceCreateDesc& createDesc) = 0;
+    };
+
+    // Enumerates factory devices by notifying EnumerateVisitor about every
+    // device that is present.
+    virtual void EnumerateDevices(EnumerateVisitor& visitor) = 0;
+
+    // Matches vendorId/productId pair with the factory; returns 'true'
+    // if the factory can handle the device.
+    virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const
+    {
+        OVR_UNUSED2(vendorId, productId);
+        return false;
+    }
+
+    // Detects the HID device and adds the DeviceCreateDesc into Devices list, if
+    // the device belongs to this factory. Returns 'false', if not.
+    virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc)
+    {
+        OVR_UNUSED2(pdevMgr, desc);
+        return false;
+    }
+    
+protected:
+    DeviceManagerImpl* pManager;
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceManagerImpl
+
+// DeviceManagerImpl is a partial default DeviceManager implementation that
+// maintains a list of devices and supports their enumeration.
+
+class DeviceManagerImpl : public DeviceImpl<OVR::DeviceManager>, public ThreadCommandQueue
+{
+public:
+    DeviceManagerImpl();
+    ~DeviceManagerImpl();
+
+    // Constructor helper function to create Descriptor and manager lock during initialization.
+    static DeviceCreateDesc* CreateManagerDesc();
+
+    // DeviceManagerImpl provides partial implementation of Initialize/Shutdown that must
+    // be called by the platform-specific derived class.
+    virtual bool Initialize(DeviceBase* parent);
+    virtual void Shutdown();
+
+
+    // Every DeviceManager has an associated profile manager, which is used to store
+    // user settings that may affect device behavior. 
+    virtual ProfileManager* GetProfileManager() const { return pProfileManager.GetPtr(); }
+
+    // Override to return ThreadCommandQueue implementation used to post commands
+    // to the background device manager thread (that must be created by Initialize).
+    virtual ThreadCommandQueue* GetThreadQueue() = 0;
+
+    // Returns the thread id of the DeviceManager.
+    virtual ThreadId GetThreadId() const = 0;
+
+    virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args);
+
+
+    // 
+    void AddFactory(DeviceFactory* factory)
+    {
+        // This lock is only needed if we call AddFactory after manager thread creation.
+        Lock::Locker scopeLock(GetLock());
+        Factories.PushBack(factory);
+        factory->AddedToManager(this);        
+    }
+
+    void CallOnDeviceAdded(DeviceCreateDesc* desc)
+    {
+        HandlerRef.Call(MessageDeviceStatus(Message_DeviceAdded, this, DeviceHandle(desc)));
+    }
+    void CallOnDeviceRemoved(DeviceCreateDesc* desc)
+    {
+        HandlerRef.Call(MessageDeviceStatus(Message_DeviceRemoved, this, DeviceHandle(desc)));
+    }
+
+    // Helper to access Common data for a device.
+    static DeviceCommon* GetDeviceCommon(DeviceBase* device)
+    {
+        return device->getDeviceCommon();
+    }
+
+
+    // Background-thread callbacks for DeviceCreation/Release. These
+    DeviceBase* CreateDevice_MgrThread(DeviceCreateDesc* createDesc, DeviceBase* parent = 0);
+    Void        ReleaseDevice_MgrThread(DeviceBase* device);
+
+   
+    // Calls EnumerateDevices() on all factories
+    virtual Void EnumerateAllFactoryDevices();
+    // Enumerates devices for a particular factory.
+    virtual Void EnumerateFactoryDevices(DeviceFactory* factory);
+
+    virtual HIDDeviceManager* GetHIDDeviceManager() const
+    {
+        return HidDeviceManager;
+    }
+
+    // Adds device (DeviceCreateDesc*) into Devices. Returns NULL, 
+    // if unsuccessful or device is already in the list.
+    virtual Ptr<DeviceCreateDesc> AddDevice_NeedsLock(const DeviceCreateDesc& createDesc);
+    
+    // Finds a device descriptor by path and optional type.
+    Ptr<DeviceCreateDesc> FindDevice(const String& path, DeviceType = Device_None);
+
+    // Finds HID device by HIDDeviceDesc.
+    Ptr<DeviceCreateDesc> FindHIDDevice(const HIDDeviceDesc&, bool created);
+    void DetectHIDDevice(const HIDDeviceDesc&);
+
+    // Manager Lock-protected list of devices.
+    List<DeviceCreateDesc>  Devices;    
+
+    // Factories used to detect and manage devices.
+    List<DeviceFactory>     Factories;
+
+protected:
+    Ptr<HIDDeviceManager>   HidDeviceManager;
+    Ptr<ProfileManager>     pProfileManager;
+};
+
+
+} // namespace OVR
+
+#endif
diff --git a/LibOVR/Src/OVR_DeviceMessages.h b/LibOVR/Src/OVR_DeviceMessages.h
new file mode 100644
index 0000000..c182404
--- /dev/null
+++ b/LibOVR/Src/OVR_DeviceMessages.h
@@ -0,0 +1,273 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_DeviceMessages.h
+Content     :   Definition of messages generated by devices
+Created     :   February 5, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_DeviceMessages_h
+#define OVR_DeviceMessages_h
+
+#include "OVR_DeviceConstants.h"
+#include "OVR_DeviceHandle.h"
+
+#include "Kernel/OVR_Math.h"
+#include "Kernel/OVR_Array.h"
+#include "Kernel/OVR_Color.h"
+#include "Kernel/OVR_String.h"
+
+namespace OVR {
+
+class DeviceBase;
+class DeviceHandle;
+class String;
+
+
+#define OVR_MESSAGETYPE(devName, msgIndex)   ((Device_##devName << 8) | msgIndex)
+
+// MessageType identifies the structure of the Message class; based on the message,
+// casting can be used to obtain the exact value.
+enum MessageType
+{
+    // Used for unassigned message types.
+    Message_None            = 0,
+
+    // Device Manager Messages
+    Message_DeviceAdded             = OVR_MESSAGETYPE(Manager, 0),  // A new device is detected by manager.
+    Message_DeviceRemoved           = OVR_MESSAGETYPE(Manager, 1),  // Existing device has been plugged/unplugged.
+    // Sensor Messages
+    Message_BodyFrame               = OVR_MESSAGETYPE(Sensor, 0),   // Emitted by sensor at regular intervals.
+    Message_ExposureFrame	        = OVR_MESSAGETYPE(Sensor, 1),
+    Message_PixelRead               = OVR_MESSAGETYPE(Sensor, 2),
+
+    // Latency Tester Messages
+    Message_LatencyTestSamples          = OVR_MESSAGETYPE(LatencyTester, 0),
+    Message_LatencyTestColorDetected    = OVR_MESSAGETYPE(LatencyTester, 1),
+    Message_LatencyTestStarted          = OVR_MESSAGETYPE(LatencyTester, 2),
+    Message_LatencyTestButton           = OVR_MESSAGETYPE(LatencyTester, 3),
+    
+    Message_CameraFrame					= OVR_MESSAGETYPE(Camera, 0),
+	Message_CameraAdded			        = OVR_MESSAGETYPE(Camera, 1),	
+};
+
+//-------------------------------------------------------------------------------------
+// Base class for all messages.
+class Message
+{
+public:
+    Message(MessageType type = Message_None,
+            DeviceBase* pdev = 0) : Type(type), pDevice(pdev)
+    { }
+
+    MessageType Type;    // What kind of message this is.
+    DeviceBase* pDevice; // Device that emitted the message.
+};
+
+
+// Sensor BodyFrame notification.
+// Sensor uses Right-Handed coordinate system to return results, with the following
+// axis definitions:
+//  - Y Up positive
+//  - X Right Positive
+//  - Z Back Positive
+// Rotations a counter-clockwise (CCW) while looking in the negative direction
+// of the axis. This means they are interpreted as follows:
+//  - Roll is rotation around Z, counter-clockwise (tilting left) in XY plane.
+//  - Yaw is rotation around Y, positive for turning left.
+//  - Pitch is rotation around X, positive for pitching up.
+
+//-------------------------------------------------------------------------------------
+// ***** Sensor
+
+class MessageBodyFrame : public Message
+{
+public:
+    MessageBodyFrame(DeviceBase* dev)
+        : Message(Message_BodyFrame, dev), Temperature(0.0f), TimeDelta(0.0f)
+    {
+    }
+
+    Vector3f Acceleration;   // Acceleration in m/s^2.
+    Vector3f RotationRate;   // Angular velocity in rad/s.
+    Vector3f MagneticField;  // Magnetic field strength in Gauss.
+    float    Temperature;    // Temperature reading on sensor surface, in degrees Celsius.
+    float    TimeDelta;      // Time passed since last Body Frame, in seconds.
+
+    // The absolute time from the host computers perspective that the message should be
+    // interpreted as. This is based on incoming timestamp and processed by a filter
+    // that syncs the clocks while attempting to keep the distance between messages
+    // device clock matching.
+    //
+    // Integration should use TimeDelta, but prediction into the future should derive
+    // the delta time from PredictToSeconds - AbsoluteTimeSeconds.
+    //
+    // This value will generally be <= the return from a call to ovr_GetTimeInSeconds(),
+    // but could be greater by under 1 ms due to system time update interrupt delays.
+    //
+    double   AbsoluteTimeSeconds;
+};
+
+// Sent when we receive a device status changes (e.g.:
+// Message_DeviceAdded, Message_DeviceRemoved).
+class MessageDeviceStatus : public Message
+{
+public:
+    MessageDeviceStatus(MessageType type, DeviceBase* dev, const DeviceHandle &hdev)
+        : Message(type, dev), Handle(hdev) { }
+
+    DeviceHandle Handle;
+};
+
+class MessageExposureFrame : public Message
+{
+public:
+    MessageExposureFrame(DeviceBase* dev)
+        : Message(Message_ExposureFrame, dev),
+        CameraPattern(0), CameraFrameCount(0), CameraTimeSeconds(0) { }
+
+    UByte   CameraPattern;
+    UInt32  CameraFrameCount;
+    double  CameraTimeSeconds;
+};
+
+class MessagePixelRead : public Message
+{
+public:
+    MessagePixelRead(DeviceBase* dev)
+        : Message(Message_PixelRead, dev),
+        PixelReadValue(0), SensorTimeSeconds(0), FrameTimeSeconds(0) { }
+
+    UByte   PixelReadValue;
+    UInt32  RawSensorTime;
+    UInt32  RawFrameTime;
+    double  SensorTimeSeconds;
+    double  FrameTimeSeconds;
+};
+
+//-------------------------------------------------------------------------------------
+// ***** Latency Tester
+
+// Sent when we receive Latency Tester samples.
+class MessageLatencyTestSamples : public Message
+{
+public:
+    MessageLatencyTestSamples(DeviceBase* dev)
+        : Message(Message_LatencyTestSamples, dev)
+    {
+    }
+
+    Array<Color>     Samples;
+};
+
+// Sent when a Latency Tester 'color detected' event occurs.
+class MessageLatencyTestColorDetected : public Message
+{
+public:
+    MessageLatencyTestColorDetected(DeviceBase* dev)
+        : Message(Message_LatencyTestColorDetected, dev)
+    {
+    }
+
+    UInt16      Elapsed;
+    Color       DetectedValue;
+    Color       TargetValue;
+};
+
+// Sent when a Latency Tester 'change color' event occurs.
+class MessageLatencyTestStarted : public Message
+{
+public:
+    MessageLatencyTestStarted(DeviceBase* dev)
+        : Message(Message_LatencyTestStarted, dev)
+    {
+    }
+
+    Color    TargetValue;
+};
+
+// Sent when a Latency Tester 'button' event occurs.
+class MessageLatencyTestButton : public Message
+{
+public:
+    MessageLatencyTestButton(DeviceBase* dev)
+        : Message(Message_LatencyTestButton, dev)
+    {
+    }
+
+};
+
+//-------------------------------------------------------------------------------------
+// ***** Camera
+
+// Sent by camera, frame.
+class MessageCameraFrame : public Message
+{
+public:
+    MessageCameraFrame(DeviceBase* dev)
+        : Message(Message_CameraFrame, dev), CameraHandle(NULL), pFrameData(NULL)
+    {
+        LostFrames = 0;
+    }
+
+    void SetInfo(UInt32 frameNumber, double timeSeconds, UInt32 width, UInt32 height, UInt32 format)
+    {
+        FrameNumber = frameNumber;
+        ArrivalTimeSeconds = timeSeconds;
+        Width = width;
+        Height = height;
+        Format = format;
+    }
+
+    void SetData(const UByte* pdata, UInt32 sizeInBytes)
+    {
+        pFrameData = pdata;
+        FrameSizeInBytes = sizeInBytes;
+    }
+
+    UInt32   FrameNumber;			// an index of the frame
+    double   ArrivalTimeSeconds;    // frame time in seconds, as recorded by the host computer
+    const UByte* pFrameData;		// a ptr to frame data. 
+    UInt32   FrameSizeInBytes;		// size of the data in the pFrameData.
+    UInt32   Width, Height;			// width & height in pixels.
+    UInt32   Format;				// format of pixel, see CameraDevice::PixelFormat enum
+    UInt32   LostFrames;			// number of lost frames before this frame
+	String	  DeviceIdentifier;		// identifies the device sensing the message
+    UInt32* CameraHandle;			// Identifies the camera object associated with this frame
+};
+
+// Sent when a new camera is connected
+class MessageCameraAdded : public Message
+{
+public:
+    MessageCameraAdded(DeviceBase* dev)
+        : Message(Message_CameraAdded, dev) { }
+
+    MessageCameraAdded(UInt32* cam)
+        : Message(Message_CameraAdded, NULL), CameraHandle(cam) { }
+
+    UInt32* CameraHandle;			// Identifies the camera object associated with this frame
+};
+
+} // namespace OVR
+
+#endif
diff --git a/LibOVR/Src/OVR_HIDDevice.h b/LibOVR/Src/OVR_HIDDevice.h
new file mode 100644
index 0000000..24bfcfa
--- /dev/null
+++ b/LibOVR/Src/OVR_HIDDevice.h
@@ -0,0 +1,154 @@
+/************************************************************************************
+
+Filename    :   OVR_HIDDevice.h
+Content     :   Cross platform HID device interface.
+Created     :   February 22, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_HIDDevice_h
+#define OVR_HIDDevice_h
+
+#include "OVR_HIDDeviceBase.h"
+
+#include "Kernel/OVR_RefCount.h"
+#include "Kernel/OVR_String.h"
+#include "Kernel/OVR_Timer.h"
+
+namespace OVR {
+
+class HIDDevice;
+class DeviceManager;
+
+// HIDDeviceDesc contains interesting attributes of a HID device, including a Path
+// that can be used to create it.
+struct HIDDeviceDesc
+{
+    UInt16  VendorId;
+    UInt16  ProductId;
+    UInt16  VersionNumber;
+    UInt16  Usage;
+    UInt16  UsagePage;
+    String  Path;           // Platform specific.
+    String  Manufacturer;
+    String  Product;
+    String  SerialNumber;
+};
+
+// HIDEnumerateVisitor exposes a Visit interface called for every detected device
+// by HIDDeviceManager::Enumerate. 
+class HIDEnumerateVisitor
+{
+public:
+
+    // Should return true if we are interested in supporting
+    // this HID VendorId and ProductId pair.
+    virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId)
+    { OVR_UNUSED2(vendorId, productId); return true; }
+
+    // Override to get notified about available device. Will only be called for
+    // devices that matched MatchVendorProduct.
+    virtual void Visit(HIDDevice&, const HIDDeviceDesc&) { }
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** HIDDeviceManager
+
+// Internal manager for enumerating and opening HID devices.
+// If an OVR::DeviceManager is created then an OVR::HIDDeviceManager will automatically be created and can be accessed from the
+// DeviceManager by calling 'GetHIDDeviceManager()'. When using HIDDeviceManager in standalone mode, the client must call
+// 'Create' below.
+class HIDDeviceManager : public RefCountBase<HIDDeviceManager>
+{
+public:
+
+    // Creates a new HIDDeviceManager. Only one instance of HIDDeviceManager should be created at a time.
+    static HIDDeviceManager* Create(Ptr<OVR::DeviceManager>& deviceManager);
+
+    // Enumerate HID devices using a HIDEnumerateVisitor derived visitor class.
+    virtual bool Enumerate(HIDEnumerateVisitor* enumVisitor) = 0;
+
+    // Open a HID device with the specified path.
+    virtual HIDDevice* Open(const String& path) = 0;
+
+protected:
+    HIDDeviceManager()
+    { }
+};
+
+//-------------------------------------------------------------------------------------
+// ***** HIDDevice
+
+// HID device object. This is designed to be operated in synchronous
+// and asynchronous modes. With no handler set, input messages will be
+// stored and can be retrieved by calling 'Read' or 'ReadBlocking'.
+class HIDDevice : public RefCountBase<HIDDevice>, public HIDDeviceBase
+{
+public:
+
+    HIDDevice()
+     :  Handler(NULL)
+    {
+    }
+
+    virtual ~HIDDevice() {}
+
+    virtual bool SetFeatureReport(UByte* data, UInt32 length) = 0;
+    virtual bool GetFeatureReport(UByte* data, UInt32 length) = 0;
+
+// Not yet implemented.
+/*
+    virtual bool Write(UByte* data, UInt32 length) = 0;
+
+    virtual bool Read(UByte* pData, UInt32 length, UInt32 timeoutMilliS) = 0;
+    virtual bool ReadBlocking(UByte* pData, UInt32 length) = 0;
+*/
+
+    class HIDHandler
+    {
+    public:
+        virtual void OnInputReport(UByte* pData, UInt32 length)
+        { OVR_UNUSED2(pData, length); }
+
+        virtual double OnTicks(double tickSeconds)
+        { OVR_UNUSED1(tickSeconds);  return 1000.0 ; }
+
+        enum HIDDeviceMessageType
+        {
+            HIDDeviceMessage_DeviceAdded    = 0,
+            HIDDeviceMessage_DeviceRemoved  = 1
+        };
+
+        virtual void OnDeviceMessage(HIDDeviceMessageType messageType) 
+        { OVR_UNUSED1(messageType); }
+    };
+
+    void SetHandler(HIDHandler* handler)
+    { Handler = handler; }
+
+protected:
+    HIDHandler* Handler;
+};
+
+} // namespace OVR
+
+#endif
diff --git a/LibOVR/Src/OVR_HIDDeviceBase.h b/LibOVR/Src/OVR_HIDDeviceBase.h
new file mode 100644
index 0000000..7dfd6b4
--- /dev/null
+++ b/LibOVR/Src/OVR_HIDDeviceBase.h
@@ -0,0 +1,51 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_HIDDeviceBase.h
+Content     :   Definition of HID device interface.
+Created     :   March 11, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_HIDDeviceBase_h
+#define OVR_HIDDeviceBase_h
+
+#include "Kernel/OVR_Types.h"
+
+namespace OVR {
+
+//-------------------------------------------------------------------------------------
+// ***** HIDDeviceBase
+
+// Base interface for HID devices.
+class HIDDeviceBase
+{
+public:
+
+    virtual ~HIDDeviceBase() { }
+
+    virtual bool SetFeatureReport(UByte* data, UInt32 length) = 0;
+    virtual bool GetFeatureReport(UByte* data, UInt32 length) = 0;
+};
+
+} // namespace OVR
+
+#endif
diff --git a/LibOVR/Src/OVR_HIDDeviceImpl.h b/LibOVR/Src/OVR_HIDDeviceImpl.h
new file mode 100644
index 0000000..1399da6
--- /dev/null
+++ b/LibOVR/Src/OVR_HIDDeviceImpl.h
@@ -0,0 +1,201 @@
+/************************************************************************************
+
+Filename    :   OVR_HIDDeviceImpl.h
+Content     :   Implementation of HIDDevice.
+Created     :   March 7, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_HIDDeviceImpl_h
+#define OVR_HIDDeviceImpl_h
+
+//#include "OVR_Device.h"
+#include "OVR_DeviceImpl.h"
+
+namespace OVR {
+
+//-------------------------------------------------------------------------------------
+class HIDDeviceCreateDesc : public DeviceCreateDesc
+{
+public:
+    HIDDeviceCreateDesc(DeviceFactory* factory, DeviceType type, const HIDDeviceDesc& hidDesc)
+        : DeviceCreateDesc(factory, type), HIDDesc(hidDesc) { }
+    HIDDeviceCreateDesc(const HIDDeviceCreateDesc& other)
+        : DeviceCreateDesc(other.pFactory, other.Type), HIDDesc(other.HIDDesc) { }
+
+    virtual bool MatchDevice(const String& path)
+    {
+        // should it be case insensitive?
+        return HIDDesc.Path.CompareNoCase(path) == 0;
+    }
+
+    HIDDeviceDesc HIDDesc;
+};
+
+//-------------------------------------------------------------------------------------
+template<class B>
+class HIDDeviceImpl : public DeviceImpl<B>, public HIDDevice::HIDHandler
+{
+public:
+    HIDDeviceImpl(HIDDeviceCreateDesc* createDesc, DeviceBase* parent)
+     :  DeviceImpl<B>(createDesc, parent)        
+    {
+    }
+
+    // HIDDevice::Handler interface.
+    virtual void OnDeviceMessage(HIDDeviceMessageType messageType)
+    {
+        MessageType handlerMessageType;
+        switch (messageType) {
+            case HIDDeviceMessage_DeviceAdded:
+                handlerMessageType           = Message_DeviceAdded;
+                DeviceImpl<B>::ConnectedFlag = true;
+                break;
+
+            case HIDDeviceMessage_DeviceRemoved:
+                handlerMessageType           = Message_DeviceRemoved;
+                DeviceImpl<B>::ConnectedFlag = false;
+                break;
+
+            default: OVR_ASSERT(0); return;
+        }
+
+        // Do device notification.
+        MessageDeviceStatus status(handlerMessageType, this, OVR::DeviceHandle(this->pCreateDesc));
+        this->HandlerRef.Call(status);
+
+        // Do device manager notification.
+        DeviceManagerImpl*   manager = this->GetManagerImpl();
+        switch (handlerMessageType) {
+            case Message_DeviceAdded:
+                manager->CallOnDeviceAdded(this->pCreateDesc);
+                break;
+                
+            case Message_DeviceRemoved:
+                manager->CallOnDeviceRemoved(this->pCreateDesc);
+                break;
+                
+            default:;
+        }
+    }
+
+    virtual bool Initialize(DeviceBase* parent)
+    {
+        // Open HID device.
+        HIDDeviceDesc&		hidDesc = *getHIDDesc();
+        HIDDeviceManager*   pManager = GetHIDDeviceManager();
+
+
+        HIDDevice* device = pManager->Open(hidDesc.Path);
+        if (!device)
+        {
+            return false;
+        }
+
+        InternalDevice = *device;
+        InternalDevice->SetHandler(this);
+
+        // AddRef() to parent, forcing chain to stay alive.
+        DeviceImpl<B>::pParent = parent;
+
+        return true;
+    }
+
+    virtual void Shutdown()
+    {   
+        InternalDevice->SetHandler(NULL);
+
+        DeviceImpl<B>::pParent.Clear();
+    }
+
+    DeviceManager* GetDeviceManager()
+    {
+        return DeviceImpl<B>::pCreateDesc->GetManagerImpl();
+    }
+
+    HIDDeviceManager* GetHIDDeviceManager()
+    {
+        return DeviceImpl<B>::pCreateDesc->GetManagerImpl()->GetHIDDeviceManager();
+    }
+
+    bool SetFeatureReport(UByte* data, UInt32 length)
+    { 
+        // Push call with wait.
+        bool result = false;
+
+		ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue();
+        if (!pQueue->PushCallAndWaitResult(this, &HIDDeviceImpl::setFeatureReport, &result, data, length))
+            return false;
+
+        return result;
+    }
+
+    bool setFeatureReport(UByte* data, UInt32 length)
+    {
+        return InternalDevice->SetFeatureReport(data, length);
+    }
+
+    bool GetFeatureReport(UByte* data, UInt32 length)
+    { 
+        bool result = false;
+
+		ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue();
+        if (!pQueue->PushCallAndWaitResult(this, &HIDDeviceImpl::getFeatureReport, &result, data, length))
+            return false;
+
+        return result;
+    }
+
+    bool getFeatureReport(UByte* data, UInt32 length)
+    {
+        return InternalDevice->GetFeatureReport(data, length);
+    }
+
+	UByte GetDeviceInterfaceVersion()
+	{
+		UInt16 versionNumber = getHIDDesc()->VersionNumber;
+
+		// Our interface and hardware versions are represented as two BCD digits each.
+		// Interface version is in the last two digits.
+		UByte interfaceVersion = (UByte)	((versionNumber & 0x000F) >> 0) * 1 +
+											((versionNumber & 0x00F0) >> 4) * 10;
+		return interfaceVersion;
+	}
+
+protected:
+    HIDDevice* GetInternalDevice() const
+    {
+        return InternalDevice;
+    }
+
+    HIDDeviceDesc* getHIDDesc() const
+    { return &getCreateDesc()->HIDDesc; }
+
+    HIDDeviceCreateDesc* getCreateDesc() const
+    { return (HIDDeviceCreateDesc*) &(*DeviceImpl<B>::pCreateDesc); }
+
+private:
+    Ptr<HIDDevice> InternalDevice;
+};
+
+} // namespace OVR
+
+#endif
diff --git a/LibOVR/Src/OVR_JSON.cpp b/LibOVR/Src/OVR_JSON.cpp
new file mode 100644
index 0000000..262a0d9
--- /dev/null
+++ b/LibOVR/Src/OVR_JSON.cpp
@@ -0,0 +1,1185 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_JSON.h
+Content     :   JSON format reader and writer
+Created     :   April 9, 2013
+Author      :   Brant Lewis
+Notes       :
+  The code is a derivative of the cJSON library written by Dave Gamble and subject 
+  to the following permissive copyright.
+
+  Copyright (c) 2009 Dave Gamble
+ 
+  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.
+
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+#include "OVR_JSON.h"
+#include "Kernel/OVR_SysFile.h"
+#include "Kernel/OVR_Log.h"
+
+namespace OVR {
+
+
+//-----------------------------------------------------------------------------
+// Create a new copy of a string
+static char* JSON_strdup(const char* str)
+{
+    UPInt len  = OVR_strlen(str) + 1;
+    char* copy = (char*)OVR_ALLOC(len);
+    if (!copy)
+        return 0;
+    memcpy(copy, str, len);
+    return copy;
+}
+
+
+//-----------------------------------------------------------------------------
+// Render the number from the given item into a string.
+static char* PrintNumber(double d)
+{
+	char *str;
+	//double d=item->valuedouble;
+    int valueint = (int)d;
+	if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
+	{
+		str=(char*)OVR_ALLOC(21);	// 2^64+1 can be represented in 21 chars.
+		if (str)
+            OVR_sprintf(str, 21, "%d", valueint);
+	}
+	else
+	{
+		str=(char*)OVR_ALLOC(64);	// This is a nice tradeoff.
+		if (str)
+		{
+			if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)
+                OVR_sprintf(str, 64, "%.0f", d);
+			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)
+                OVR_sprintf(str, 64, "%e", d);
+			else
+                OVR_sprintf(str, 64, "%f", d);
+		}
+	}
+	return str;
+}
+
+// Parse the input text into an un-escaped cstring, and populate item.
+static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+
+// Helper to assign error sting and return 0.
+const char* AssignError(const char** perror, const char *errorMessage)
+{
+    if (perror)
+        *perror = errorMessage;
+    return 0;
+}
+
+//-----------------------------------------------------------------------------
+// ***** JSON Node class
+
+JSON::JSON(JSONItemType itemType)
+    : Type(itemType), dValue(0.0)
+{
+}
+
+JSON::~JSON()
+{
+    JSON* child = Children.GetFirst();
+    while (!Children.IsNull(child))
+    {
+        child->RemoveNode();
+        child->Release();
+        child = Children.GetFirst();
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Parse the input text to generate a number, and populate the result into item
+// Returns the text position after the parsed number
+const char* JSON::parseNumber(const char *num)
+{
+    const char* num_start = num;
+    double      n=0, sign=1, scale=0;
+    int         subscale     = 0,
+                signsubscale = 1;
+
+	// Could use sscanf for this?
+	if (*num=='-') 
+        sign=-1,num++;	// Has sign?
+	if (*num=='0')
+        num++;			// is zero
+	
+    if (*num>='1' && *num<='9')	
+    {
+        do
+        {   
+            n=(n*10.0)+(*num++ -'0');
+        }
+        while (*num>='0' && *num<='9');	// Number?
+    }
+
+	if (*num=='.' && num[1]>='0' && num[1]<='9')
+    {
+        num++;
+        do
+        {
+            n=(n*10.0)+(*num++ -'0');
+            scale--;
+        }
+        while (*num>='0' && *num<='9');  // Fractional part?
+    }
+
+	if (*num=='e' || *num=='E')		// Exponent?
+	{
+        num++;
+        if (*num=='+')
+            num++;
+        else if (*num=='-')
+        {
+            signsubscale=-1;
+            num++;		// With sign?
+        }
+
+		while (*num>='0' && *num<='9')
+            subscale=(subscale*10)+(*num++ - '0');	// Number?
+	}
+
+    // Number = +/- number.fraction * 10^+/- exponent
+	n = sign*n*pow(10.0,(scale+subscale*signsubscale));
+
+    // Assign parsed value.
+	Type   = JSON_Number;
+    dValue = n;
+    Value.AssignString(num_start, num - num_start);
+    
+	return num;
+}
+
+// Parses a hex string up to the specified number of digits.
+// Returns the first character after the string.
+const char* ParseHex(unsigned* val, unsigned digits, const char* str)
+{
+    *val = 0;
+
+    for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++)
+    {
+        unsigned v = *str;
+
+        if ((v >= '0') && (v <= '9'))
+            v -= '0';
+        else if ((v >= 'a') && (v <= 'f'))
+            v = 10 + v - 'a';
+        else if ((v >= 'A') && (v <= 'F'))
+            v = 10 + v - 'A';
+        else
+            break;
+
+        *val = *val * 16 + v;
+    }
+
+    return str;
+}
+
+//-----------------------------------------------------------------------------
+// Parses the input text into a string item and returns the text position after
+// the parsed string
+const char* JSON::parseString(const char* str, const char** perror)
+{
+	const char* ptr = str+1;
+    const char* p;
+    char*       ptr2;
+    char*       out;
+    int         len=0;
+    unsigned    uc, uc2;
+	
+    if (*str!='\"')
+    {
+        return AssignError(perror, "Syntax Error: Missing quote");
+    }
+	
+	while (*ptr!='\"' && *ptr && ++len)
+    {   
+        if (*ptr++ == '\\') ptr++;	// Skip escaped quotes.
+    }
+	
+    // This is how long we need for the string, roughly.
+	out=(char*)OVR_ALLOC(len+1);
+	if (!out)
+        return 0;
+	
+	ptr = str+1;
+    ptr2= out;
+
+	while (*ptr!='\"' && *ptr)
+	{
+		if (*ptr!='\\')
+        {
+            *ptr2++ = *ptr++;
+        }
+		else
+		{
+			ptr++;
+			switch (*ptr)
+			{
+				case 'b': *ptr2++ = '\b';	break;
+				case 'f': *ptr2++ = '\f';	break;
+				case 'n': *ptr2++ = '\n';	break;
+				case 'r': *ptr2++ = '\r';	break;
+				case 't': *ptr2++ = '\t';	break;
+
+                // Transcode utf16 to utf8.
+                case 'u':
+
+                    // Get the unicode char.
+                    p = ParseHex(&uc, 4, ptr + 1);
+                    if (ptr != p)
+                        ptr = p - 1;
+
+					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)
+                        break;	// Check for invalid.
+
+                    // UTF16 surrogate pairs.
+					if (uc>=0xD800 && uc<=0xDBFF)
+					{
+						if (ptr[1]!='\\' || ptr[2]!='u')
+                            break;	// Missing second-half of surrogate.
+
+                        p= ParseHex(&uc2, 4, ptr + 3);
+                        if (ptr != p)
+                            ptr = p - 1;
+                        
+						if (uc2<0xDC00 || uc2>0xDFFF)
+                            break;	// Invalid second-half of surrogate.
+
+						uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
+					}
+
+					len=4;
+                    
+                    if (uc<0x80)
+                        len=1;
+                    else if (uc<0x800)
+                        len=2;
+                    else if (uc<0x10000)
+                        len=3;
+                    
+                    ptr2+=len;
+					
+					switch (len)
+                    {
+						case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+						case 1: *--ptr2 = (char)(uc | firstByteMark[len]);
+					}
+					ptr2+=len;
+					break;
+
+                default:
+                    *ptr2++ = *ptr;
+                    break;
+			}
+			ptr++;
+		}
+	}
+
+	*ptr2 = 0;
+	if (*ptr=='\"')
+        ptr++;
+	
+    // Make a copy of the string 
+    Value=out;
+    OVR_FREE(out);
+	Type=JSON_String;
+
+	return ptr;
+}
+
+//-----------------------------------------------------------------------------
+// Render the string provided to an escaped version that can be printed.
+char* PrintString(const char* str)
+{
+	const char *ptr;
+    char *ptr2,*out;
+    int len=0;
+    unsigned char token;
+	
+	if (!str)
+        return JSON_strdup("");
+	ptr=str;
+    
+    token=*ptr;
+    while (token && ++len)\
+    {
+        if (strchr("\"\\\b\f\n\r\t",token))
+            len++;
+        else if (token<32) 
+            len+=5;
+        ptr++;
+        token=*ptr;
+    }
+	
+	int buff_size = len+3;
+    out=(char*)OVR_ALLOC(buff_size);
+	if (!out)
+        return 0;
+
+	ptr2 = out;
+    ptr  = str;
+	*ptr2++ = '\"';
+
+	while (*ptr)
+	{
+		if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') 
+            *ptr2++=*ptr++;
+		else
+		{
+			*ptr2++='\\';
+			switch (token=*ptr++)
+			{
+				case '\\':	*ptr2++='\\';	break;
+				case '\"':	*ptr2++='\"';	break;
+				case '\b':	*ptr2++='b';	break;
+				case '\f':	*ptr2++='f';	break;
+				case '\n':	*ptr2++='n';	break;
+				case '\r':	*ptr2++='r';	break;
+				case '\t':	*ptr2++='t';	break;
+				default: 
+                    OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token);
+                    ptr2+=5;
+                    break;	// Escape and print.
+			}
+		}
+	}
+	*ptr2++='\"';
+    *ptr2++=0;
+	return out;
+}
+
+//-----------------------------------------------------------------------------
+// Utility to jump whitespace and cr/lf
+static const char* skip(const char* in)
+{
+    while (in && *in && (unsigned char)*in<=' ') 
+        in++; 
+    return in;
+}
+
+//-----------------------------------------------------------------------------
+// Parses the supplied buffer of JSON text and returns a JSON object tree
+// The returned object must be Released after use
+JSON* JSON::Parse(const char* buff, const char** perror)
+{
+    const char* end = 0;
+	JSON*       json = new JSON();
+	
+	if (!json)
+    {
+        AssignError(perror, "Error: Failed to allocate memory");
+        return 0;
+    }
+ 
+	end = json->parseValue(skip(buff), perror);
+	if (!end)
+    {
+        json->Release();
+        return NULL;
+    }	// parse failure. ep is set.
+
+    return json;
+}
+
+//-----------------------------------------------------------------------------
+// This version works for buffers that are not null terminated strings.
+JSON* JSON::ParseBuffer(const char *buff, int len, const char** perror)
+{
+	// Our JSON parser does not support length-based parsing,
+	// so ensure it is null-terminated.
+	char *termStr = new char[len + 1];
+	memcpy(termStr, buff, len);
+	termStr[len] = '\0';
+
+	JSON *objJson = Parse(termStr, perror);
+
+	delete[]termStr;
+
+	return objJson;
+}
+
+//-----------------------------------------------------------------------------
+// Parser core - when encountering text, process appropriately.
+const char* JSON::parseValue(const char* buff, const char** perror)
+{
+    if (perror)
+        *perror = 0;
+
+	if (!buff)
+        return NULL;	// Fail on null.
+
+	if (!strncmp(buff,"null",4))
+    {
+        Type = JSON_Null;
+        return buff+4;
+    }
+	if (!strncmp(buff,"false",5))
+    { 
+        Type   = JSON_Bool;
+        Value  = "false";
+        dValue = 0;
+        return buff+5;
+    }
+	if (!strncmp(buff,"true",4))
+    {
+        Type   = JSON_Bool;
+        Value  = "true";
+        dValue = 1;
+        return buff+4;
+    }
+	if (*buff=='\"')
+    {
+        return parseString(buff, perror);
+    }
+	if (*buff=='-' || (*buff>='0' && *buff<='9'))
+    { 
+        return parseNumber(buff);
+    }
+	if (*buff=='[')
+    { 
+        return parseArray(buff, perror);
+    }
+	if (*buff=='{')
+    {
+        return parseObject(buff, perror);
+    }
+
+    return AssignError(perror, "Syntax Error: Invalid syntax");
+}
+
+
+//-----------------------------------------------------------------------------
+// Render a value to text. 
+char* JSON::PrintValue(int depth, bool fmt)
+{
+	char *out=0;
+
+    switch (Type)
+	{
+        case JSON_Null:	    out = JSON_strdup("null");	break;
+        case JSON_Bool:
+            if (dValue == 0)
+                out = JSON_strdup("false");
+            else
+                out = JSON_strdup("true");
+            break;
+        case JSON_Number:	out = PrintNumber(dValue); break;
+        case JSON_String:	out = PrintString(Value); break;
+        case JSON_Array:	out = PrintArray(depth, fmt); break;
+        case JSON_Object:	out = PrintObject(depth, fmt); break;
+        case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break;
+	}
+	return out;
+}
+
+//-----------------------------------------------------------------------------
+// Build an array object from input text and returns the text position after
+// the parsed array
+const char* JSON::parseArray(const char* buff, const char** perror)
+{
+	JSON *child;
+	if (*buff!='[')
+    {
+        return AssignError(perror, "Syntax Error: Missing opening bracket");
+    }
+
+	Type=JSON_Array;
+	buff=skip(buff+1);
+	
+    if (*buff==']')
+        return buff+1;	// empty array.
+
+    child = new JSON();
+	if (!child)
+        return 0;		 // memory fail
+    Children.PushBack(child);
+	
+    buff=skip(child->parseValue(skip(buff), perror));	// skip any spacing, get the buff. 
+	if (!buff)
+        return 0;
+
+	while (*buff==',')
+	{
+		JSON *new_item = new JSON();
+		if (!new_item)
+            return AssignError(perror, "Error: Failed to allocate memory");
+		
+        Children.PushBack(new_item);
+
+		buff=skip(new_item->parseValue(skip(buff+1), perror));
+		if (!buff)
+            return AssignError(perror, "Error: Failed to allocate memory");
+	}
+
+	if (*buff==']')
+        return buff+1;	// end of array
+
+    return AssignError(perror, "Syntax Error: Missing ending bracket");
+}
+
+//-----------------------------------------------------------------------------
+// Render an array to text.  The returned text must be freed
+char* JSON::PrintArray(int depth, bool fmt)
+{
+	char **entries;
+	char * out = 0,*ptr,*ret;
+    SPInt  len = 5;
+	
+    bool fail = false;
+	
+	// How many entries in the array? 
+    int numentries = GetItemCount();
+	if (!numentries)
+	{
+		out=(char*)OVR_ALLOC(3);
+		if (out)
+            OVR_strcpy(out, 3, "[]");
+		return out;
+	}
+	// Allocate an array to hold the values for each
+	entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
+	if (!entries)
+        return 0;
+	memset(entries,0,numentries*sizeof(char*));
+
+	//// Retrieve all the results:
+    JSON* child = Children.GetFirst();
+    for (int i=0; i<numentries; i++)
+	{
+		//JSON* child = Children[i];
+        ret=child->PrintValue(depth+1, fmt);
+		entries[i]=ret;
+		if (ret)
+            len+=OVR_strlen(ret)+2+(fmt?1:0);
+        else
+        {
+            fail = true;
+            break;
+        }
+        child = Children.GetNext(child);
+	}
+	
+	// If we didn't fail, try to malloc the output string 
+	if (!fail)
+        out=(char*)OVR_ALLOC(len);
+	// If that fails, we fail. 
+	if (!out)
+        fail = true;
+
+	// Handle failure.
+	if (fail)
+	{
+		for (int i=0; i<numentries; i++) 
+        {
+            if (entries[i])
+                OVR_FREE(entries[i]);
+        }
+		OVR_FREE(entries);
+		return 0;
+	}
+	
+	// Compose the output array.
+	*out='[';
+	ptr=out+1;
+    *ptr=0;
+	for (int i=0; i<numentries; i++)
+	{
+		OVR_strcpy(ptr, len - (ptr-out), entries[i]);
+        ptr+=OVR_strlen(entries[i]);
+		if (i!=numentries-1)
+        {
+            *ptr++=',';
+            if (fmt)
+                *ptr++=' ';
+            *ptr=0;
+        }
+		OVR_FREE(entries[i]);
+	}
+	OVR_FREE(entries);
+	*ptr++=']';
+    *ptr++=0;
+	return out;	
+}
+
+//-----------------------------------------------------------------------------
+// Build an object from the supplied text and returns the text position after
+// the parsed object
+const char* JSON::parseObject(const char* buff, const char** perror)
+{
+	if (*buff!='{')
+    {
+        return AssignError(perror, "Syntax Error: Missing opening brace");
+    }
+	
+	Type=JSON_Object;
+	buff=skip(buff+1);
+	if (*buff=='}')
+        return buff+1;	// empty array.
+	
+    JSON* child = new JSON();
+    Children.PushBack(child);
+
+	buff=skip(child->parseString(skip(buff), perror));
+	if (!buff) 
+        return 0;
+	child->Name = child->Value;
+    child->Value.Clear();
+	
+    if (*buff!=':')
+    {
+        return AssignError(perror, "Syntax Error: Missing colon");
+    }
+
+	buff=skip(child->parseValue(skip(buff+1), perror));	// skip any spacing, get the value.
+	if (!buff)
+        return 0;
+	
+	while (*buff==',')
+	{
+        child = new JSON();
+		if (!child)
+            return 0; // memory fail
+		
+        Children.PushBack(child);
+
+		buff=skip(child->parseString(skip(buff+1), perror));
+		if (!buff)
+            return 0;
+		
+        child->Name=child->Value;
+        child->Value.Clear();
+		
+        if (*buff!=':')
+        {
+            return AssignError(perror, "Syntax Error: Missing colon");
+        }	// fail!
+		
+        // Skip any spacing, get the value.
+        buff=skip(child->parseValue(skip(buff+1), perror));
+		if (!buff)
+            return 0;
+	}
+	
+	if (*buff=='}')
+        return buff+1;	// end of array 
+	
+    return AssignError(perror, "Syntax Error: Missing closing brace");
+}
+
+//-----------------------------------------------------------------------------
+// Render an object to text.  The returned string must be freed
+char* JSON::PrintObject(int depth, bool fmt)
+{
+	char** entries = 0, **names = 0;
+	char*  out = 0;
+    char*  ptr, *ret, *str;
+    SPInt  len = 7, i = 0, j;
+    bool   fail = false;
+	
+    // Count the number of entries.
+    int numentries = GetItemCount();
+    
+	// Explicitly handle empty object case
+	if (numentries == 0)
+	{
+		out=(char*)OVR_ALLOC(fmt?depth+3:3);
+		if (!out)
+            return 0;
+		ptr=out;
+        *ptr++='{';
+		
+        if (fmt)
+        {
+            *ptr++='\n';
+            for (i=0;i<depth-1;i++)
+                *ptr++='\t';
+        }
+		*ptr++='}';
+        *ptr++=0;
+		return out;
+	}
+	// Allocate space for the names and the objects
+	entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
+	if (!entries)
+        return 0;
+	names=(char**)OVR_ALLOC(numentries*sizeof(char*));
+	
+    if (!names)
+    {
+        OVR_FREE(entries);
+        return 0;
+    }
+	memset(entries,0,sizeof(char*)*numentries);
+	memset(names,0,sizeof(char*)*numentries);
+
+	// Collect all the results into our arrays:
+    depth++;
+    if (fmt)
+        len+=depth;
+
+    JSON* child = Children.GetFirst();
+    while (!Children.IsNull(child))
+	{
+		names[i]     = str = PrintString(child->Name);
+		entries[i++] = ret = child->PrintValue(depth, fmt);
+
+		if (str && ret)
+        {
+            len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?2+depth:0);
+        }
+        else
+        {
+            fail = true;
+            break;
+        }
+		
+        child = Children.GetNext(child);
+	}
+	
+	// Try to allocate the output string
+	if (!fail)
+        out=(char*)OVR_ALLOC(len);
+	if (!out)
+        fail=true;
+
+	// Handle failure
+	if (fail)
+	{
+		for (i=0;i<numentries;i++)
+        {
+            if (names[i])
+                OVR_FREE(names[i]);
+            
+            if (entries[i])
+                OVR_FREE(entries[i]);}
+		
+        OVR_FREE(names);
+        OVR_FREE(entries);
+		return 0;
+	}
+	
+	// Compose the output:
+	*out = '{';
+    ptr  = out+1;
+    if (fmt)
+        *ptr++='\n';
+    *ptr = 0;
+	
+    for (i=0; i<numentries; i++)
+	{
+		if (fmt)
+        {
+            for (j=0; j<depth; j++)
+                *ptr++ = '\t';
+        }
+		OVR_strcpy(ptr, len - (ptr-out), names[i]);
+        ptr   += OVR_strlen(names[i]);
+		*ptr++ =':';
+        
+        if (fmt)
+            *ptr++='\t';
+		
+        OVR_strcpy(ptr, len - (ptr-out), entries[i]);
+        ptr+=OVR_strlen(entries[i]);
+		
+        if (i!=numentries-1)
+            *ptr++ = ',';
+		
+        if (fmt)
+            *ptr++ = '\n';
+        *ptr = 0;
+		
+        OVR_FREE(names[i]);
+        OVR_FREE(entries[i]);
+	}
+	
+	OVR_FREE(names);
+    OVR_FREE(entries);
+	
+    if (fmt)
+    {
+        for (i=0;i<depth-1;i++)
+            *ptr++='\t';
+    }
+	*ptr++='}';
+    *ptr++=0;
+	
+    return out;	
+}
+
+
+
+// Returns the number of child items in the object
+// Counts the number of items in the object.
+unsigned JSON::GetItemCount() const
+{
+    unsigned count = 0;
+    for(const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext)
+        count++;
+    return count;
+}
+
+JSON* JSON::GetItemByIndex(unsigned index)
+{
+    unsigned i     = 0;
+    JSON*    child = 0;
+
+    if (!Children.IsEmpty())
+    {
+        child = Children.GetFirst();
+
+        while (i < index)
+        {   
+            if (Children.IsNull(child->pNext))
+            {
+                child = 0;
+                break;
+            }
+            child = child->pNext;
+            i++;
+        }
+    }
+  
+    return child;
+}
+
+// Returns the child item with the given name or NULL if not found
+JSON* JSON::GetItemByName(const char* name)
+{
+    JSON* child = 0;
+
+    if (!Children.IsEmpty())
+    {
+        child = Children.GetFirst();
+
+        while (OVR_strcmp(child->Name, name) != 0)
+        {   
+            if (Children.IsNull(child->pNext))
+            {
+                child = 0;
+                break;
+            }
+            child = child->pNext;
+        }
+    }
+
+    return child;
+}
+
+//-----------------------------------------------------------------------------
+// Adds a new item to the end of the child list
+void JSON::AddItem(const char *string, JSON *item)
+{
+    if (!item)
+        return;
+ 
+    item->Name = string;
+    Children.PushBack(item);
+}
+
+/*
+
+// Removes and frees the items at the given index
+void JSON::DeleteItem(unsigned int index)
+{
+    unsigned int num_items = 0;
+    JSON* child = Children.GetFirst();
+    while (!Children.IsNull(child) && num_items < index)
+    {   
+        num_items++;
+        child = Children.GetNext(child);
+    }
+
+    if (!Children.IsNull(child))
+    
+        child->RemoveNode();
+        child->Release();
+    }
+}
+
+// Replaces and frees the item at the give index with the new item
+void JSON::ReplaceItem(unsigned int index, JSON* new_item)
+{
+    unsigned int num_items = 0;
+    JSON* child = Children.GetFirst();
+    while (!Children.IsNull(child) && num_items < index)
+    {   
+        num_items++;
+        child = Children.GetNext(child);
+    }
+
+    if (!Children.IsNull(child))
+    {
+        child->ReplaceNodeWith(new_item);
+        child->Release();        
+    }
+}
+*/
+
+// Removes and frees the last child item
+void JSON::RemoveLast()
+{
+    JSON* child = Children.GetLast();
+    if (!Children.IsNull(child))
+    {
+        child->RemoveNode();
+        child->Release();
+    }
+}
+
+// Helper function to simplify creation of a typed object
+JSON* JSON::createHelper(JSONItemType itemType, double dval, const char* strVal)
+{
+    JSON *item = new JSON(itemType);
+    if (item)
+    {
+        item->dValue = dval;
+        if (strVal)
+            item->Value = strVal;
+    }
+    return item;
+}
+
+//-----------------------------------------------------------------------------
+// Get elements by name
+double JSON::GetNumberByName(const char *name, double defValue)
+{
+	JSON* item = GetItemByName(name);
+	if (!item || item->Type != JSON_Number) {
+		return defValue;
+	}
+	else {
+		return item->dValue;
+	}
+}
+
+int JSON::GetIntByName(const char *name, int defValue)
+{
+	JSON* item = GetItemByName(name);
+	if (!item || item->Type != JSON_Number) {
+		return defValue;
+	}
+	else {
+		return (int)item->dValue;
+	}
+}
+
+bool JSON::GetBoolByName(const char *name, bool defValue)
+{
+	JSON* item = GetItemByName(name);
+	if (!item || item->Type != JSON_Bool) {
+		return defValue;
+	}
+	else {
+		return (int)item->dValue != 0;
+	}
+}
+
+String JSON::GetStringByName(const char *name, const String &defValue)
+{
+	JSON* item = GetItemByName(name);
+	if (!item || item->Type != JSON_String) {
+		return defValue;
+	}
+	else {
+		return item->Value;
+	}
+}
+
+//-----------------------------------------------------------------------------
+// Adds an element to an array object type
+void JSON::AddArrayElement(JSON *item)
+{
+    if (!item)
+        return;
+
+    Children.PushBack(item);
+}
+
+// Inserts an element into a valid array position
+void JSON::InsertArrayElement(int index, JSON *item)
+{
+    if (!item)
+        return;
+
+    if (index == 0)
+    {
+        Children.PushFront(item);
+        return;
+    }
+
+    JSON* iter = Children.GetFirst();
+    int i=0;
+    while (iter && i<index)
+    {
+        iter = Children.GetNext(iter);
+        i++;
+    }
+
+    if (iter)
+        iter->InsertNodeBefore(item);
+    else
+        Children.PushBack(item);
+}
+
+// Returns the size of an array
+int JSON::GetArraySize()
+{
+    if (Type == JSON_Array)
+        return GetItemCount();
+    else
+        return 0;
+}
+
+// Returns the number value an the give array index
+double JSON::GetArrayNumber(int index)
+{
+    if (Type == JSON_Array)
+    {
+        JSON* number = GetItemByIndex(index);
+        return number ? number->dValue : 0.0;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+// Returns the string value at the given array index
+const char* JSON::GetArrayString(int index)
+{
+    if (Type == JSON_Array)
+    {
+        JSON* number = GetItemByIndex(index);
+        return number ? number->Value : 0;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+JSON* JSON::Copy()
+{
+    JSON* copy = new JSON(Type);
+    copy->Name = Name;
+    copy->Value = Value;
+    copy->dValue = dValue;
+
+    JSON* child = Children.GetFirst();
+    while (!Children.IsNull(child))
+    {
+        copy->Children.PushBack(child->Copy());
+        child = Children.GetNext(child);
+    }
+
+    return copy;
+}
+
+//-----------------------------------------------------------------------------
+// Loads and parses the given JSON file pathname and returns a JSON object tree.
+// The returned object must be Released after use.
+JSON* JSON::Load(const char* path, const char** perror)
+{
+    SysFile f;
+    if (!f.Open(path, File::Open_Read, File::Mode_Read))
+    {
+        AssignError(perror, "Failed to open file");
+        return NULL;
+    }
+
+    int    len   = f.GetLength();
+    UByte* buff  = (UByte*)OVR_ALLOC(len + 1);
+    int    bytes = f.Read(buff, len);
+    f.Close();
+
+    if (bytes == 0 || bytes != len)
+    {
+        OVR_FREE(buff);
+        return NULL;
+    }
+
+	// Ensure the result is null-terminated since Parse() expects null-terminated input.
+	buff[len] = '\0';
+
+    JSON* json = JSON::Parse((char*)buff, perror);
+    OVR_FREE(buff);
+    return json;
+}
+
+//-----------------------------------------------------------------------------
+// Serializes the JSON object and writes to the give file path
+bool JSON::Save(const char* path)
+{
+    SysFile f;
+    if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write))
+        return false;
+
+    char* text = PrintValue(0, true);
+    if (text)
+    {
+        SPInt len   = OVR_strlen(text);
+        OVR_ASSERT(len <= (SPInt)(int)len);
+
+        int   bytes = f.Write((UByte*)text, (int)len);
+        f.Close();
+        OVR_FREE(text);
+        return (bytes == len);
+    }
+    else
+    {
+        return false;
+    }
+}
+
+}
diff --git a/LibOVR/Src/OVR_JSON.h b/LibOVR/Src/OVR_JSON.h
new file mode 100644
index 0000000..a2a603c
--- /dev/null
+++ b/LibOVR/Src/OVR_JSON.h
@@ -0,0 +1,164 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_JSON.h
+Content     :   JSON format reader and writer
+Created     :   April 9, 2013
+Author      :   Brant Lewis
+Notes       :
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_JSON_H
+#define OVR_JSON_H
+
+#include "Kernel/OVR_RefCount.h"
+#include "Kernel/OVR_String.h"
+#include "Kernel/OVR_List.h"
+
+namespace OVR {  
+
+// JSONItemType describes the type of JSON item, specifying the type of
+// data that can be obtained from it.
+enum JSONItemType
+{
+    JSON_None      = 0,
+    JSON_Null      = 1,
+    JSON_Bool      = 2,
+    JSON_Number    = 3,
+    JSON_String    = 4,
+    JSON_Array     = 5,
+    JSON_Object    = 6
+};
+
+//-----------------------------------------------------------------------------
+// ***** JSON
+
+// JSON object represents a JSON node that can be either a root of the JSON tree
+// or a child item. Every node has a type that describes what is is.
+// New JSON trees are typically loaded JSON::Load or created with JSON::Parse.
+
+class JSON : public RefCountBase<JSON>, public ListNode<JSON>
+{
+protected:
+    List<JSON>      Children;
+
+public:
+    JSONItemType    Type;       // Type of this JSON node.
+    String          Name;       // Name part of the {Name, Value} pair in a parent object.
+    String          Value;
+    double          dValue;
+
+public:
+    ~JSON();
+
+    // *** Creation of NEW JSON objects
+
+    static JSON*    CreateObject()               { return new JSON(JSON_Object);}
+    static JSON*    CreateNull()                 { return new JSON(JSON_Null); }
+    static JSON*    CreateArray()                { return new JSON(JSON_Array); }
+    static JSON*    CreateBool(bool b)           { return createHelper(JSON_Bool, b ? 1.0 : 0.0); }
+    static JSON*    CreateNumber(double num)     { return createHelper(JSON_Number, num); }
+    static JSON*    CreateString(const char *s)  { return createHelper(JSON_String, 0.0, s); }
+
+    // Creates a new JSON object from parsing string.
+    // Returns null pointer and fills in *perror in case of parse error.
+    static JSON*    Parse(const char* buff, const char** perror = 0);
+
+	// This version works for buffers that are not null terminated strings.
+	static JSON*	ParseBuffer(const char *buff, int len, const char** perror = 0);
+
+    // Loads and parses a JSON object from a file.
+    // Returns 0 and assigns perror with error message on fail.
+    static JSON*    Load(const char* path, const char** perror = 0);
+
+    // Saves a JSON object to a file.
+    bool            Save(const char* path);
+
+    // *** Object Member Access
+
+    // These provide access to child items of the list.
+    bool            HasItems() const         { return Children.IsEmpty(); }
+    // Returns first/last child item, or null if child list is empty
+    JSON*           GetFirstItem()           { return (!Children.IsEmpty()) ? Children.GetFirst() : 0; }
+    JSON*           GetLastItem()            { return (!Children.IsEmpty()) ? Children.GetLast() : 0; }
+
+    // Counts the number of items in the object; these methods are inefficient.
+    unsigned        GetItemCount() const;
+    JSON*           GetItemByIndex(unsigned i);
+    JSON*           GetItemByName(const char* name);
+
+	// Accessors by name
+	double			GetNumberByName(const char *name, double defValue = 0.0);
+	int				GetIntByName(const char *name, int defValue = 0);
+	bool			GetBoolByName(const char *name, bool defValue = false);
+	String			GetStringByName(const char *name, const String &defValue = "");
+
+    // Returns next item in a list of children; 0 if no more items exist.
+    JSON*           GetNextItem(JSON* item)  { return Children.IsNull(item->pNext) ? 0 : item->pNext; }
+    JSON*           GetPrevItem(JSON* item)  { return Children.IsNull(item->pPrev) ? 0 : item->pPrev; }
+
+
+    // Child item access functions
+    void            AddItem(const char *string, JSON* item);
+    void            AddNullItem(const char* name)                    { AddItem(name, CreateNull()); }
+    void            AddBoolItem(const char* name, bool b)            { AddItem(name, CreateBool(b)); }
+    void            AddNumberItem(const char* name, double n)        { AddItem(name, CreateNumber(n)); }
+    void            AddStringItem(const char* name, const char* s)   { AddItem(name, CreateString(s)); }
+//    void            ReplaceItem(unsigned index, JSON* new_item);
+//    void            DeleteItem(unsigned index);
+    void            RemoveLast();
+
+    // *** Array Element Access
+
+    // Add new elements to the end of array.
+    void            AddArrayElement(JSON *item);
+    void            InsertArrayElement(int index, JSON* item);
+    void            AddArrayNumber(double n)        { AddArrayElement(CreateNumber(n)); }
+    void            AddArrayString(const char* s)   { AddArrayElement(CreateString(s)); }
+
+    // Accessed array elements; currently inefficient.
+    int             GetArraySize();
+    double          GetArrayNumber(int index);
+    const char*     GetArrayString(int index);
+
+    JSON*           Copy();  // Create a copy of this object
+
+protected:
+    JSON(JSONItemType itemType = JSON_Object);
+
+    static JSON*    createHelper(JSONItemType itemType, double dval, const char* strVal = 0);
+
+    // JSON Parsing helper functions.
+    const char*     parseValue(const char *buff, const char** perror);
+    const char*     parseNumber(const char *num);
+    const char*     parseArray(const char* value, const char** perror);
+    const char*     parseObject(const char* value, const char** perror);
+    const char*     parseString(const char* str, const char** perror);
+
+    char*           PrintValue(int depth, bool fmt);
+    char*           PrintObject(int depth, bool fmt);
+    char*           PrintArray(int depth, bool fmt);
+};
+
+
+}
+
+#endif
diff --git a/LibOVR/Src/OVR_LatencyTestImpl.cpp b/LibOVR/Src/OVR_LatencyTestImpl.cpp
new file mode 100644
index 0000000..015d9e4
--- /dev/null
+++ b/LibOVR/Src/OVR_LatencyTestImpl.cpp
@@ -0,0 +1,773 @@
+/************************************************************************************
+
+Filename    :   OVR_LatencyTestImpl.cpp
+Content     :   Oculus Latency Tester device implementation.
+Created     :   March 7, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_LatencyTestImpl.h"
+#include "Kernel/OVR_Alg.h"
+
+namespace OVR {
+
+using namespace Alg;
+
+//-------------------------------------------------------------------------------------
+// ***** Oculus Latency Tester specific packet data structures
+
+enum {    
+    LatencyTester_VendorId  = Oculus_VendorId,
+    LatencyTester_ProductId = 0x0101,
+};
+
+static void UnpackSamples(const UByte* buffer, UByte* r, UByte* g, UByte* b)
+{
+    *r = buffer[0];
+    *g = buffer[1];
+    *b = buffer[2];
+}
+
+// Messages we handle.
+enum LatencyTestMessageType
+{
+    LatencyTestMessage_None                 = 0,
+    LatencyTestMessage_Samples              = 1,
+    LatencyTestMessage_ColorDetected        = 2,
+    LatencyTestMessage_TestStarted          = 3,
+    LatencyTestMessage_Button               = 4,
+    LatencyTestMessage_Unknown              = 0x100,
+    LatencyTestMessage_SizeError            = 0x101,
+};
+
+struct LatencyTestSample
+{
+    UByte Value[3];
+};
+
+struct LatencyTestSamples
+{
+    UByte	SampleCount;
+    UInt16	Timestamp;
+
+    LatencyTestSample Samples[20];
+
+    LatencyTestMessageType Decode(const UByte* buffer, int size)
+    {
+        if (size < 64)
+        {
+            return LatencyTestMessage_SizeError;
+        }
+
+        SampleCount		= buffer[1];
+        Timestamp		= DecodeUInt16(buffer + 2);
+        
+        for (UByte i = 0; i < SampleCount; i++)
+        {
+            UnpackSamples(buffer + 4 + (3 * i),  &Samples[i].Value[0], &Samples[i].Value[1], &Samples[i].Value[2]);
+        }
+
+        return LatencyTestMessage_Samples;
+    }
+};
+
+struct LatencyTestSamplesMessage
+{
+    LatencyTestMessageType      Type;
+    LatencyTestSamples        Samples;
+};
+
+bool DecodeLatencyTestSamplesMessage(LatencyTestSamplesMessage* message, UByte* buffer, int size)
+{
+    memset(message, 0, sizeof(LatencyTestSamplesMessage));
+
+    if (size < 64)
+    {
+        message->Type = LatencyTestMessage_SizeError;
+        return false;
+    }
+
+    switch (buffer[0])
+    {
+    case LatencyTestMessage_Samples:
+        message->Type = message->Samples.Decode(buffer, size);
+        break;
+
+    default:
+        message->Type = LatencyTestMessage_Unknown;
+        break;
+    }
+
+    return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
+}
+
+struct LatencyTestColorDetected
+{
+    UInt16	CommandID;
+    UInt16	Timestamp;
+    UInt16  Elapsed;
+    UByte   TriggerValue[3];
+    UByte   TargetValue[3];
+
+    LatencyTestMessageType Decode(const UByte* buffer, int size)
+    {
+        if (size < 13)
+            return LatencyTestMessage_SizeError;
+
+        CommandID = DecodeUInt16(buffer + 1);
+        Timestamp = DecodeUInt16(buffer + 3);
+        Elapsed = DecodeUInt16(buffer + 5);
+        memcpy(TriggerValue, buffer + 7, 3);
+        memcpy(TargetValue, buffer + 10, 3);
+
+        return LatencyTestMessage_ColorDetected;
+    }
+};
+
+struct LatencyTestColorDetectedMessage
+{
+    LatencyTestMessageType    Type;
+    LatencyTestColorDetected  ColorDetected;
+};
+
+bool DecodeLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message, UByte* buffer, int size)
+{
+    memset(message, 0, sizeof(LatencyTestColorDetectedMessage));
+
+    if (size < 13)
+    {
+        message->Type = LatencyTestMessage_SizeError;
+        return false;
+    }
+
+    switch (buffer[0])
+    {
+    case LatencyTestMessage_ColorDetected:
+        message->Type = message->ColorDetected.Decode(buffer, size);
+        break;
+
+    default:
+        message->Type = LatencyTestMessage_Unknown;
+        break;
+    }
+
+    return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
+}
+
+struct LatencyTestStarted
+{
+    UInt16	CommandID;
+    UInt16	Timestamp;
+    UByte   TargetValue[3];
+
+    LatencyTestMessageType Decode(const UByte* buffer, int size)
+    {
+        if (size < 8)
+            return LatencyTestMessage_SizeError;
+
+        CommandID = DecodeUInt16(buffer + 1);
+        Timestamp = DecodeUInt16(buffer + 3);
+        memcpy(TargetValue, buffer + 5, 3);
+
+        return LatencyTestMessage_TestStarted;
+    }
+};
+
+struct LatencyTestStartedMessage
+{
+    LatencyTestMessageType  Type;
+    LatencyTestStarted  TestStarted;
+};
+
+bool DecodeLatencyTestStartedMessage(LatencyTestStartedMessage* message, UByte* buffer, int size)
+{
+    memset(message, 0, sizeof(LatencyTestStartedMessage));
+
+    if (size < 8)
+    {
+        message->Type = LatencyTestMessage_SizeError;
+        return false;
+    }
+
+    switch (buffer[0])
+    {
+    case LatencyTestMessage_TestStarted:
+        message->Type = message->TestStarted.Decode(buffer, size);
+        break;
+
+    default:
+        message->Type = LatencyTestMessage_Unknown;
+        break;
+    }
+
+    return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
+}
+
+struct LatencyTestButton
+{
+    UInt16	CommandID;
+    UInt16	Timestamp;
+
+    LatencyTestMessageType Decode(const UByte* buffer, int size)
+    {
+        if (size < 5)
+            return LatencyTestMessage_SizeError;
+
+        CommandID = DecodeUInt16(buffer + 1);
+        Timestamp = DecodeUInt16(buffer + 3);
+
+        return LatencyTestMessage_Button;
+    }
+};
+
+struct LatencyTestButtonMessage
+{
+    LatencyTestMessageType    Type;
+    LatencyTestButton         Button;
+};
+
+bool DecodeLatencyTestButtonMessage(LatencyTestButtonMessage* message, UByte* buffer, int size)
+{
+    memset(message, 0, sizeof(LatencyTestButtonMessage));
+
+    if (size < 5)
+    {
+        message->Type = LatencyTestMessage_SizeError;
+        return false;
+    }
+
+    switch (buffer[0])
+    {
+    case LatencyTestMessage_Button:
+        message->Type = message->Button.Decode(buffer, size);
+        break;
+
+    default:
+        message->Type = LatencyTestMessage_Unknown;
+        break;
+    }
+
+    return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
+}
+
+struct LatencyTestConfigurationImpl
+{
+    enum  { PacketSize = 5 };
+    UByte   Buffer[PacketSize];
+
+    OVR::LatencyTestConfiguration  Configuration;
+
+    LatencyTestConfigurationImpl(const OVR::LatencyTestConfiguration& configuration)
+        : Configuration(configuration)
+    {
+        Pack();
+    }
+
+    void Pack()
+    {
+        Buffer[0] = 5;
+		Buffer[1] = UByte(Configuration.SendSamples);
+		Buffer[2] = Configuration.Threshold.R;
+        Buffer[3] = Configuration.Threshold.G;
+        Buffer[4] = Configuration.Threshold.B;
+    }
+
+    void Unpack()
+    {
+		Configuration.SendSamples = Buffer[1] != 0 ? true : false;
+        Configuration.Threshold.R = Buffer[2];
+        Configuration.Threshold.G = Buffer[3];
+        Configuration.Threshold.B = Buffer[4];
+    }
+};
+
+struct LatencyTestCalibrateImpl
+{
+    enum  { PacketSize = 4 };
+    UByte   Buffer[PacketSize];
+
+    Color CalibrationColor;
+    
+    LatencyTestCalibrateImpl(const Color& calibrationColor)
+        : CalibrationColor(calibrationColor)
+    {
+        Pack();
+    }
+
+    void Pack()
+    {
+        Buffer[0] = 7;
+		Buffer[1] = CalibrationColor.R;
+		Buffer[2] = CalibrationColor.G;
+		Buffer[3] = CalibrationColor.B;
+    }
+
+    void Unpack()
+    {
+        CalibrationColor.R = Buffer[1];
+        CalibrationColor.G = Buffer[2];
+        CalibrationColor.B = Buffer[3];
+    }
+};
+
+struct LatencyTestStartTestImpl
+{
+    enum  { PacketSize = 6 };
+    UByte   Buffer[PacketSize];
+
+    Color TargetColor;
+
+    LatencyTestStartTestImpl(const Color& targetColor)
+        : TargetColor(targetColor)
+    {
+        Pack();
+    }
+
+    void Pack()
+    {
+        UInt16 commandID = 1;
+
+        Buffer[0] = 8;
+        EncodeUInt16(Buffer+1, commandID);
+		Buffer[3] = TargetColor.R;
+		Buffer[4] = TargetColor.G;
+		Buffer[5] = TargetColor.B;
+    }
+
+    void Unpack()
+    {
+//      UInt16 commandID = DecodeUInt16(Buffer+1);
+        TargetColor.R = Buffer[3];
+        TargetColor.G = Buffer[4];
+        TargetColor.B = Buffer[5];
+    }
+};
+
+struct LatencyTestDisplayImpl
+{
+    enum  { PacketSize = 6 };
+    UByte   Buffer[PacketSize];
+
+    OVR::LatencyTestDisplay  Display;
+
+    LatencyTestDisplayImpl(const OVR::LatencyTestDisplay& display)
+        : Display(display)
+    {
+        Pack();
+    }
+
+    void Pack()
+    {
+        Buffer[0] = 9;
+        Buffer[1] = Display.Mode;
+        EncodeUInt32(Buffer+2, Display.Value);
+    }
+
+    void Unpack()
+    {
+        Display.Mode = Buffer[1];
+        Display.Value = DecodeUInt32(Buffer+2);
+    }
+};
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTestDeviceFactory
+
+LatencyTestDeviceFactory &LatencyTestDeviceFactory::GetInstance()
+{
+	static LatencyTestDeviceFactory instance;
+	return instance;
+}
+
+void LatencyTestDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
+{
+
+    class LatencyTestEnumerator : public HIDEnumerateVisitor
+    {
+        // Assign not supported; suppress MSVC warning.
+        void operator = (const LatencyTestEnumerator&) { }
+
+        DeviceFactory*     pFactory;
+        EnumerateVisitor&  ExternalVisitor;   
+    public:
+        LatencyTestEnumerator(DeviceFactory* factory, EnumerateVisitor& externalVisitor)
+            : pFactory(factory), ExternalVisitor(externalVisitor) { }
+
+        virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId)
+        {
+            return pFactory->MatchVendorProduct(vendorId, productId);
+        }
+
+        virtual void Visit(HIDDevice& device, const HIDDeviceDesc& desc)
+        {
+            OVR_UNUSED(device);
+
+            LatencyTestDeviceCreateDesc createDesc(pFactory, desc);
+            ExternalVisitor.Visit(createDesc);
+        }
+    };
+
+    LatencyTestEnumerator latencyTestEnumerator(this, visitor);
+    GetManagerImpl()->GetHIDDeviceManager()->Enumerate(&latencyTestEnumerator);
+}
+
+bool LatencyTestDeviceFactory::MatchVendorProduct(UInt16 vendorId, UInt16 productId) const
+{
+    return ((vendorId == LatencyTester_VendorId) && (productId == LatencyTester_ProductId));                
+}
+
+bool LatencyTestDeviceFactory::DetectHIDDevice(DeviceManager* pdevMgr, 
+                                               const HIDDeviceDesc& desc)
+{
+    if (MatchVendorProduct(desc.VendorId, desc.ProductId))
+    {
+        LatencyTestDeviceCreateDesc createDesc(this, desc);
+        return pdevMgr->AddDevice_NeedsLock(createDesc).GetPtr() != NULL;
+    }
+    return false;
+}
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTestDeviceCreateDesc
+
+DeviceBase* LatencyTestDeviceCreateDesc::NewDeviceInstance()
+{
+    return new LatencyTestDeviceImpl(this);
+}
+
+bool LatencyTestDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
+{
+    if ((info->InfoClassType != Device_LatencyTester) &&
+        (info->InfoClassType != Device_None))
+        return false;
+
+    info->Type =            Device_LatencyTester;
+    info->ProductName =     HIDDesc.Product;
+    info->Manufacturer =    HIDDesc.Manufacturer;
+    info->Version =         HIDDesc.VersionNumber;
+
+    if (info->InfoClassType == Device_LatencyTester)
+    {
+        SensorInfo* sinfo = (SensorInfo*)info;
+        sinfo->VendorId  = HIDDesc.VendorId;
+        sinfo->ProductId = HIDDesc.ProductId;
+        sinfo->SerialNumber = HIDDesc.SerialNumber;
+    }
+    return true;
+}
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTestDevice
+
+LatencyTestDeviceImpl::LatencyTestDeviceImpl(LatencyTestDeviceCreateDesc* createDesc)
+    : OVR::HIDDeviceImpl<OVR::LatencyTestDevice>(createDesc, 0)
+{
+}
+
+LatencyTestDeviceImpl::~LatencyTestDeviceImpl()
+{
+    // Check that Shutdown() was called.
+    OVR_ASSERT(!pCreateDesc->pDevice);    
+}
+
+// Internal creation APIs.
+bool LatencyTestDeviceImpl::Initialize(DeviceBase* parent)
+{
+    if (HIDDeviceImpl<OVR::LatencyTestDevice>::Initialize(parent))
+    {
+        LogText("OVR::LatencyTestDevice initialized.\n");
+        return true;
+    }
+
+    return false;
+}
+
+void LatencyTestDeviceImpl::Shutdown()
+{   
+    HIDDeviceImpl<OVR::LatencyTestDevice>::Shutdown();
+
+    LogText("OVR::LatencyTestDevice - Closed '%s'\n", getHIDDesc()->Path.ToCStr());
+}
+
+void LatencyTestDeviceImpl::OnInputReport(UByte* pData, UInt32 length)
+{
+    
+    bool processed = false;
+    if (!processed)
+    {
+        LatencyTestSamplesMessage message; 
+        if (DecodeLatencyTestSamplesMessage(&message, pData, length))     
+        {
+            processed = true;
+            onLatencyTestSamplesMessage(&message);
+        }
+    }
+
+    if (!processed)
+    {
+        LatencyTestColorDetectedMessage message; 
+        if (DecodeLatencyTestColorDetectedMessage(&message, pData, length))     
+        {
+            processed = true;
+            onLatencyTestColorDetectedMessage(&message);
+        }
+    }
+
+    if (!processed)
+    {
+        LatencyTestStartedMessage message; 
+        if (DecodeLatencyTestStartedMessage(&message, pData, length))     
+        {
+            processed = true;
+            onLatencyTestStartedMessage(&message);
+        }
+    }
+
+    if (!processed)
+    {
+        LatencyTestButtonMessage message; 
+        if (DecodeLatencyTestButtonMessage(&message, pData, length))     
+        {
+            processed = true;
+            onLatencyTestButtonMessage(&message);
+        }
+    }
+}
+
+bool LatencyTestDeviceImpl::SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag)
+{  
+    bool                result = false;
+    ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue();
+
+    if (GetManagerImpl()->GetThreadId() != OVR::GetCurrentThreadId())
+    {
+        if (!waitFlag)
+        {
+            return queue->PushCall(this, &LatencyTestDeviceImpl::setConfiguration, configuration);
+        }
+
+        if (!queue->PushCallAndWaitResult(  this, 
+            &LatencyTestDeviceImpl::setConfiguration,
+            &result, 
+            configuration))
+        {
+            return false;
+        }
+    }
+    else
+        return setConfiguration(configuration);
+
+    return result;
+}
+
+bool LatencyTestDeviceImpl::setConfiguration(const OVR::LatencyTestConfiguration& configuration)
+{
+    LatencyTestConfigurationImpl ltc(configuration);
+    return GetInternalDevice()->SetFeatureReport(ltc.Buffer, LatencyTestConfigurationImpl::PacketSize);
+}
+
+bool LatencyTestDeviceImpl::GetConfiguration(OVR::LatencyTestConfiguration* configuration)
+{  
+    bool result = false;
+
+	ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue();
+    if (!pQueue->PushCallAndWaitResult(this, &LatencyTestDeviceImpl::getConfiguration, &result, configuration))
+        return false;
+
+    return result;
+}
+
+bool LatencyTestDeviceImpl::getConfiguration(OVR::LatencyTestConfiguration* configuration)
+{
+    LatencyTestConfigurationImpl ltc(*configuration);
+    if (GetInternalDevice()->GetFeatureReport(ltc.Buffer, LatencyTestConfigurationImpl::PacketSize))
+    {
+        ltc.Unpack();
+        *configuration = ltc.Configuration;
+        return true;
+    }
+
+    return false;
+}
+
+bool LatencyTestDeviceImpl::SetCalibrate(const Color& calibrationColor, bool waitFlag)
+{
+    bool                result = false;
+    ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue();
+
+    if (!waitFlag)
+    {
+        return queue->PushCall(this, &LatencyTestDeviceImpl::setCalibrate, calibrationColor);
+    }
+
+    if (!queue->PushCallAndWaitResult(  this, 
+                                        &LatencyTestDeviceImpl::setCalibrate,
+                                        &result, 
+                                        calibrationColor))
+    {
+        return false;
+    }
+
+    return result;
+}
+
+bool LatencyTestDeviceImpl::setCalibrate(const Color& calibrationColor)
+{
+    LatencyTestCalibrateImpl ltc(calibrationColor);
+    return GetInternalDevice()->SetFeatureReport(ltc.Buffer, LatencyTestCalibrateImpl::PacketSize);
+}
+
+bool LatencyTestDeviceImpl::SetStartTest(const Color& targetColor, bool waitFlag)
+{
+    bool                result = false;
+    ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue();
+
+    if (!waitFlag)
+    {
+        return queue->PushCall(this, &LatencyTestDeviceImpl::setStartTest, targetColor);
+    }
+
+    if (!queue->PushCallAndWaitResult(  this, 
+                                        &LatencyTestDeviceImpl::setStartTest,
+                                        &result, 
+                                        targetColor))
+    {
+        return false;
+    }
+
+    return result;
+}
+
+bool LatencyTestDeviceImpl::setStartTest(const Color& targetColor)
+{
+    LatencyTestStartTestImpl ltst(targetColor);
+    return GetInternalDevice()->SetFeatureReport(ltst.Buffer, LatencyTestStartTestImpl::PacketSize);
+}
+
+bool LatencyTestDeviceImpl::SetDisplay(const OVR::LatencyTestDisplay& display, bool waitFlag)
+{
+    bool                 result = false;
+    ThreadCommandQueue * queue = GetManagerImpl()->GetThreadQueue();
+
+    if (!waitFlag)
+    {
+        return queue->PushCall(this, &LatencyTestDeviceImpl::setDisplay, display);
+    }
+
+    if (!queue->PushCallAndWaitResult(  this, 
+                                        &LatencyTestDeviceImpl::setDisplay,
+                                        &result, 
+                                        display))
+    {
+        return false;
+    }
+
+    return result;
+}
+
+bool LatencyTestDeviceImpl::setDisplay(const OVR::LatencyTestDisplay& display)
+{
+    LatencyTestDisplayImpl ltd(display);
+    return GetInternalDevice()->SetFeatureReport(ltd.Buffer, LatencyTestDisplayImpl::PacketSize);
+}
+
+void LatencyTestDeviceImpl::onLatencyTestSamplesMessage(LatencyTestSamplesMessage* message)
+{
+
+    if (message->Type != LatencyTestMessage_Samples)
+        return;
+
+    LatencyTestSamples& s = message->Samples;
+
+    // Call OnMessage() within a lock to avoid conflicts with handlers.
+    Lock::Locker scopeLock(HandlerRef.GetLock());
+  
+    if (HandlerRef.HasHandlers())
+    {
+        MessageLatencyTestSamples samples(this);
+        for (UByte i = 0; i < s.SampleCount; i++)
+        {            
+            samples.Samples.PushBack(Color(s.Samples[i].Value[0], s.Samples[i].Value[1], s.Samples[i].Value[2]));
+        }
+
+        HandlerRef.Call(samples);
+    }
+}
+
+void LatencyTestDeviceImpl::onLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message)
+{
+    if (message->Type != LatencyTestMessage_ColorDetected)
+        return;
+
+    LatencyTestColorDetected& s = message->ColorDetected;
+
+    // Call OnMessage() within a lock to avoid conflicts with handlers.
+    Lock::Locker scopeLock(HandlerRef.GetLock());
+
+    if (HandlerRef.HasHandlers())
+    {
+        MessageLatencyTestColorDetected detected(this);
+        detected.Elapsed = s.Elapsed;
+        detected.DetectedValue = Color(s.TriggerValue[0], s.TriggerValue[1], s.TriggerValue[2]);
+        detected.TargetValue = Color(s.TargetValue[0], s.TargetValue[1], s.TargetValue[2]);
+
+        HandlerRef.Call(detected);
+    }
+}
+
+void LatencyTestDeviceImpl::onLatencyTestStartedMessage(LatencyTestStartedMessage* message)
+{
+    if (message->Type != LatencyTestMessage_TestStarted)
+        return;
+
+    LatencyTestStarted& ts = message->TestStarted;
+
+    // Call OnMessage() within a lock to avoid conflicts with handlers.
+    Lock::Locker scopeLock(HandlerRef.GetLock());
+
+    if (HandlerRef.HasHandlers())
+    {
+        MessageLatencyTestStarted started(this);
+        started.TargetValue = Color(ts.TargetValue[0], ts.TargetValue[1], ts.TargetValue[2]);
+
+        HandlerRef.Call(started);
+    }
+}
+
+void LatencyTestDeviceImpl::onLatencyTestButtonMessage(LatencyTestButtonMessage* message)
+{
+    if (message->Type != LatencyTestMessage_Button)
+        return;
+
+//  LatencyTestButton& s = message->Button;
+
+    // Call OnMessage() within a lock to avoid conflicts with handlers.
+    Lock::Locker scopeLock(HandlerRef.GetLock());
+
+    if (HandlerRef.HasHandlers())
+    {
+        MessageLatencyTestButton button(this);
+
+        HandlerRef.Call(button);
+    }
+}
+
+} // namespace OVR
diff --git a/LibOVR/Src/OVR_LatencyTestImpl.h b/LibOVR/Src/OVR_LatencyTestImpl.h
new file mode 100644
index 0000000..34faec2
--- /dev/null
+++ b/LibOVR/Src/OVR_LatencyTestImpl.h
@@ -0,0 +1,144 @@
+/************************************************************************************
+
+Filename    :   OVR_LatencyTestImpl.h
+Content     :   Latency Tester specific implementation.
+Created     :   March 7, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_LatencyTestImpl_h
+#define OVR_LatencyTestImpl_h
+
+#include "OVR_HIDDeviceImpl.h"
+
+namespace OVR {
+
+struct LatencyTestSamplesMessage;
+struct LatencyTestButtonMessage;
+struct LatencyTestStartedMessage;
+struct LatencyTestColorDetectedMessage;
+
+//-------------------------------------------------------------------------------------
+// LatencyTestDeviceFactory enumerates Oculus Latency Tester devices.
+class LatencyTestDeviceFactory : public DeviceFactory
+{
+public:
+	static LatencyTestDeviceFactory &GetInstance();
+
+	// Enumerates devices, creating and destroying relevant objects in manager.
+    virtual void EnumerateDevices(EnumerateVisitor& visitor);
+
+    virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const;
+    virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc);
+
+protected:
+    DeviceManager* getManager() const { return (DeviceManager*) pManager; }   
+};
+
+
+// Describes a single a Oculus Latency Tester device and supports creating its instance.
+class LatencyTestDeviceCreateDesc : public HIDDeviceCreateDesc
+{
+public:
+    LatencyTestDeviceCreateDesc(DeviceFactory* factory, const HIDDeviceDesc& hidDesc)
+        : HIDDeviceCreateDesc(factory, Device_LatencyTester, hidDesc) { }
+    
+    virtual DeviceCreateDesc* Clone() const
+    {
+        return new LatencyTestDeviceCreateDesc(*this);
+    }
+
+    virtual DeviceBase* NewDeviceInstance();
+
+    virtual MatchResult MatchDevice(const DeviceCreateDesc& other,
+                                    DeviceCreateDesc**) const
+    {
+        if ((other.Type == Device_LatencyTester) && (pFactory == other.pFactory))
+        {            
+            const LatencyTestDeviceCreateDesc& s2 = (const LatencyTestDeviceCreateDesc&) other;
+            if (MatchHIDDevice(s2.HIDDesc))
+                return Match_Found;
+        }
+        return Match_None;
+    }
+
+    virtual bool MatchHIDDevice(const HIDDeviceDesc& hidDesc) const
+    {
+        // should paths comparison be case insensitive?
+        return ((HIDDesc.Path.CompareNoCase(hidDesc.Path) == 0) &&
+                (HIDDesc.SerialNumber == hidDesc.SerialNumber));
+    }
+    virtual bool        GetDeviceInfo(DeviceInfo* info) const;
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** OVR::LatencyTestDeviceImpl
+
+// Oculus Latency Tester interface.
+
+class LatencyTestDeviceImpl : public HIDDeviceImpl<OVR::LatencyTestDevice>
+{
+public:
+     LatencyTestDeviceImpl(LatencyTestDeviceCreateDesc* createDesc);
+    ~LatencyTestDeviceImpl();
+
+    // DeviceCommon interface.
+    virtual bool Initialize(DeviceBase* parent);
+    virtual void Shutdown();
+
+    // DeviceManagerThread::Notifier interface.
+    virtual void OnInputReport(UByte* pData, UInt32 length);
+
+    // LatencyTesterDevice interface
+    virtual bool SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag = false);
+    virtual bool GetConfiguration(OVR::LatencyTestConfiguration* configuration);
+
+    virtual bool SetCalibrate(const Color& calibrationColor, bool waitFlag = false);
+
+    virtual bool SetStartTest(const Color& targetColor, bool waitFlag = false);
+    virtual bool SetDisplay(const LatencyTestDisplay& display, bool waitFlag = false);
+
+protected:
+    bool    openDevice(const char** errorFormatString);
+    void    closeDevice();
+    void    closeDeviceOnIOError();
+
+    bool    initializeRead();
+    bool    processReadResult();
+
+    bool    setConfiguration(const OVR::LatencyTestConfiguration& configuration);
+    bool    getConfiguration(OVR::LatencyTestConfiguration* configuration);
+    bool    setCalibrate(const Color& calibrationColor);
+    bool    setStartTest(const Color& targetColor);
+    bool    setDisplay(const OVR::LatencyTestDisplay& display);
+
+    // Called for decoded messages
+    void onLatencyTestSamplesMessage(LatencyTestSamplesMessage* message);
+    void onLatencyTestButtonMessage(LatencyTestButtonMessage* message);
+    void onLatencyTestStartedMessage(LatencyTestStartedMessage* message);
+    void onLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message);
+
+};
+
+} // namespace OVR
+
+#endif // OVR_LatencyTestImpl_h
diff --git a/LibOVR/Src/OVR_Linux_DeviceManager.cpp b/LibOVR/Src/OVR_Linux_DeviceManager.cpp
new file mode 100644
index 0000000..f1c4278
--- /dev/null
+++ b/LibOVR/Src/OVR_Linux_DeviceManager.cpp
@@ -0,0 +1,331 @@
+/************************************************************************************
+
+Filename    :   OVR_Linux_DeviceManager.h
+Content     :   Linux implementation of DeviceManager.
+Created     :   
+Authors     :   
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_Linux_DeviceManager.h"
+
+// Sensor & HMD Factories
+#include "OVR_LatencyTestImpl.h"
+#include "OVR_SensorImpl.h"
+#include "OVR_Linux_HIDDevice.h"
+#include "OVR_Linux_HMDDevice.h"
+
+#include "Kernel/OVR_Timer.h"
+#include "Kernel/OVR_Std.h"
+#include "Kernel/OVR_Log.h"
+
+namespace OVR { namespace Linux {
+
+
+//-------------------------------------------------------------------------------------
+// **** Linux::DeviceManager
+
+DeviceManager::DeviceManager()
+{
+}
+
+DeviceManager::~DeviceManager()
+{    
+}
+
+bool DeviceManager::Initialize(DeviceBase*)
+{
+    if (!DeviceManagerImpl::Initialize(0))
+        return false;
+
+    pThread = *new DeviceManagerThread();
+    if (!pThread || !pThread->Start())
+        return false;
+
+    // Wait for the thread to be fully up and running.
+    pThread->StartupEvent.Wait();
+
+    // Do this now that we know the thread's run loop.
+    HidDeviceManager = *HIDDeviceManager::CreateInternal(this);
+         
+    pCreateDesc->pDevice = this;
+    LogText("OVR::DeviceManager - initialized.\n");
+    return true;
+}
+
+void DeviceManager::Shutdown()
+{   
+    LogText("OVR::DeviceManager - shutting down.\n");
+
+    // Set Manager shutdown marker variable; this prevents
+    // any existing DeviceHandle objects from accessing device.
+    pCreateDesc->pLock->pManager = 0;
+
+    // Push for thread shutdown *WITH NO WAIT*.
+    // This will have the following effect:
+    //  - Exit command will get enqueued, which will be executed later on the thread itself.
+    //  - Beyond this point, this DeviceManager object may be deleted by our caller.
+    //  - Other commands, such as CreateDevice, may execute before ExitCommand, but they will
+    //    fail gracefully due to pLock->pManager == 0. Future commands can't be enqued
+    //    after pManager is null.
+    //  - Once ExitCommand executes, ThreadCommand::Run loop will exit and release the last
+    //    reference to the thread object.
+    pThread->PushExitCommand(false);
+    pThread.Clear();
+
+    DeviceManagerImpl::Shutdown();
+}
+
+ThreadCommandQueue* DeviceManager::GetThreadQueue()
+{
+    return pThread;
+}
+
+ThreadId DeviceManager::GetThreadId() const
+{
+    return pThread->GetThreadId();
+}
+
+bool DeviceManager::GetDeviceInfo(DeviceInfo* info) const
+{
+    if ((info->InfoClassType != Device_Manager) &&
+        (info->InfoClassType != Device_None))
+        return false;
+    
+    info->Type    = Device_Manager;
+    info->Version = 0;
+    info->ProductName = "DeviceManager";
+    info->Manufacturer = "Oculus VR, Inc.";        
+    return true;
+}
+
+DeviceEnumerator<> DeviceManager::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
+{
+    // TBD: Can this be avoided in the future, once proper device notification is in place?
+    pThread->PushCall((DeviceManagerImpl*)this,
+                      &DeviceManager::EnumerateAllFactoryDevices, true);
+
+    return DeviceManagerImpl::EnumerateDevicesEx(args);
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** DeviceManager Thread 
+
+DeviceManagerThread::DeviceManagerThread()
+    : Thread(ThreadStackSize)
+{
+    int result = pipe(CommandFd);
+    OVR_ASSERT(!result);
+    OVR_UNUSED(result);
+
+    AddSelectFd(NULL, CommandFd[0]);
+}
+
+DeviceManagerThread::~DeviceManagerThread()
+{
+    if (CommandFd[0])
+    {
+        RemoveSelectFd(NULL, CommandFd[0]);
+        close(CommandFd[0]);
+        close(CommandFd[1]);
+    }
+}
+
+bool DeviceManagerThread::AddSelectFd(Notifier* notify, int fd)
+{
+    struct pollfd pfd;
+    pfd.fd = fd;
+    pfd.events = POLLIN|POLLHUP|POLLERR;
+    pfd.revents = 0;
+
+    FdNotifiers.PushBack(notify);
+    PollFds.PushBack(pfd);
+
+    OVR_ASSERT(FdNotifiers.GetSize() == PollFds.GetSize());
+    return true;
+}
+
+bool DeviceManagerThread::RemoveSelectFd(Notifier* notify, int fd)
+{
+    // [0] is reserved for thread commands with notify of null, but we still
+    // can use this function to remove it.
+    for (UPInt i = 0; i < FdNotifiers.GetSize(); i++)
+    {
+        if ((FdNotifiers[i] == notify) && (PollFds[i].fd == fd))
+        {
+            FdNotifiers.RemoveAt(i);
+            PollFds.RemoveAt(i);
+            return true;
+        }
+    }
+    return false;
+}
+
+
+
+int DeviceManagerThread::Run()
+{
+    ThreadCommand::PopBuffer command;
+
+    SetThreadName("OVR::DeviceManagerThread");
+    LogText("OVR::DeviceManagerThread - running (ThreadId=%p).\n", GetThreadId());
+    
+    // Signal to the parent thread that initialization has finished.
+    StartupEvent.SetEvent();
+
+    while(!IsExiting())
+    {
+        // PopCommand will reset event on empty queue.
+        if (PopCommand(&command))
+        {
+            command.Execute();
+        }
+        else
+        {
+            bool commands = 0;
+            do
+            {
+                int waitMs = -1;
+
+                // If devices have time-dependent logic registered, get the longest wait
+                // allowed based on current ticks.
+                if (!TicksNotifiers.IsEmpty())
+                {
+                    double   timeSeconds = Timer::GetSeconds();
+                    unsigned waitAllowed;
+
+                    for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++)
+                    {
+                        waitAllowed = (unsigned)(TicksNotifiers[j]->OnTicks(timeSeconds) * Timer::MsPerSecond);
+                        if (waitAllowed < (unsigned)waitMs)
+                            waitMs = waitAllowed;
+                    }                
+                }
+
+                // wait until there is data available on one of the devices or the timeout expires
+                int n = poll(&PollFds[0], PollFds.GetSize(), waitMs);
+
+                if (n > 0)
+                {
+                    // Iterate backwards through the list so the ordering will not be
+                    // affected if the called object gets removed during the callback
+                    // Also, the HID data streams are located toward the back of the list
+                    // and servicing them first will allow a disconnect to be handled
+                    // and cleaned directly at the device first instead of the general HID monitor
+                    for (int i=PollFds.GetSize()-1; i>=0; i--)
+                    {
+                        if (PollFds[i].revents & POLLERR)
+                        {
+                            OVR_DEBUG_LOG(("poll: error on [%d]: %d", i, PollFds[i].fd));
+                        }
+                        else if (PollFds[i].revents & POLLIN)
+                        {
+                            if (FdNotifiers[i])
+                                FdNotifiers[i]->OnEvent(i, PollFds[i].fd);
+                            else if (i == 0) // command
+                            {
+                                char dummy[128];
+                                read(PollFds[i].fd, dummy, 128);
+                                commands = 1;
+                            }
+                        }
+
+                        if (PollFds[i].revents & POLLHUP)
+                            PollFds[i].events = 0;
+
+                        if (PollFds[i].revents != 0)
+                        {
+                            n--;
+                            if (n == 0)
+                                break;
+                        }
+                    }
+                }
+            } while (PollFds.GetSize() > 0 && !commands);
+        }
+    }
+
+    LogText("OVR::DeviceManagerThread - exiting (ThreadId=%p).\n", GetThreadId());
+    return 0;
+}
+
+bool DeviceManagerThread::AddTicksNotifier(Notifier* notify)
+{
+     TicksNotifiers.PushBack(notify);
+     return true;
+}
+
+bool DeviceManagerThread::RemoveTicksNotifier(Notifier* notify)
+{
+    for (UPInt i = 0; i < TicksNotifiers.GetSize(); i++)
+    {
+        if (TicksNotifiers[i] == notify)
+        {
+            TicksNotifiers.RemoveAt(i);
+            return true;
+        }
+    }
+    return false;
+}
+
+} // namespace Linux
+
+
+//-------------------------------------------------------------------------------------
+// ***** Creation
+
+
+// Creates a new DeviceManager and initializes OVR.
+DeviceManager* DeviceManager::Create()
+{
+    if (!System::IsInitialized())
+    {
+        // Use custom message, since Log is not yet installed.
+        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
+            LogMessage(Log_Debug, "DeviceManager::Create failed - OVR::System not initialized"); );
+        return 0;
+    }
+
+    Ptr<Linux::DeviceManager> manager = *new Linux::DeviceManager;
+
+    if (manager)
+    {
+        if (manager->Initialize(0))
+        {            
+            manager->AddFactory(&LatencyTestDeviceFactory::GetInstance());
+            manager->AddFactory(&SensorDeviceFactory::GetInstance());
+            manager->AddFactory(&Linux::HMDDeviceFactory::GetInstance());
+
+            manager->AddRef();
+        }
+        else
+        {
+            manager.Clear();
+        }
+
+    }    
+
+    return manager.GetPtr();
+}
+
+
+} // namespace OVR
+
diff --git a/LibOVR/Src/OVR_Linux_DeviceManager.h b/LibOVR/Src/OVR_Linux_DeviceManager.h
new file mode 100644
index 0000000..6532103
--- /dev/null
+++ b/LibOVR/Src/OVR_Linux_DeviceManager.h
@@ -0,0 +1,122 @@
+/************************************************************************************
+
+Filename    :   OVR_Linux_DeviceManager.h
+Content     :   Linux-specific DeviceManager header.
+Created     :   
+Authors     :   
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Linux_DeviceManager_h
+#define OVR_Linux_DeviceManager_h
+
+#include "OVR_DeviceImpl.h"
+
+#include <unistd.h>
+#include <sys/poll.h>
+
+
+namespace OVR { namespace Linux {
+
+class DeviceManagerThread;
+
+//-------------------------------------------------------------------------------------
+// ***** Linux DeviceManager
+
+class DeviceManager : public DeviceManagerImpl
+{
+public:
+    DeviceManager();
+    ~DeviceManager();
+
+    // Initialize/Shutdowncreate and shutdown manger thread.
+    virtual bool Initialize(DeviceBase* parent);
+    virtual void Shutdown();
+
+    virtual ThreadCommandQueue* GetThreadQueue();
+    virtual ThreadId GetThreadId() const;
+
+    virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args);    
+
+    virtual bool  GetDeviceInfo(DeviceInfo* info) const;
+
+    Ptr<DeviceManagerThread> pThread;
+};
+
+//-------------------------------------------------------------------------------------
+// ***** Device Manager Background Thread
+
+class DeviceManagerThread : public Thread, public ThreadCommandQueue
+{
+    friend class DeviceManager;
+    enum { ThreadStackSize = 64 * 1024 };
+public:
+    DeviceManagerThread();
+    ~DeviceManagerThread();
+
+    virtual int Run();
+
+    // ThreadCommandQueue notifications for CommandEvent handling.
+    virtual void OnPushNonEmpty_Locked() { write(CommandFd[1], this, 1); }
+    virtual void OnPopEmpty_Locked()     { }
+
+    class Notifier
+    {
+    public:
+        // Called when I/O is received
+        virtual void OnEvent(int i, int fd) = 0;
+
+        // Called when timing ticks are updated.
+        // Returns the largest number of seconds this function can
+        // wait till next call.
+        virtual double  OnTicks(double tickSeconds)
+        {
+            OVR_UNUSED1(tickSeconds);
+            return 1000.0;
+        }
+    };
+
+    // Add I/O notifier
+    bool AddSelectFd(Notifier* notify, int fd);
+    bool RemoveSelectFd(Notifier* notify, int fd);
+
+    // Add notifier that will be called at regular intervals.
+    bool AddTicksNotifier(Notifier* notify);
+    bool RemoveTicksNotifier(Notifier* notify);
+
+private:
+    
+    bool threadInitialized() { return CommandFd[0] != 0; }
+
+    // pipe used to signal commands
+    int CommandFd[2];
+
+    Array<struct pollfd>    PollFds;
+    Array<Notifier*>        FdNotifiers;
+
+    Event                   StartupEvent;
+
+    // Ticks notifiers - used for time-dependent events such as keep-alive.
+    Array<Notifier*>        TicksNotifiers;
+};
+
+}} // namespace Linux::OVR
+
+#endif // OVR_Linux_DeviceManager_h
diff --git a/LibOVR/Src/OVR_Linux_HIDDevice.cpp b/LibOVR/Src/OVR_Linux_HIDDevice.cpp
new file mode 100644
index 0000000..133e5c3
--- /dev/null
+++ b/LibOVR/Src/OVR_Linux_HIDDevice.cpp
@@ -0,0 +1,819 @@
+/************************************************************************************
+Filename    :   OVR_Linux_HIDDevice.cpp
+Content     :   Linux HID device implementation.
+Created     :   February 26, 2013
+Authors     :   Lee Cooper
+ 
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_Linux_HIDDevice.h"
+
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/hidraw.h>
+#include "OVR_HIDDeviceImpl.h"
+
+namespace OVR { namespace Linux {
+
+static const UInt32 MAX_QUEUED_INPUT_REPORTS = 5;
+    
+//-------------------------------------------------------------------------------------
+// **** Linux::DeviceManager
+//-----------------------------------------------------------------------------
+HIDDeviceManager::HIDDeviceManager(DeviceManager* manager) : DevManager(manager)
+{
+    UdevInstance = NULL;
+    HIDMonitor = NULL;
+    HIDMonHandle = -1;
+}
+
+//-----------------------------------------------------------------------------
+HIDDeviceManager::~HIDDeviceManager()
+{
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDeviceManager::initializeManager()
+{
+    if (HIDMonitor)
+    {
+        return true;
+    }
+
+    // Create a udev_monitor handle to watch for device changes (hot-plug detection)
+    HIDMonitor = udev_monitor_new_from_netlink(UdevInstance, "udev");
+    if (HIDMonitor == NULL)
+    {
+        return false;
+    }
+
+    udev_monitor_filter_add_match_subsystem_devtype(HIDMonitor, "hidraw", NULL);  // filter for hidraw only
+	
+    int err = udev_monitor_enable_receiving(HIDMonitor);
+    if (err)
+    {
+        udev_monitor_unref(HIDMonitor);
+        HIDMonitor = NULL;
+        return false;
+    }
+	
+    // Get the file descriptor (fd) for the monitor.  
+    HIDMonHandle = udev_monitor_get_fd(HIDMonitor);
+    if (HIDMonHandle < 0)
+    {
+        udev_monitor_unref(HIDMonitor);
+        HIDMonitor = NULL;
+        return false;
+    }
+
+    // This file handle will be polled along-side with the device hid handles for changes
+    // Add the handle to the polling list
+    if (!DevManager->pThread->AddSelectFd(this, HIDMonHandle))
+    {
+        close(HIDMonHandle);
+        HIDMonHandle = -1;
+
+        udev_monitor_unref(HIDMonitor);
+        HIDMonitor = NULL;
+        return false;
+    }
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDeviceManager::Initialize()
+{
+    // Get a udev library handle.  This handle must stay active during the
+    // duration the lifetime of device monitoring handles
+    UdevInstance = udev_new();
+    if (!UdevInstance)
+        return false;
+
+    return initializeManager();
+}
+
+//-----------------------------------------------------------------------------
+void HIDDeviceManager::Shutdown()
+{
+    OVR_ASSERT_LOG((UdevInstance), ("Should have called 'Initialize' before 'Shutdown'."));
+
+    if (HIDMonitor)
+    {
+        DevManager->pThread->RemoveSelectFd(this, HIDMonHandle);
+        close(HIDMonHandle);
+        HIDMonHandle = -1;
+
+        udev_monitor_unref(HIDMonitor);
+        HIDMonitor = NULL;
+    }
+
+    udev_unref(UdevInstance);  // release the library
+    
+    LogText("OVR::Linux::HIDDeviceManager - shutting down.\n");
+}
+
+//-------------------------------------------------------------------------------
+bool HIDDeviceManager::AddNotificationDevice(HIDDevice* device)
+{
+    NotificationDevices.PushBack(device);
+    return true;
+}
+
+//-------------------------------------------------------------------------------
+bool HIDDeviceManager::RemoveNotificationDevice(HIDDevice* device)
+{
+    for (UPInt i = 0; i < NotificationDevices.GetSize(); i++)
+    {
+        if (NotificationDevices[i] == device)
+        {
+            NotificationDevices.RemoveAt(i);
+            return true;
+        }
+    }
+    return false;
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDeviceManager::getIntProperty(udev_device* device,
+                                      const char* propertyName,
+                                      SInt32* pResult)
+{
+    const char* str = udev_device_get_sysattr_value(device, propertyName);
+	if (str)
+    {
+        *pResult = strtol(str, NULL, 16);
+        return true;
+    }
+    else
+    {
+        *pResult = 0;
+        return true;
+    }
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDeviceManager::initVendorProductVersion(udev_device* device, HIDDeviceDesc* pDevDesc)
+{
+    SInt32 result;
+    if (getIntProperty(device, "idVendor", &result))
+        pDevDesc->VendorId = result;
+    else
+        return false;
+
+    if (getIntProperty(device, "idProduct", &result))
+        pDevDesc->ProductId = result;
+    else
+        return false;
+
+    if (getIntProperty(device, "bcdDevice", &result))
+        pDevDesc->VersionNumber = result;
+    else
+        return false;
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDeviceManager::getStringProperty(udev_device* device,
+                                         const char* propertyName,
+                                         OVR::String* pResult)
+{
+    // Get the attribute in UTF8
+    const char* str = udev_device_get_sysattr_value(device, propertyName);
+	if (str)
+    {   // Copy the string into the return value
+		*pResult = String(str);
+        return true;
+	}
+    else
+    {
+        return false;
+    }
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor)
+{
+    
+    if (!initializeManager())
+    {
+        return false;
+    }
+
+	// Get a list of hid devices
+    udev_enumerate* devices = udev_enumerate_new(UdevInstance);
+    udev_enumerate_add_match_subsystem(devices, "hidraw");
+    udev_enumerate_scan_devices(devices);
+
+    udev_list_entry* entry = udev_enumerate_get_list_entry(devices);
+
+    // Search each device for the matching vid/pid
+    while (entry != NULL)
+    {
+        // Get the device file name
+        const char* sysfs_path = udev_list_entry_get_name(entry);
+        udev_device* hid;  // The device's HID udev node.
+        hid = udev_device_new_from_syspath(UdevInstance, sysfs_path);
+        const char* dev_path = udev_device_get_devnode(hid);
+
+        // Get the USB device
+        hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
+        if (hid)
+        {
+            HIDDeviceDesc devDesc;
+
+            // Check the VID/PID for a match
+            if (dev_path &&
+                initVendorProductVersion(hid, &devDesc) &&
+                enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId))
+            {
+                devDesc.Path = dev_path;
+                getFullDesc(hid, &devDesc);
+
+                // Look for the device to check if it is already opened.
+                Ptr<DeviceCreateDesc> existingDevice = DevManager->FindHIDDevice(devDesc, true);
+                // if device exists and it is opened then most likely the device open()
+                // will fail; therefore, we just set Enumerated to 'true' and continue.
+                if (existingDevice && existingDevice->pDevice)
+                {
+                    existingDevice->Enumerated = true;
+                }
+                else
+                {   // open the device temporarily for startup communication
+                    int device_handle = open(dev_path, O_RDWR);
+                    if (device_handle >= 0)
+                    {
+                        // Construct minimal device that the visitor callback can get feature reports from
+                        Linux::HIDDevice device(this, device_handle);
+                        enumVisitor->Visit(device, devDesc);
+
+                        close(device_handle);  // close the file handle
+                    }
+                }
+            }
+
+            udev_device_unref(hid);
+            entry = udev_list_entry_get_next(entry);
+        }
+    }
+
+	// Free the enumerator and udev objects
+    udev_enumerate_unref(devices);
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+OVR::HIDDevice* HIDDeviceManager::Open(const String& path)
+{
+    Ptr<Linux::HIDDevice> device = *new Linux::HIDDevice(this);
+
+    if (device->HIDInitialize(path))
+    {
+        device->AddRef();        
+        return device;
+    }
+
+    return NULL;
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDeviceManager::getFullDesc(udev_device* device, HIDDeviceDesc* desc)
+{
+        
+    if (!initVendorProductVersion(device, desc))
+    {
+        return false;
+    }
+        
+    if (!getStringProperty(device, "serial", &(desc->SerialNumber)))
+    {
+        return false;
+    }
+    
+    getStringProperty(device, "manufacturer", &(desc->Manufacturer));
+    getStringProperty(device, "product", &(desc->Product));
+        
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDeviceManager::GetDescriptorFromPath(const char* dev_path, HIDDeviceDesc* desc)
+{
+    if (!initializeManager())
+    {
+        return false;
+    }
+
+    // Search for the udev device from the given pathname so we can
+    // have a handle to query device properties
+
+    udev_enumerate* devices = udev_enumerate_new(UdevInstance);
+    udev_enumerate_add_match_subsystem(devices, "hidraw");
+    udev_enumerate_scan_devices(devices);
+
+    udev_list_entry* entry = udev_enumerate_get_list_entry(devices);
+
+    bool success = false;
+    // Search for the device with the matching path
+    while (entry != NULL)
+    {
+        // Get the device file name
+        const char* sysfs_path = udev_list_entry_get_name(entry);
+        udev_device* hid;  // The device's HID udev node.
+        hid = udev_device_new_from_syspath(UdevInstance, sysfs_path);
+        const char* path = udev_device_get_devnode(hid);
+
+        if (OVR_strcmp(dev_path, path) == 0)
+        {   // Found the device so lets collect the device descriptor
+
+            // Get the USB device
+            hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
+            if (hid)
+            {
+                desc->Path = dev_path;
+                success = getFullDesc(hid, desc);
+            }
+
+        }
+
+        udev_device_unref(hid);
+        entry = udev_list_entry_get_next(entry);
+    }
+
+    // Free the enumerator
+    udev_enumerate_unref(devices);
+
+    return success;
+}
+
+//-----------------------------------------------------------------------------
+void HIDDeviceManager::OnEvent(int i, int fd)
+{
+    OVR_UNUSED(i);
+    OVR_UNUSED(fd);
+
+    // There is a device status change
+    udev_device* hid = udev_monitor_receive_device(HIDMonitor);
+    if (hid)
+    {
+        const char* dev_path = udev_device_get_devnode(hid);
+        const char* action = udev_device_get_action(hid);
+
+        HIDDeviceDesc device_info;
+        device_info.Path = dev_path;
+
+        MessageType notify_type;
+        if (OVR_strcmp(action, "add") == 0)
+        {
+            notify_type = Message_DeviceAdded;
+
+            // Retrieve the device info.  This can only be done on a connected
+            // device and is invalid for a disconnected device
+
+            // Get the USB device
+            hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
+            if (!hid)
+            {
+                return;
+            }
+
+            getFullDesc(hid, &device_info);
+        }
+        else if (OVR_strcmp(action, "remove") == 0)
+        {
+            notify_type = Message_DeviceRemoved;
+        }
+        else
+        {
+            return;
+        }
+
+        bool error = false;
+        bool deviceFound = false;
+        for (UPInt i = 0; i < NotificationDevices.GetSize(); i++)
+        {
+            if (NotificationDevices[i] &&
+                NotificationDevices[i]->OnDeviceNotification(notify_type, &device_info, &error))
+            {
+                // The notification was for an existing device
+                deviceFound = true;
+                break;
+            }
+        }
+
+        if (notify_type == Message_DeviceAdded && !deviceFound)
+        {
+            DevManager->DetectHIDDevice(device_info);
+        }
+
+        udev_device_unref(hid);
+    }
+}
+
+//=============================================================================
+//                           Linux::HIDDevice
+//=============================================================================
+HIDDevice::HIDDevice(HIDDeviceManager* manager)
+ :  InMinimalMode(false), HIDManager(manager)
+{
+    DeviceHandle = -1;
+}
+    
+//-----------------------------------------------------------------------------
+// This is a minimal constructor used during enumeration for us to pass
+// a HIDDevice to the visit function (so that it can query feature reports).
+HIDDevice::HIDDevice(HIDDeviceManager* manager, int device_handle)
+:   InMinimalMode(true), HIDManager(manager), DeviceHandle(device_handle)
+{
+}
+
+//-----------------------------------------------------------------------------
+HIDDevice::~HIDDevice()
+{
+    if (!InMinimalMode)
+    {
+        HIDShutdown();
+    }
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDevice::HIDInitialize(const String& path)
+{
+    const char* hid_path = path.ToCStr();
+    if (!openDevice(hid_path))
+    {
+        LogText("OVR::Linux::HIDDevice - Failed to open HIDDevice: %s", hid_path);
+        return false;
+    }
+    
+    HIDManager->DevManager->pThread->AddTicksNotifier(this);
+    HIDManager->AddNotificationDevice(this);
+
+    LogText("OVR::Linux::HIDDevice - Opened '%s'\n"
+            "                    Manufacturer:'%s'  Product:'%s'  Serial#:'%s'\n",
+            DevDesc.Path.ToCStr(),
+            DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(),
+            DevDesc.SerialNumber.ToCStr());
+    
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDevice::initInfo()
+{
+    // Device must have been successfully opened.
+    OVR_ASSERT(DeviceHandle >= 0);
+
+    int desc_size = 0;
+    hidraw_report_descriptor rpt_desc;
+    memset(&rpt_desc, 0, sizeof(rpt_desc));
+
+    // get report descriptor size
+    int r = ioctl(DeviceHandle, HIDIOCGRDESCSIZE, &desc_size);
+    if (r < 0)
+    {
+        OVR_ASSERT_LOG(false, ("Failed to get report descriptor size."));
+        return false;
+    }
+
+    // Get the report descriptor
+    rpt_desc.size = desc_size;
+    r = ioctl(DeviceHandle, HIDIOCGRDESC, &rpt_desc);
+    if (r < 0)
+    {
+        OVR_ASSERT_LOG(false, ("Failed to get report descriptor."));
+        return false;
+    }
+    
+    /*
+    // Get report lengths.
+    SInt32 bufferLength;
+    bool getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxInputReportSizeKey), &bufferLength);
+    OVR_ASSERT(getResult);
+    InputReportBufferLength = (UInt16) bufferLength;
+
+    getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxOutputReportSizeKey), &bufferLength);
+    OVR_ASSERT(getResult);
+    OutputReportBufferLength = (UInt16) bufferLength;
+
+    getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxFeatureReportSizeKey), &bufferLength);
+    OVR_ASSERT(getResult);
+    FeatureReportBufferLength = (UInt16) bufferLength;
+    
+    
+    if (ReadBufferSize < InputReportBufferLength)
+    {
+        OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
+        return false;
+    }
+    
+    // Get device desc.
+    if (!HIDManager->getFullDesc(Device, &DevDesc))
+    {
+        OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device."));
+        return false;
+    }
+    
+    return true;
+    */
+
+    // Get report lengths.
+// TODO: hard-coded for now.  Need to interpret these values from the report descriptor
+    InputReportBufferLength = 62;
+    OutputReportBufferLength = 0;
+    FeatureReportBufferLength = 69;
+    
+    if (ReadBufferSize < InputReportBufferLength)
+    {
+        OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
+        return false;
+    }
+      
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDevice::openDevice(const char* device_path)
+{
+    // First fill out the device descriptor
+    if (!HIDManager->GetDescriptorFromPath(device_path, &DevDesc))
+    {
+        return false;
+    }
+
+    // Now open the device
+    DeviceHandle = open(device_path, O_RDWR);
+    if (DeviceHandle < 0)
+    {
+        OVR_DEBUG_LOG(("Failed 'CreateHIDFile' while opening device, error = 0x%X.", errno));
+        DeviceHandle = -1;
+        return false;
+    }
+
+    // fill out some values from the feature report descriptor
+    if (!initInfo())
+    {
+        OVR_ASSERT_LOG(false, ("Failed to get HIDDevice info."));
+
+        close(DeviceHandle);
+        DeviceHandle = -1;
+        return false;
+    }
+
+    // Add the device to the polling list
+    if (!HIDManager->DevManager->pThread->AddSelectFd(this, DeviceHandle))
+    {
+        OVR_ASSERT_LOG(false, ("Failed to initialize polling for HIDDevice."));
+
+        close(DeviceHandle);
+        DeviceHandle = -1;
+        return false;
+    }
+    
+    return true;
+}
+    
+//-----------------------------------------------------------------------------
+void HIDDevice::HIDShutdown()
+{
+
+    HIDManager->DevManager->pThread->RemoveTicksNotifier(this);
+    HIDManager->RemoveNotificationDevice(this);
+    
+    if (DeviceHandle >= 0) // Device may already have been closed if unplugged.
+    {
+        closeDevice(false);
+    }
+    
+    LogText("OVR::Linux::HIDDevice - HIDShutdown '%s'\n", DevDesc.Path.ToCStr());
+}
+
+//-----------------------------------------------------------------------------
+void HIDDevice::closeDevice(bool wasUnplugged)
+{
+    OVR_UNUSED(wasUnplugged);
+    OVR_ASSERT(DeviceHandle >= 0);
+    
+
+    HIDManager->DevManager->pThread->RemoveSelectFd(this, DeviceHandle);
+
+    close(DeviceHandle);  // close the file handle
+    DeviceHandle = -1;
+        
+    LogText("OVR::Linux::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr());
+}
+
+//-----------------------------------------------------------------------------
+void HIDDevice::closeDeviceOnIOError()
+{
+    LogText("OVR::Linux::HIDDevice - Lost connection to '%s'\n", DevDesc.Path.ToCStr());
+    closeDevice(false);
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length)
+{
+    
+    if (DeviceHandle < 0)
+        return false;
+    
+    UByte reportID = data[0];
+
+    if (reportID == 0)
+    {
+        // Not using reports so remove from data packet.
+        data++;
+        length--;
+    }
+
+    int r = ioctl(DeviceHandle, HIDIOCSFEATURE(length), data);
+	return (r >= 0);
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length)
+{
+    if (DeviceHandle < 0)
+        return false;
+
+	int r = ioctl(DeviceHandle, HIDIOCGFEATURE(length), data);
+    return (r >= 0);
+}
+
+//-----------------------------------------------------------------------------
+double HIDDevice::OnTicks(double tickSeconds)
+{
+    if (Handler)
+    {
+        return Handler->OnTicks(tickSeconds);
+    }
+    
+    return DeviceManagerThread::Notifier::OnTicks(tickSeconds);
+}
+
+//-----------------------------------------------------------------------------
+void HIDDevice::OnEvent(int i, int fd)
+{
+    OVR_UNUSED(i);
+    // We have data to read from the device
+    int bytes = read(fd, ReadBuffer, ReadBufferSize);
+    if (bytes >= 0)
+    {
+// TODO: I need to handle partial messages and package reconstruction
+        if (Handler)
+        {
+            Handler->OnInputReport(ReadBuffer, bytes);
+        }
+    }
+    else
+    {   // Close the device on read error.
+        closeDeviceOnIOError();
+    }
+}
+
+//-----------------------------------------------------------------------------
+bool HIDDevice::OnDeviceNotification(MessageType messageType,
+                                     HIDDeviceDesc* device_info,
+                                     bool* error)
+{
+    const char* device_path = device_info->Path.ToCStr();
+
+    if (messageType == Message_DeviceAdded && DeviceHandle < 0)
+    {
+        // Is this the correct device?
+        if (!(device_info->VendorId == DevDesc.VendorId
+            && device_info->ProductId == DevDesc.ProductId
+            && device_info->SerialNumber == DevDesc.SerialNumber))
+        {
+            return false;
+        }
+
+        // A closed device has been re-added. Try to reopen.
+        if (!openDevice(device_path))
+        {
+            LogError("OVR::Linux::HIDDevice - Failed to reopen a device '%s' that was re-added.\n", 
+                     device_path);
+            *error = true;
+            return true;
+        }
+
+        LogText("OVR::Linux::HIDDevice - Reopened device '%s'\n", device_path);
+
+        if (Handler)
+        {
+            Handler->OnDeviceMessage(HIDHandler::HIDDeviceMessage_DeviceAdded);
+        }
+    }
+    else if (messageType == Message_DeviceRemoved)
+    {
+        // Is this the correct device?
+        // For disconnected device, the device description will be invalid so
+        // checking the path is the only way to match them
+        if (DevDesc.Path.CompareNoCase(device_path) != 0)
+        {
+            return false;
+        }
+
+        if (DeviceHandle >= 0)
+        {
+            closeDevice(true);
+        }
+
+        if (Handler)
+        {
+            Handler->OnDeviceMessage(HIDHandler::HIDDeviceMessage_DeviceRemoved);
+        }
+    }
+    else
+    {
+        OVR_ASSERT(0);
+    }
+
+    *error = false;
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+HIDDeviceManager* HIDDeviceManager::CreateInternal(Linux::DeviceManager* devManager)
+{
+        
+    if (!System::IsInitialized())
+    {
+        // Use custom message, since Log is not yet installed.
+        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
+                            LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
+        return 0;
+    }
+
+    Ptr<Linux::HIDDeviceManager> manager = *new Linux::HIDDeviceManager(devManager);
+
+    if (manager)
+    {
+        if (manager->Initialize())
+        {
+            manager->AddRef();
+        }
+        else
+        {
+            manager.Clear();
+        }
+    }
+
+    return manager.GetPtr();
+}
+    
+} // namespace Linux
+
+//-------------------------------------------------------------------------------------
+// ***** Creation
+
+// Creates a new HIDDeviceManager and initializes OVR.
+HIDDeviceManager* HIDDeviceManager::Create(Ptr<OVR::DeviceManager>& deviceManager)
+{
+    
+    if (!System::IsInitialized())
+    {
+        // Use custom message, since Log is not yet installed.
+        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
+            LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
+        return 0;
+    }
+
+    Ptr<Linux::DeviceManager> deviceManagerLinux = *new Linux::DeviceManager;
+
+    if (!deviceManagerLinux)
+    {
+		return NULL;
+	}
+
+    if (!deviceManagerLinux->Initialize(NULL))
+    {         
+		return NULL;
+    }
+
+	deviceManager = deviceManagerLinux;
+
+	return deviceManagerLinux->GetHIDDeviceManager();
+}
+
+} // namespace OVR
diff --git a/LibOVR/Src/OVR_Linux_HIDDevice.h b/LibOVR/Src/OVR_Linux_HIDDevice.h
new file mode 100644
index 0000000..52f2d69
--- /dev/null
+++ b/LibOVR/Src/OVR_Linux_HIDDevice.h
@@ -0,0 +1,135 @@
+/************************************************************************************
+Filename    :   OVR_Linux_HIDDevice.h
+Content     :   Linux HID device implementation.
+Created     :   June 13, 2013
+Authors     :   Brant Lewis
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_LINUX_HIDDevice_h
+#define OVR_LINUX_HIDDevice_h
+
+#include "OVR_HIDDevice.h"
+#include "OVR_Linux_DeviceManager.h"
+#include <libudev.h>
+
+namespace OVR { namespace Linux {
+
+class HIDDeviceManager;
+
+//-------------------------------------------------------------------------------------
+// ***** Linux HIDDevice
+
+class HIDDevice : public OVR::HIDDevice, public DeviceManagerThread::Notifier
+{
+private:
+    friend class HIDDeviceManager;
+
+public:
+    HIDDevice(HIDDeviceManager* manager);
+
+    // This is a minimal constructor used during enumeration for us to pass
+    // a HIDDevice to the visit function (so that it can query feature reports).
+    HIDDevice(HIDDeviceManager* manager, int device_handle);
+    
+    virtual ~HIDDevice();
+
+    bool HIDInitialize(const String& path);
+    void HIDShutdown();
+    
+    virtual bool SetFeatureReport(UByte* data, UInt32 length);
+	virtual bool GetFeatureReport(UByte* data, UInt32 length);
+
+    // DeviceManagerThread::Notifier
+    void OnEvent(int i, int fd);
+    double OnTicks(double tickSeconds);
+
+    bool OnDeviceNotification(MessageType messageType,
+                              HIDDeviceDesc* device_info,
+                              bool* error);
+
+private:
+    bool initInfo();
+    bool openDevice(const char* dev_path);
+    void closeDevice(bool wasUnplugged);
+    void closeDeviceOnIOError();
+    bool setupDevicePluggedInNotification();
+
+    bool                    InMinimalMode;
+    HIDDeviceManager*       HIDManager;
+    int                     DeviceHandle;     // file handle to the device
+    HIDDeviceDesc           DevDesc;
+    
+    enum { ReadBufferSize = 96 };
+    UByte                   ReadBuffer[ReadBufferSize];
+
+    UInt16                  InputReportBufferLength;
+    UInt16                  OutputReportBufferLength;
+    UInt16                  FeatureReportBufferLength;
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** Linux HIDDeviceManager
+
+class HIDDeviceManager : public OVR::HIDDeviceManager, public DeviceManagerThread::Notifier
+{
+	friend class HIDDevice;
+
+public:
+    HIDDeviceManager(Linux::DeviceManager* Manager);
+    virtual ~HIDDeviceManager();
+
+    virtual bool Initialize();
+    virtual void Shutdown();
+
+    virtual bool Enumerate(HIDEnumerateVisitor* enumVisitor);
+    virtual OVR::HIDDevice* Open(const String& path);
+
+    static HIDDeviceManager* CreateInternal(DeviceManager* manager);
+
+    void OnEvent(int i, int fd);
+    
+private:
+    bool initializeManager();
+    bool initVendorProductVersion(udev_device* device, HIDDeviceDesc* pDevDesc);
+    bool getPath(udev_device* device, String* pPath);
+    bool getIntProperty(udev_device* device, const char* key, int32_t* pResult);
+    bool getStringProperty(udev_device* device,
+                           const char* propertyName,
+                           OVR::String* pResult);
+    bool getFullDesc(udev_device* device, HIDDeviceDesc* desc);
+    bool GetDescriptorFromPath(const char* dev_path, HIDDeviceDesc* desc);
+    
+    bool AddNotificationDevice(HIDDevice* device);
+    bool RemoveNotificationDevice(HIDDevice* device);
+    
+    DeviceManager*           DevManager;
+
+    udev*                    UdevInstance;     // a handle to the udev library instance
+    udev_monitor*            HIDMonitor;
+    int                      HIDMonHandle;     // the udev_monitor file handle
+
+    Array<HIDDevice*>        NotificationDevices;
+};
+
+}} // namespace OVR::Linux
+
+#endif // OVR_Linux_HIDDevice_h
diff --git a/LibOVR/Src/OVR_Linux_HMDDevice.cpp b/LibOVR/Src/OVR_Linux_HMDDevice.cpp
new file mode 100644
index 0000000..98143d3
--- /dev/null
+++ b/LibOVR/Src/OVR_Linux_HMDDevice.cpp
@@ -0,0 +1,291 @@
+/************************************************************************************
+
+Filename    :   OVR_Linux_HMDDevice.h
+Content     :   Linux HMDDevice implementation
+Created     :   June 17, 2013
+Authors     :   Brant Lewis
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_Linux_HMDDevice.h"
+
+#include "OVR_Linux_DeviceManager.h"
+
+#include "OVR_Profile.h"
+
+#include "../../3rdParty/EDID/edid.h"
+
+namespace OVR { namespace Linux {
+
+//-------------------------------------------------------------------------------------
+
+HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory, const String& displayDeviceName, long dispId)
+        : DeviceCreateDesc(factory, Device_HMD),
+          DisplayDeviceName(displayDeviceName),
+          Contents(0),
+          DisplayId(dispId)
+{
+    DeviceId = DisplayDeviceName;
+
+    Desktop.X = 0;
+    Desktop.Y = 0;
+    ResolutionInPixels = Sizei(0);
+    ScreenSizeInMeters = Sizef(0.0f);
+    VCenterFromTopInMeters = 0.0f;
+    LensSeparationInMeters = 0.0f;
+}
+
+HMDDeviceCreateDesc::HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other)
+        : DeviceCreateDesc(other.pFactory, Device_HMD),
+          DeviceId(other.DeviceId), DisplayDeviceName(other.DisplayDeviceName),
+          Contents(other.Contents),
+          DisplayId(other.DisplayId)
+{
+    Desktop.X              = other.Desktop.X;
+    Desktop.Y              = other.Desktop.Y;
+    ResolutionInPixels     = other.ResolutionInPixels;
+    ScreenSizeInMeters     = other.ScreenSizeInMeters;
+    VCenterFromTopInMeters = other.VCenterFromTopInMeters;
+    LensSeparationInMeters = other.LensSeparationInMeters;
+}
+
+HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCreateDesc& other,
+                                                                  DeviceCreateDesc** pcandidate) const
+{
+    if ((other.Type != Device_HMD) || (other.pFactory != pFactory))
+        return Match_None;
+
+    // There are several reasons we can come in here:
+    //   a) Matching this HMD Monitor created desc to OTHER HMD Monitor desc
+    //          - Require exact device DeviceId/DeviceName match
+    //   b) Matching SensorDisplayInfo created desc to OTHER HMD Monitor desc
+    //          - This DeviceId is empty; becomes candidate
+    //   c) Matching this HMD Monitor created desc to SensorDisplayInfo desc
+    //          - This other.DeviceId is empty; becomes candidate
+
+    const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
+
+    if ((DeviceId == s2.DeviceId) &&
+        (DisplayId == s2.DisplayId))
+    {
+        // Non-null DeviceId may match while size is different if screen size was overwritten
+        // by SensorDisplayInfo in prior iteration.
+        if (!DeviceId.IsEmpty() ||
+            (ScreenSizeInMeters == s2.ScreenSizeInMeters) )
+        {            
+            *pcandidate = 0;
+            return Match_Found;
+        }
+    }
+
+
+    // DisplayInfo takes precedence, although we try to match it first.
+    if ((ResolutionInPixels == s2.ResolutionInPixels) &&        
+        (ScreenSizeInMeters == s2.ScreenSizeInMeters))
+    {
+        if (DeviceId.IsEmpty() && !s2.DeviceId.IsEmpty())
+        {
+            *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
+            return Match_Candidate;
+        }
+
+        *pcandidate = 0;
+        return Match_Found;
+    }
+    
+    // SensorDisplayInfo may override resolution settings, so store as candidate.
+    if (s2.DeviceId.IsEmpty())
+    {        
+        *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
+        return Match_Candidate;
+    }
+    // OTHER HMD Monitor desc may initialize DeviceName/Id
+    else if (DeviceId.IsEmpty())
+    {
+        *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
+        return Match_Candidate;
+    }
+    
+    return Match_None;
+}
+
+
+bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, 
+                                                 bool* newDeviceFlag)
+{
+    // This candidate was the the "best fit" to apply sensor DisplayInfo to.
+    OVR_ASSERT(other.Type == Device_HMD);
+    
+    const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
+
+    // Force screen size on resolution from SensorDisplayInfo.
+    // We do this because USB detection is more reliable as compared to HDMI EDID,
+    // which may be corrupted by splitter reporting wrong monitor 
+    if (s2.DeviceId.IsEmpty())
+    {
+        ScreenSizeInMeters = s2.ScreenSizeInMeters;        
+        Contents |= Contents_Screen;
+
+        if (s2.Contents & HMDDeviceCreateDesc::Contents_Distortion)
+        {
+            memcpy(DistortionK, s2.DistortionK, sizeof(float)*4);
+            // TODO: DistortionEqn
+            Contents |= Contents_Distortion;
+        }
+        DeviceId          = s2.DeviceId;
+        DisplayId         = s2.DisplayId;
+        DisplayDeviceName = s2.DisplayDeviceName;
+        Desktop.X         = s2.Desktop.X;
+        Desktop.Y         = s2.Desktop.Y;
+        if (newDeviceFlag) *newDeviceFlag = true;
+    }
+    else if (DeviceId.IsEmpty())
+    {
+        // This branch is executed when 'fake' HMD descriptor is being replaced by
+        // the real one.
+        DeviceId          = s2.DeviceId;
+        DisplayId         = s2.DisplayId;
+        DisplayDeviceName = s2.DisplayDeviceName;
+        Desktop.X         = s2.Desktop.X;
+        Desktop.Y         = s2.Desktop.Y;
+
+		// ScreenSize and Resolution are NOT assigned here, since they may have
+		// come from a sensor DisplayInfo (which has precedence over HDMI).
+
+        if (newDeviceFlag) *newDeviceFlag = true;
+    }
+    else
+    {
+        if (newDeviceFlag) *newDeviceFlag = false;
+    }
+
+    return true;
+}
+
+bool HMDDeviceCreateDesc::MatchDevice(const String& path)
+{
+    return DeviceId.CompareNoCase(path) == 0;
+}
+
+//-------------------------------------------------------------------------------------
+// ***** HMDDeviceFactory
+
+HMDDeviceFactory &HMDDeviceFactory::GetInstance()
+{
+	static HMDDeviceFactory instance;
+	return instance;
+}
+
+void HMDDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
+{
+    // For now we'll assume the Rift DK1 is attached in extended monitor mode. Ultimately we need to
+    // use XFree86 to enumerate X11 screens in case the Rift is attached as a separate screen.
+
+    bool foundHMD = false;
+    Display* display = XOpenDisplay(NULL);
+    XRRScreenResources *screen = XRRGetScreenResources(display, DefaultRootWindow(display));
+    for (int iscres = screen->noutput - 1; iscres >= 0; --iscres) {
+        RROutput output = screen->outputs[iscres];
+        MonitorInfo * mi = read_edid_data(display, output);
+        if (mi == NULL) {
+            continue;
+        }
+
+        XRROutputInfo * info = XRRGetOutputInfo (display, screen, output);
+        if (info && (0 == memcmp(mi->manufacturer_code, "OVR", 3))) {
+
+            // Generate a device ID string similar to the way Windows does it
+            char device_id[32];
+            OVR_sprintf(device_id, 32, "%s%04d", mi->manufacturer_code, mi->product_code);
+
+            // The default monitor coordinates
+            int mx      = 0;
+            int my      = 0;
+            int mwidth  = 1280;
+            int mheight = 800;
+
+            if (info->connection == RR_Connected && info->crtc) {
+                XRRCrtcInfo * crtc_info = XRRGetCrtcInfo (display, screen, info->crtc);
+                if (crtc_info)
+                {
+                    mx = crtc_info->x;
+                    my = crtc_info->y;
+                    //mwidth = crtc_info->width;
+                    //mheight = crtc_info->height;
+                    XRRFreeCrtcInfo(crtc_info);
+                }
+            }
+
+            String deviceID = device_id;
+            HMDDeviceCreateDesc hmdCreateDesc(this, deviceID, iscres);
+
+            // Hard-coded defaults in case the device doesn't have the data itself.
+            if (strstr(device_id, "OVR0003"))
+            {   // DK2 prototypes and variants (default to HmdType_DK2)
+                hmdCreateDesc.SetScreenParameters(mx, my, 1920, 1080, 0.12576f, 0.07074f, 0.12576f*0.5f, 0.0635f );
+            }
+            else if (strstr(device_id, "OVR0002"))
+            {   // HD Prototypes (default to HmdType_DKHDProto)
+                hmdCreateDesc.SetScreenParameters(mx, my, 1920, 1080, 0.12096f, 0.06804f, 0.06804f*0.5f, 0.0635f );
+            }
+            else if (strstr(device_id, "OVR0001"))
+            {   // DK1
+                hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.14976f, 0.0936f, 0.0936f*0.5f, 0.0635f);
+            }
+            else if (strstr(device_id, "OVR00"))
+            {   // Future Oculus HMD devices (default to DK1 dimensions)
+                hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.14976f, 0.0936f, 0.0936f*0.5f, 0.0635f);
+            }
+            else
+            {   // Duct-tape prototype
+                hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.12096f, 0.0756f, 0.0756f*0.5f, 0.0635f);
+            }
+
+            OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %s - %s\n", device_id, mi->dsc_product_name));
+
+            // Notify caller about detected device. This will call EnumerateAddDevice
+            // if the this is the first time device was detected.
+            visitor.Visit(hmdCreateDesc);
+            foundHMD = true;
+            break;
+        } // if
+
+        XRRFreeOutputInfo(info);
+        delete mi;
+    } // for
+    XRRFreeScreenResources(screen);
+
+
+    // Real HMD device is not found; however, we still may have a 'fake' HMD
+    // device created via SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo.
+    // Need to find it and set 'Enumerated' to true to avoid Removal notification.
+    if (!foundHMD)
+    {
+        Ptr<DeviceCreateDesc> hmdDevDesc = getManager()->FindDevice("", Device_HMD);
+        if (hmdDevDesc)
+            hmdDevDesc->Enumerated = true;
+    }
+}
+
+#include "OVR_Common_HMDDevice.cpp"
+
+}} // namespace OVR::Linux
+
+
diff --git a/LibOVR/Src/OVR_Linux_HMDDevice.h b/LibOVR/Src/OVR_Linux_HMDDevice.h
new file mode 100644
index 0000000..a8c044f
--- /dev/null
+++ b/LibOVR/Src/OVR_Linux_HMDDevice.h
@@ -0,0 +1,154 @@
+/************************************************************************************
+
+Filename    :   OVR_Linux_HMDDevice.h
+Content     :   Linux HMDDevice implementation
+Created     :   June 17, 2013
+Authors     :   Brant Lewis
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Linux_HMDDevice_h
+#define OVR_Linux_HMDDevice_h
+
+#include "OVR_Linux_DeviceManager.h"
+#include "OVR_Profile.h"
+
+namespace OVR { namespace Linux {
+
+class HMDDevice;
+
+//-------------------------------------------------------------------------------------
+
+// HMDDeviceFactory enumerates attached Oculus HMD devices.
+//
+// This is currently done by matching monitor device strings.
+
+class HMDDeviceFactory : public DeviceFactory
+{
+public:
+    static HMDDeviceFactory &GetInstance();
+
+    // Enumerates devices, creating and destroying relevant objects in manager.
+    virtual void EnumerateDevices(EnumerateVisitor& visitor);
+
+protected:
+    DeviceManager* getManager() const { return (DeviceManager*) pManager; }
+};
+
+
+class HMDDeviceCreateDesc : public DeviceCreateDesc
+{
+    friend class HMDDevice;
+
+protected:
+    enum
+    {
+        Contents_Screen     = 1,
+        Contents_Distortion = 2,
+    };
+    String              DeviceId;
+    String              DisplayDeviceName;
+    struct
+    {
+        int             X, Y;
+    }                   Desktop;
+    unsigned int        Contents;
+
+    Sizei               ResolutionInPixels;
+    Sizef               ScreenSizeInMeters;
+    float               VCenterFromTopInMeters;
+    float               LensSeparationInMeters;
+
+    // TODO: update these to splines.
+    DistortionEqnType   DistortionEqn;
+    float               DistortionK[4];
+
+    long                DisplayId;
+
+public:
+    HMDDeviceCreateDesc(DeviceFactory* factory,
+                        const String& displayDeviceName, long dispId);
+    HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other);
+
+    virtual DeviceCreateDesc* Clone() const
+    {
+        return new HMDDeviceCreateDesc(*this);
+    }
+
+    virtual DeviceBase* NewDeviceInstance();
+
+    virtual MatchResult MatchDevice(const DeviceCreateDesc& other,
+                                    DeviceCreateDesc**) const;
+
+    // Matches device by path.
+    virtual bool        MatchDevice(const String& path);
+
+    virtual bool        UpdateMatchedCandidate(const DeviceCreateDesc&, bool* newDeviceFlag = NULL);
+
+    virtual bool GetDeviceInfo(DeviceInfo* info) const;
+
+    void  SetScreenParameters(int x, int y,
+                              int hres, int vres,
+                              float hsize, float vsize,
+                              float vCenterFromTopInMeters, float lensSeparationInMeters);
+    void SetDistortion(const float* dks);
+   
+    HmdTypeEnum GetHmdType() const;
+};
+
+
+//-------------------------------------------------------------------------------------
+
+// HMDDevice represents an Oculus HMD device unit. An instance of this class
+// is typically created from the DeviceManager.
+//  After HMD device is created, we its sensor data can be obtained by 
+//  first creating a Sensor object and then wrappig it in SensorFusion.
+
+class HMDDevice : public DeviceImpl<OVR::HMDDevice>
+{
+public:
+    HMDDevice(HMDDeviceCreateDesc* createDesc);
+    ~HMDDevice();    
+
+    virtual bool Initialize(DeviceBase* parent);
+    virtual void Shutdown();
+
+    // Requests the currently used default profile. This profile affects the
+    // settings reported by HMDInfo. 
+    virtual Profile*    GetProfile();
+    virtual const char* GetProfileName();
+    virtual bool        SetProfileName(const char* name);
+
+    // Query associated sensor.
+    virtual OVR::SensorDevice* GetSensor();  
+
+protected:
+    HMDDeviceCreateDesc* getDesc() const { return (HMDDeviceCreateDesc*)pCreateDesc.GetPtr(); }
+
+    // User name for the profile used with this device.
+    String               ProfileName;
+    mutable Ptr<Profile> pCachedProfile;
+};
+
+
+}} // namespace OVR::Linux
+
+#endif // OVR_Linux_HMDDevice_h
+
diff --git a/LibOVR/Src/OVR_Linux_SensorDevice.cpp b/LibOVR/Src/OVR_Linux_SensorDevice.cpp
new file mode 100644
index 0000000..5b671a6
--- /dev/null
+++ b/LibOVR/Src/OVR_Linux_SensorDevice.cpp
@@ -0,0 +1,57 @@
+/************************************************************************************
+
+Filename    :   OVR_Linux_SensorDevice.cpp
+Content     :   Linux SensorDevice implementation
+Created     :   June 13, 2013
+Authors     :   Brant Lewis
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_Linux_HMDDevice.h"
+#include "OVR_SensorImpl.h"
+#include "OVR_DeviceImpl.h"
+
+namespace OVR { namespace Linux {
+
+} // namespace Linux
+
+//-------------------------------------------------------------------------------------
+void SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(   const SensorDisplayInfoImpl& displayInfo, 
+                                                            DeviceFactory::EnumerateVisitor& visitor)
+{
+    Linux::HMDDeviceCreateDesc hmdCreateDesc(&Linux::HMDDeviceFactory::GetInstance(), String(), 0);
+
+    hmdCreateDesc.SetScreenParameters(  0, 0,
+                                        displayInfo.HResolution, displayInfo.VResolution,
+                                        displayInfo.HScreenSize, displayInfo.VScreenSize,
+                                        displayInfo.VCenter, displayInfo.LensSeparation);
+
+    if ((displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) == SensorDisplayInfoImpl::Base_Distortion)
+    {
+        // TODO: update to spline system.
+        hmdCreateDesc.SetDistortion(displayInfo.DistortionK);
+    }
+
+    visitor.Visit(hmdCreateDesc);
+}
+
+} // namespace OVR
+
+
diff --git a/LibOVR/Src/OVR_Profile.cpp b/LibOVR/Src/OVR_Profile.cpp
new file mode 100644
index 0000000..4844c29
--- /dev/null
+++ b/LibOVR/Src/OVR_Profile.cpp
@@ -0,0 +1,1517 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_Profile.cpp
+Content     :   Structs and functions for loading and storing device profile settings
+Created     :   February 14, 2013
+Notes       :
+   
+   Profiles are used to store per-user settings that can be transferred and used
+   across multiple applications.  For example, player IPD can be configured once 
+   and reused for a unified experience across games.  Configuration and saving of profiles
+   can be accomplished in game via the Profile API or by the official Oculus Configuration
+   Utility.
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_Profile.h"
+#include "OVR_Device.h"
+#include "OVR_JSON.h"
+#include "Kernel/OVR_Types.h"
+#include "Kernel/OVR_SysFile.h"
+#include "Kernel/OVR_Allocator.h"
+#include "Kernel/OVR_Array.h"
+
+#ifdef OVR_OS_WIN32
+#include <Shlobj.h>
+#else
+#include <dirent.h>
+#include <sys/stat.h>
+
+#ifdef OVR_OS_LINUX
+#include <unistd.h>
+#include <pwd.h>
+#endif
+
+#endif
+
+
+#define PROFILE_VERSION 2.0
+#define MAX_PROFILE_MAJOR_VERSION 2
+#define MAX_DEVICE_PROFILE_MAJOR_VERSION 1
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------
+// Returns the pathname of the JSON file containing the stored profiles
+String GetBaseOVRPath(bool create_dir)
+{
+    String path;
+
+#if defined(OVR_OS_WIN32)
+
+    TCHAR data_path[MAX_PATH];
+    SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, NULL, 0, data_path);
+    path = String(data_path);
+    
+    path += "/Oculus";
+
+    if (create_dir)
+    {   // Create the Oculus directory if it doesn't exist
+        WCHAR wpath[128];
+        OVR::UTF8Util::DecodeString(wpath, path.ToCStr());
+
+        DWORD attrib = GetFileAttributes(wpath);
+        bool exists = attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY);
+        if (!exists)
+        {   
+            CreateDirectory(wpath, NULL);
+        }
+    }
+        
+#elif defined(OVR_OS_MAC)
+
+    const char* home = getenv("HOME");
+    path = home;
+    path += "/Library/Preferences/Oculus";
+
+    if (create_dir)
+    {   // Create the Oculus directory if it doesn't exist
+        DIR* dir = opendir(path);
+        if (dir == NULL)
+        {
+            mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
+        }
+        else
+        {
+            closedir(dir);
+        }
+    }
+
+#else
+
+    passwd* pwd = getpwuid(getuid());
+    const char* home = pwd->pw_dir;
+    path = home;
+    path += "/.config/Oculus";
+
+    if (create_dir)
+    {   // Create the Oculus directory if it doesn't exist
+        DIR* dir = opendir(path);
+        if (dir == NULL)
+        {
+            mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
+        }
+        else
+        {
+            closedir(dir);
+        }
+    }
+
+#endif
+
+    return path;
+}
+
+String ProfileManager::GetProfilePath(bool create_dir)
+{
+    String path = GetBaseOVRPath(create_dir);
+    path += "/ProfileDB.json";
+    return path;
+}
+
+bool ProfileManager::GetDeviceTags(const DeviceBase* device, String& product, String& serial)
+{
+    product = "";
+    serial = "";
+
+    if (device && device->GetType() == Device_HMD)
+    {
+        HMDDevice* hmd = (HMDDevice*)device;
+
+        Ptr<SensorDevice> sensor = *(hmd->GetSensor());
+        if (sensor)
+        {
+            SensorInfo sinfo;
+            sensor->GetDeviceInfo(&sinfo);
+            serial = sinfo.SerialNumber;    // get the serial number
+
+            // Derive the product tag from the HMD product name
+            HMDInfo hmdinfo;
+            hmd->GetDeviceInfo(&hmdinfo);
+
+            const char* product_name = NULL;
+
+            // If the HMD is unrecognized then use the name stamped into the
+            // sensor firmware
+            if (hmdinfo.HmdType == HmdType_None || hmdinfo.HmdType == HmdType_Unknown)
+                product_name = sinfo.ProductName.ToCStr();
+            else
+                product_name = hmdinfo.ProductName.ToCStr();
+            
+            // First strip off "Oculus"
+            const char* oculus = strstr(product_name, "Oculus ");
+            if (oculus)
+                product_name = oculus + OVR_strlen("Oculus ");
+            // And remove spaces from the name
+            for (const char* s=product_name; *s != 0; s++)
+            {
+                if (*s != ' ')
+                    product.AppendChar(*s);
+            }         
+        } 
+    }
+    
+    return (!product.IsEmpty() && !serial.IsEmpty());
+}
+
+static JSON* FindTaggedData(JSON* data, const char** tag_names, const char** qtags, int num_qtags)
+{
+    if (data == NULL || !(data->Name == "TaggedData") || data->Type != JSON_Array)
+        return NULL;
+
+    JSON* tagged_item = data->GetFirstItem();
+    while (tagged_item)
+    {
+        JSON* tags = tagged_item->GetItemByName("tags");
+        if (tags->Type == JSON_Array && num_qtags == tags->GetArraySize())
+        {   // Check for a full tag match on each item
+            int num_matches = 0;
+            
+            for (int k=0; k<num_qtags; k++)
+            {
+                JSON* tag = tags->GetFirstItem();
+                while (tag)
+                {
+                    JSON* tagval = tag->GetFirstItem();
+                    if (tagval && tagval->Name == tag_names[k])
+                    {
+                        if (tagval->Value == qtags[k])
+                            num_matches++;
+                        break;
+                    }
+                    tag = tags->GetNextItem(tag);
+                }
+            }
+
+            // if all tags were matched then copy the values into this Profile
+            if (num_matches == num_qtags)
+            {
+                JSON* vals = tagged_item->GetItemByName("vals");
+                return vals;
+            }
+        }
+
+        tagged_item = data->GetNextItem(tagged_item);
+    }
+
+    return NULL;
+}
+
+static void FilterTaggedData(JSON* data, const char* tag_name, const char* qtag, Array<JSON*>& items)
+{
+    if (data == NULL || !(data->Name == "TaggedData") || data->Type != JSON_Array)
+        return;
+
+    JSON* tagged_item = data->GetFirstItem();
+    while (tagged_item)
+    {
+        JSON* tags = tagged_item->GetItemByName("tags");
+        if (tags->Type == JSON_Array)
+        {   // Check for a tag match on the requested tag
+            
+            JSON* tag = tags->GetFirstItem();
+            while (tag)
+            {
+                JSON* tagval = tag->GetFirstItem();
+                if (tagval && tagval->Name == tag_name)
+                {
+                    if (tagval->Value == qtag)
+                    {   // Add this item to the output list
+                        items.PushBack(tagged_item);
+                    }
+                    break;
+                }
+                tag = tags->GetNextItem(tag);
+            }
+        }
+
+        tagged_item = data->GetNextItem(tagged_item);
+    }
+}
+
+//-----------------------------------------------------------------------------
+// ***** ProfileManager
+
+ProfileManager::ProfileManager()
+{
+    Changed = false;
+}
+
+ProfileManager::~ProfileManager()
+{
+    ClearCache();
+}
+
+ProfileManager* ProfileManager::Create()
+{
+    return new ProfileManager();
+}
+
+// Clear the local profile cache
+void ProfileManager::ClearCache()
+{
+    Lock::Locker lockScope(&ProfileLock);
+    //ProfileCache.Clear();
+    if (ProfileCache)
+    {
+        //ProfileCache->Release();
+        ProfileCache = NULL;
+    }
+    Changed = false;
+}
+
+// Returns a profile with all system default values
+Profile* ProfileManager::GetDefaultProfile(const DeviceBase* device)
+{
+    // In the absence of any data, set some reasonable profile defaults.
+    // However, this is not future proof and developers should still
+    // provide reasonable default values for queried fields.
+    Profile* profile = CreateProfile();
+    profile->SetValue(OVR_KEY_USER, "default");
+    profile->SetValue(OVR_KEY_NAME, "Default");
+    profile->SetValue(OVR_KEY_GENDER, OVR_DEFAULT_GENDER);
+    profile->SetFloatValue(OVR_KEY_PLAYER_HEIGHT, OVR_DEFAULT_PLAYER_HEIGHT);
+    profile->SetFloatValue(OVR_KEY_EYE_HEIGHT, 1.675f);
+    profile->SetFloatValue(OVR_KEY_IPD, OVR_DEFAULT_IPD);
+    float dist[2] = {OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL, OVR_DEFAULT_NECK_TO_EYE_VERTICAL};
+    profile->SetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, dist, 2);
+    //profile->SetFloatValue(OVR_KEY_NECK_TO_EYE_VERTICAL, 0.12f);
+
+    // TODO: Provide device specific defaults
+    OVR_UNUSED(device);
+
+    // DK1 default
+    //profile->SetValue("EyeCup", "A");
+
+    return profile;
+}
+
+// Poplulates the local profile cache.  This occurs on the first access of the profile
+// data.  All profile operations are performed against the local cache until the
+// ProfileManager is released or goes out of scope at which time the cache is serialized
+// to disk.
+void ProfileManager::LoadCache(bool create)
+{
+    Lock::Locker lockScope(&ProfileLock);
+
+    ClearCache();
+
+    String path = GetProfilePath(false);
+
+    Ptr<JSON> root = *JSON::Load(path);
+    if (root == NULL)
+    {   
+        path = GetBaseOVRPath(false) + "/Profiles.json";  // look for legacy profile
+        root = *JSON::Load(path);
+        
+        if (root == NULL)
+        {
+            if (create)
+            {   // Generate a skeleton profile database
+                root = *JSON::CreateObject();
+                root->AddNumberItem("Oculus Profile Version", 2.0);
+                root->AddItem("Users", JSON::CreateArray());
+                root->AddItem("TaggedData", JSON::CreateArray());
+                ProfileCache = root;
+            }
+            
+            return;
+        }
+
+        // Verify the legacy version
+        JSON* version_item = root->GetFirstItem();
+        if (version_item->Name == "Oculus Profile Version")
+        {
+            int major = atoi(version_item->Value.ToCStr());
+            if (major != 1)
+                return;   // don't use the file on unsupported major version number
+        }
+        else
+        {
+            return;      // invalid file
+        }
+
+        // Convert the legacy format to the new database format
+        LoadV1Profiles(root);
+    }
+    else
+    {
+        // Verify the file format and version
+        JSON* version_item = root->GetFirstItem();
+        if (version_item->Name == "Oculus Profile Version")
+        {
+            int major = atoi(version_item->Value.ToCStr());
+            if (major != 2)
+                return;   // don't use the file on unsupported major version number
+        }
+        else
+        {
+            return;       // invalid file 
+        }
+
+        ProfileCache = root;   // store the database contents for traversal
+    }
+}
+
+void ProfileManager::LoadV1Profiles(JSON* v1)
+{
+    JSON* item0 = v1->GetFirstItem();
+    JSON* item1 = v1->GetNextItem(item0);
+    JSON* item2 = v1->GetNextItem(item1);
+
+    // Create the new profile database
+    Ptr<JSON> root = *JSON::CreateObject();
+    root->AddNumberItem("Oculus Profile Version", 2.0);
+    root->AddItem("Users", JSON::CreateArray());
+    root->AddItem("TaggedData", JSON::CreateArray());
+    ProfileCache = root;
+
+    const char* default_dk1_user = item1->Value;
+    
+    // Read the number of profiles
+    int   profileCount = (int)item2->dValue;
+    JSON* profileItem  = item2;
+
+    for (int p=0; p<profileCount; p++)
+    {
+        profileItem = root->GetNextItem(profileItem);
+        if (profileItem == NULL)
+            break;
+
+        if (profileItem->Name == "Profile")
+        {
+            // Read the required Name field
+            const char* profileName;
+            JSON* item = profileItem->GetFirstItem();
+        
+            if (item && (item->Name == "Name"))
+            {   
+                profileName = item->Value;
+            }
+            else
+            {
+                return;   // invalid field
+            }
+            
+            // Read the user profile fields
+            if (CreateUser(profileName, profileName))
+            {
+                const char* tag_names[2] = {"User", "Product"};
+                const char* tags[2];
+                tags[0] = profileName;
+
+                Ptr<Profile> user_profile = *CreateProfile();
+                user_profile->SetValue(OVR_KEY_NAME, profileName);
+
+                float neckeye[2] = { 0, 0 };
+
+                item = profileItem->GetNextItem(item);
+                while (item)
+                {
+                    if (item->Type != JSON_Object)
+                    {
+                        if (item->Name == OVR_KEY_PLAYER_HEIGHT)
+                        {   // Add an explicit eye height
+
+                        }
+                        if (item->Name == "NeckEyeHori")
+                            neckeye[0] = (float)item->dValue;
+                        else if (item->Name == "NeckEyeVert")
+                            neckeye[1] = (float)item->dValue;
+                        else 
+                            user_profile->SetValue(item);
+                    }
+                    else
+                    {   
+                        // Add the user/device tag values
+                        const char* device_name = item->Name.ToCStr();
+                        Ptr<Profile> device_profile = *CreateProfile();
+
+                        JSON* device_item = item->GetFirstItem();
+                        while (device_item)
+                        {
+                            device_profile->SetValue(device_item);
+                            device_item = item->GetNextItem(device_item);
+                        }
+
+                        tags[1] = device_name;
+                        SetTaggedProfile(tag_names, tags, 2, device_profile);
+                    }
+
+                    item = profileItem->GetNextItem(item);
+                }
+
+                // Add an explicit eye-height field
+                float player_height = user_profile->GetFloatValue(OVR_KEY_PLAYER_HEIGHT,
+                                                                  OVR_DEFAULT_PLAYER_HEIGHT);
+                if (player_height > 0)
+                {
+                    char gender[16];
+                    user_profile->GetValue(OVR_KEY_GENDER, gender, 16);
+        
+                    const float EYE_TO_HEADTOP_RATIO =   0.44538f;
+                    const float MALE_AVG_HEAD_HEIGHT =   0.232f;
+                    const float FEMALE_AVG_HEAD_HEIGHT = 0.218f;
+     
+                    // compute distance from top of skull to the eye
+                    float head_height;
+                    if (OVR_strcmp(gender, "Female") == 0)
+                        head_height = FEMALE_AVG_HEAD_HEIGHT;
+                    else
+                        head_height = MALE_AVG_HEAD_HEIGHT;
+
+                    float skull = EYE_TO_HEADTOP_RATIO * head_height;
+                    float eye_height = player_height - skull;
+
+                    user_profile->SetFloatValue(OVR_KEY_EYE_HEIGHT, eye_height);
+                }
+
+                // Convert NeckEye values to an array
+                if (neckeye[0] > 0 && neckeye[1] > 0)
+                    user_profile->SetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, neckeye, 2);
+
+                // Add the user tag values
+                SetTaggedProfile(tag_names, tags, 1, user_profile);
+            }
+        }
+    }
+
+    // since V1 profiles were only for DK1, the assign the user to all DK1's
+    const char* tag_names[1] = { "Product" };
+    const char* tags[1] = { "RiftDK1" };
+    Ptr<Profile> product_profile = *CreateProfile();
+    product_profile->SetValue("DefaultUser", default_dk1_user);
+    SetTaggedProfile(tag_names, tags, 1, product_profile);
+}
+
+// Returns the number of stored profiles for this device type
+int ProfileManager::GetUserCount()
+{
+    Lock::Locker lockScope(&ProfileLock);
+
+    if (ProfileCache == NULL)
+    {   // Load the cache
+        LoadCache(false);
+        if (ProfileCache == NULL)
+            return 0;
+    }
+
+    JSON* users = ProfileCache->GetItemByName("Users");
+    if (users == NULL)
+        return 0;
+
+    return users->GetItemCount();
+}
+
+bool ProfileManager::CreateUser(const char* user, const char* name)
+{
+    Lock::Locker lockScope(&ProfileLock);
+
+    if (ProfileCache == NULL)
+    {   // Load the cache
+        LoadCache(true);
+        if (ProfileCache == NULL)
+            return false;
+    }
+
+    JSON* users = ProfileCache->GetItemByName("Users");
+    if (users == NULL)
+    {   // Generate the User section
+        users = JSON::CreateArray();
+        ProfileCache->AddItem("Users", users);
+//TODO: Insert this before the TaggedData
+    }
+
+    // Search for the pre-existence of this user
+    JSON* user_item = users->GetFirstItem();
+    int index = 0;
+    while (user_item)
+    {
+        JSON* userid = user_item->GetItemByName("User");
+        int compare = OVR_strcmp(user, userid->Value);
+        if (compare == 0)
+        {   // The user already exists so simply update the fields
+            JSON* name_item = user_item->GetItemByName("Name");
+            if (name_item && OVR_strcmp(name, name_item->Value) != 0)
+            {
+                name_item->Value = name;
+                Changed = true;
+            }
+            return true;
+        }
+        else if (compare < 0)
+        {   // A new user should be placed before this item
+            break;
+        }
+        
+        user_item = users->GetNextItem(user_item);
+        index++;
+    }
+
+    // Create and fill the user struct
+    JSON* new_user = JSON::CreateObject();
+    new_user->AddStringItem(OVR_KEY_USER, user);
+    new_user->AddStringItem(OVR_KEY_NAME, name);
+    // user_item->AddStringItem("Password", password);
+
+    if (user_item == NULL)
+        users->AddArrayElement(new_user);
+    else
+        users->InsertArrayElement(index, new_user);
+
+    Changed = true;
+    return true;
+}
+
+// Returns the user id of a specific user in the list.  The returned 
+// memory is locally allocated and should not be stored or deleted.  Returns NULL
+// if the index is invalid
+const char* ProfileManager::GetUser(unsigned int index)
+{
+    Lock::Locker lockScope(&ProfileLock);
+
+    if (ProfileCache == NULL)
+    {   // Load the cache
+        LoadCache(false);
+        if (ProfileCache == NULL)
+            return NULL;
+    }
+
+    JSON* users = ProfileCache->GetItemByName("Users");
+    
+    if (users && index < users->GetItemCount())
+    {
+        JSON* user_item = users->GetItemByIndex(index);
+        if (user_item)
+        {
+            JSON* user = user_item->GetFirstItem();
+            if (user)
+            {
+                JSON* userid = user_item->GetItemByName(OVR_KEY_USER);
+                if (userid)
+                    return userid->Value.ToCStr();
+            }
+        }
+    }
+    
+
+    return NULL;
+}
+
+bool ProfileManager::RemoveUser(const char* user)
+{
+    Lock::Locker lockScope(&ProfileLock);
+
+    if (ProfileCache == NULL)
+    {   // Load the cache
+        LoadCache(false);
+        if (ProfileCache == NULL)
+            return true;
+    }
+
+    JSON* users = ProfileCache->GetItemByName("Users");
+    if (users == NULL)
+        return true;
+
+    // Remove this user from the User table
+    JSON* user_item = users->GetFirstItem();
+    while (user_item)
+    {
+        JSON* userid = user_item->GetItemByName("User");
+        if (OVR_strcmp(user, userid->Value) == 0)
+        {   // Delete the user entry
+            user_item->RemoveNode();
+            user_item->Release();
+            Changed = true;
+            break;
+        }
+        
+        user_item = users->GetNextItem(user_item);
+    }
+
+    // Now remove all data entries with this user tag
+    JSON* tagged_data = ProfileCache->GetItemByName("TaggedData");
+    Array<JSON*> user_items;
+    FilterTaggedData(tagged_data, "User", user, user_items);
+    for (unsigned int i=0; i<user_items.GetSize(); i++)
+    {
+        user_items[i]->RemoveNode();
+        user_items[i]->Release();
+        Changed = true;
+    }
+ 
+    return Changed;
+}
+
+Profile* ProfileManager::CreateProfile()
+{
+    Profile* profile = new Profile();
+    return profile;
+}
+
+// Returns the name of the profile that is marked as the current default user.
+const char* ProfileManager::GetDefaultUser(const DeviceBase* device)
+{
+    const char* tag_names[2] = {"Product", "Serial"};
+    const char* tags[2];
+
+    String product;
+    String serial;
+    if (!GetDeviceTags(device, product, serial))
+        return NULL;
+
+    const char* product_str = product.IsEmpty() ? NULL : product.ToCStr();
+    const char* serial_str = serial.IsEmpty() ? NULL : serial.ToCStr();
+
+    if (product_str && serial_str)
+    {
+        tags[0] = product_str;
+        tags[1] = serial_str;
+        // Look for a default user on this specific device
+        Ptr<Profile> p = *GetTaggedProfile(tag_names, tags, 2);
+        if (p == NULL)
+        {   // Look for a default user on this product
+            p = *GetTaggedProfile(tag_names, tags, 1);
+        }
+
+        if (p)
+        {   
+            const char* user = p->GetValue("DefaultUser");
+            if (user != NULL && user[0] != 0)
+            {
+                TempBuff = user;
+                return TempBuff.ToCStr();
+            }
+        }
+    }
+
+    return NULL;
+}
+
+//-----------------------------------------------------------------------------
+bool ProfileManager::SetDefaultUser(const DeviceBase* device, const char* user)
+{
+    const char* tag_names[2] = {"Product", "Serial"};
+    const char* tags[2];
+
+    String product;
+    String serial;
+    if (!GetDeviceTags(device, product, serial))
+        return NULL;
+
+    const char* product_str = product.IsEmpty() ? NULL : product.ToCStr();
+    const char* serial_str = serial.IsEmpty() ? NULL : serial.ToCStr();
+
+    if (product_str && serial_str)
+    {
+        tags[0] = product_str;
+        tags[1] = serial_str;
+
+        Ptr<Profile> p = *CreateProfile();
+        p->SetValue("DefaultUser", user);
+        return SetTaggedProfile(tag_names, tags, 2, p);
+    }
+
+    return false;
+}
+
+//-----------------------------------------------------------------------------
+Profile* ProfileManager::GetTaggedProfile(const char** tag_names, const char** tags, int num_tags)
+{
+    Lock::Locker lockScope(&ProfileLock);
+
+    if (ProfileCache == NULL)
+    {   // Load the cache
+        LoadCache(false);
+        if (ProfileCache == NULL)
+            return NULL;
+    }
+
+    JSON* tagged_data = ProfileCache->GetItemByName("TaggedData");
+    OVR_ASSERT(tagged_data);
+    if (tagged_data == NULL)
+        return NULL;
+    
+    Profile* profile = new Profile();
+    
+    JSON* vals = FindTaggedData(tagged_data, tag_names, tags, num_tags);
+    if (vals)
+    {   
+        JSON* item = vals->GetFirstItem();
+        while (item)
+        {
+            //printf("Add %s, %s\n", item->Name.ToCStr(), item->Value.ToCStr());
+            //profile->Settings.Set(item->Name, item->Value);
+            profile->SetValue(item);
+            item = vals->GetNextItem(item);
+        }
+
+        return profile;
+    }
+    else
+    {
+        profile->Release();
+        return NULL;
+    }
+}
+
+//-----------------------------------------------------------------------------
+bool ProfileManager::SetTaggedProfile(const char** tag_names, const char** tags, int num_tags, Profile* profile)
+{
+    Lock::Locker lockScope(&ProfileLock);
+
+    if (ProfileCache == NULL)
+    {   // Load the cache
+        LoadCache(true);
+        if (ProfileCache == NULL)
+            return false;  // TODO: Generate a new profile DB
+    }
+
+    JSON* tagged_data = ProfileCache->GetItemByName("TaggedData");
+    OVR_ASSERT(tagged_data);
+    if (tagged_data == NULL)
+        return false;
+
+    // Get the cached tagged data section
+    JSON* vals = FindTaggedData(tagged_data, tag_names, tags, num_tags);
+    if (vals == NULL)
+    {  
+        JSON* tagged_item = JSON::CreateObject();
+        JSON* taglist = JSON::CreateArray();
+        for (int i=0; i<num_tags; i++)
+        {
+            JSON* k = JSON::CreateObject();
+            k->AddStringItem(tag_names[i], tags[i]);
+            taglist->AddArrayElement(k);
+        }
+
+        vals = JSON::CreateObject();
+        
+        tagged_item->AddItem("tags", taglist);
+        tagged_item->AddItem("vals", vals);
+        tagged_data->AddArrayElement(tagged_item);
+    }
+
+    // Now add or update each profile setting in cache
+    for (unsigned int i=0; i<profile->Values.GetSize(); i++)
+    {
+        JSON* value = profile->Values[i];
+        
+        bool found = false;
+        JSON* item = vals->GetFirstItem();
+        while (item)
+        {
+            if (value->Name == item->Name)
+            {
+                // Don't allow a pre-existing type to be overridden
+                OVR_ASSERT(value->Type == item->Type);
+
+                if (value->Type == item->Type)
+                {   // Check for the same value
+                    if (value->Type == JSON_Array)
+                    {   // Update each array item
+                        if (item->GetArraySize() == value->GetArraySize())
+                        {   // Update each value (assumed to be basic types and not array of objects)
+                            JSON* value_element = value->GetFirstItem();
+                            JSON* item_element = item->GetFirstItem();
+                            while (item_element && value_element)
+                            {
+                                if (value_element->Type == JSON_String)
+                                {
+                                    if (item_element->Value != value_element->Value)
+                                    {   // Overwrite the changed value and mark for file update
+                                        item_element->Value = value_element->Value;
+                                        Changed = true;
+                                    }
+                                }
+                                else {
+                                    if (item_element->dValue != value_element->dValue)
+                                    {   // Overwrite the changed value and mark for file update
+                                        item_element->dValue = value_element->dValue;
+                                        Changed = true;
+                                    }
+                                }
+                                
+                                value_element = value->GetNextItem(value_element);
+                                item_element = item->GetNextItem(item_element);
+                            }
+                        }
+                        else
+                        {   // if the array size changed, simply create a new one                            
+// TODO: Create the new array
+                        }
+                    }
+                    else if (value->Type == JSON_String)
+                    {
+                        if (item->Value != value->Value)
+                        {   // Overwrite the changed value and mark for file update
+                            item->Value = value->Value;
+                            Changed = true;
+                        }
+                    }
+                    else {
+                        if (item->dValue != value->dValue)
+                        {   // Overwrite the changed value and mark for file update
+                            item->dValue = value->dValue;
+                            Changed = true;
+                        }
+                    }
+                }
+                else
+                {
+                    return false;
+                }
+
+                found = true;
+                break;
+            }
+            
+            item = vals->GetNextItem(item);
+        }
+
+        if (!found)
+        {   // Add the new value
+            if (value->Type == JSON_String)
+                vals->AddStringItem(value->Name, value->Value);
+            else if (value->Type == JSON_Bool)
+                vals->AddBoolItem(value->Name, (value->dValue != 0));
+            else if (value->Type == JSON_Array)
+                vals->AddItem(value->Name, value->Copy());
+            else
+                vals->AddNumberItem(value->Name, value->dValue);
+
+            Changed = true;
+        }
+    }
+
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+Profile* ProfileManager::GetProfile(const DeviceBase* device, const char* user)
+{
+    Lock::Locker lockScope(&ProfileLock);
+
+    if (ProfileCache == NULL)
+    {   // Load the cache
+        LoadCache(false);
+        if (ProfileCache == NULL)
+            return NULL;
+    }
+    
+    Profile* profile = new Profile();
+
+    if (device)
+    {
+        if (!profile->LoadDeviceProfile(device) && (user == NULL))
+        {
+            profile->Release();
+            return NULL;
+        }
+    }
+    
+    if (user)
+    {
+        String product;
+        String serial;
+        GetDeviceTags(device, product, serial);
+       
+        const char* product_str = product.IsEmpty() ? NULL : product.ToCStr();
+        const char* serial_str = serial.IsEmpty() ? NULL : serial.ToCStr();
+
+        if (!profile->LoadProfile(ProfileCache.GetPtr(), user, product_str, serial_str))
+        {
+            profile->Release();
+            return NULL;
+        }
+    }
+
+    return profile;
+}
+
+//-----------------------------------------------------------------------------
+// ***** Profile
+
+Profile::~Profile()
+{
+    ValMap.Clear();
+    for (unsigned int i=0; i<Values.GetSize(); i++)
+        Values[i]->Release();
+
+    Values.Clear();
+}
+
+bool Profile::Close()
+{
+    // TODO:
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+void Profile::CopyItems(JSON* root, String prefix)
+{
+    JSON* item = root->GetFirstItem();
+    while (item)
+    {
+        String item_name;
+        if (prefix.IsEmpty())
+            item_name = item->Name;
+        else
+            item_name = prefix + "." + item->Name;
+
+        if (item->Type == JSON_Object)
+        {   // recursively copy the children
+            
+            CopyItems(item, item_name);
+        }
+        else
+        {
+            //Settings.Set(item_name, item->Value);
+            SetValue(item);
+        }
+
+        item = root->GetNextItem(item);
+    }
+}
+
+//-----------------------------------------------------------------------------
+bool Profile::LoadDeviceFile(unsigned int device_id, const char* serial)
+{
+    if (serial[0] == 0)
+        return false;
+
+    String path = GetBaseOVRPath(false);
+    path += "/Devices.json";
+
+    // Load the device profiles
+    Ptr<JSON> root = *JSON::Load(path);
+    if (root == NULL)
+        return false;
+
+    // Quick sanity check of the file type and format before we parse it
+    JSON* version = root->GetFirstItem();
+    if (version && version->Name == "Oculus Device Profile Version")
+    {   
+        int major = atoi(version->Value.ToCStr());
+        if (major > MAX_DEVICE_PROFILE_MAJOR_VERSION)
+            return false;   // don't parse the file on unsupported major version number
+    }
+    else
+    {
+        return false;
+    }   
+
+
+    JSON* device = root->GetNextItem(version);
+    while (device)
+    {   
+        if (device->Name == "Device")
+        {   
+            JSON* product_item = device->GetItemByName("ProductID");
+            JSON* serial_item = device->GetItemByName("Serial");
+            if (product_item && serial_item 
+                && (product_item->dValue == device_id) && (serial_item->Value == serial))
+            {   
+                // found the entry for this device so recursively copy all the settings to the profile
+                CopyItems(device, "");
+                return true;   
+            }
+        }
+
+        device = root->GetNextItem(device);
+    }
+    
+    return false;
+}
+
+//-----------------------------------------------------------------------------
+static int BCDByte(unsigned int byte)
+{
+    int digit1 = (byte >> 4) & 0x000f;
+    int digit2 = byte & 0x000f;
+    int decimal = digit1 * 10 + digit2;
+    return decimal;
+}
+
+//-----------------------------------------------------------------------------
+bool Profile::LoadDeviceProfile(const DeviceBase* device)
+{
+    bool success = false;
+    if (device == NULL)
+        return false;
+
+    SensorDevice* sensor = NULL;
+
+    if (device->GetType() == Device_HMD)
+    {     
+        // Convert the HMD device to Sensor
+        sensor = ((HMDDevice*)device)->GetSensor();
+        device = sensor;
+        if (device == NULL)
+            return false;
+    }
+
+    if (device->GetType() == Device_Sensor)
+    {
+        SensorDevice* sensor = (SensorDevice*)device;
+
+        SensorInfo sinfo;
+        sensor->GetDeviceInfo(&sinfo);
+
+        int dev_major = BCDByte((sinfo.Version >> 8) & 0x00ff);
+        OVR_UNUSED(dev_major);
+        int dev_minor = BCDByte(sinfo.Version & 0xff);
+      
+        if (dev_minor > 18)
+        {   // If the firmware supports hardware stored profiles then grab the device profile
+            // from the sensor
+            // TBD:  Implement this
+        }
+        else
+        {
+            // Grab the model and serial number from the device and use it to access the device
+            // profile file stored on the local machine
+            success = LoadDeviceFile(sinfo.ProductId, sinfo.SerialNumber);
+        }
+    }
+
+    if (sensor)
+        sensor->Release();    // release the sensor handle
+
+    return success;
+}
+
+//-----------------------------------------------------------------------------
+bool Profile::LoadUser(JSON* root, 
+                         const char* user,
+                          const char* model_name,
+                          const char* device_serial)
+{
+    if (user == NULL)
+        return false;
+
+    // For legacy files, convert to old style names
+    //if (model_name && OVR_strcmp(model_name, "Oculus Rift DK1") == 0)
+    //    model_name = "RiftDK1";
+    
+    bool user_found = false;
+    JSON* data = root->GetItemByName("TaggedData");
+    if (data)
+    {   
+        const char* tag_names[3];
+        const char* tags[3];
+        tag_names[0] = "User";
+        tags[0] = user;
+        int num_tags = 1;
+
+        if (model_name)
+        {
+            tag_names[num_tags] = "Product";
+            tags[num_tags] = model_name;
+            num_tags++;
+        }
+
+        if (device_serial)
+        {
+            tag_names[num_tags] = "Serial";
+            tags[num_tags] = device_serial;
+            num_tags++;
+        }
+
+        // Retrieve all tag permutations
+        for (int combos=1; combos<=num_tags; combos++)
+        {
+            for (int i=0; i<(num_tags - combos + 1); i++)
+            {
+                JSON* vals = FindTaggedData(data, tag_names+i, tags+i, combos);
+                if (vals)
+                {   
+                    if (i==0)   // This tag-combination contains a user match
+                        user_found = true;
+
+                    // Add the values to the Profile.  More specialized multi-tag values
+                    // will take precedence over and overwrite generalized ones 
+                    // For example: ("Me","RiftDK1").IPD would overwrite ("Me").IPD
+                    JSON* item = vals->GetFirstItem();
+                    while (item)
+                    {
+                        //printf("Add %s, %s\n", item->Name.ToCStr(), item->Value.ToCStr());
+                        //Settings.Set(item->Name, item->Value);
+                        SetValue(item);
+                        item = vals->GetNextItem(item);
+                    }
+                }
+            }
+        }
+    }
+
+    if (user_found)
+        SetValue(OVR_KEY_USER, user);
+
+    return user_found;
+}
+
+
+//-----------------------------------------------------------------------------
+bool Profile::LoadProfile(JSON* root,
+                          const char* user,
+                          const char* device_model,
+                          const char* device_serial)
+{
+    if (!LoadUser(root, user, device_model, device_serial))
+        return false;
+
+    return true;
+}
+
+
+//-----------------------------------------------------------------------------
+char* Profile::GetValue(const char* key, char* val, int val_length) const
+{
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value))
+    {
+        OVR_strcpy(val, val_length, value->Value.ToCStr());
+        return val;
+    }
+    else
+    {
+        val[0] = 0;
+        return NULL;
+    }
+}
+
+//-----------------------------------------------------------------------------
+const char* Profile::GetValue(const char* key)
+{
+    // Non-reentrant query.  The returned buffer can only be used until the next call
+    // to GetValue()
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value))
+    {
+        TempVal = value->Value;
+        return TempVal.ToCStr();
+    }
+    else
+    {
+        return NULL;
+    }
+}
+
+//-----------------------------------------------------------------------------
+int Profile::GetNumValues(const char* key) const
+{
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value))
+    {  
+        if (value->Type == JSON_Array)
+            return value->GetArraySize();
+        else
+            return 1;
+    }
+    else
+        return 0;        
+}
+
+//-----------------------------------------------------------------------------
+bool Profile::GetBoolValue(const char* key, bool default_val) const
+{
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value) && value->Type == JSON_Bool)
+        return (value->dValue != 0);
+    else
+        return default_val;
+}
+
+//-----------------------------------------------------------------------------
+int Profile::GetIntValue(const char* key, int default_val) const
+{
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value) && value->Type == JSON_Number)
+        return (int)(value->dValue);
+    else
+        return default_val;
+}
+
+//-----------------------------------------------------------------------------
+float Profile::GetFloatValue(const char* key, float default_val) const
+{
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value) && value->Type == JSON_Number)
+        return (float)(value->dValue);
+    else
+        return default_val;
+}
+
+//-----------------------------------------------------------------------------
+int Profile::GetFloatValues(const char* key, float* values, int num_vals) const
+{
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value) && value->Type == JSON_Array)
+    {
+        int val_count = Alg::Min(value->GetArraySize(), num_vals);
+        JSON* item = value->GetFirstItem();
+        int count=0;
+        while (item && count < val_count)
+        {
+            if (item->Type == JSON_Number)
+                values[count] = (float)item->dValue;
+            else
+                break;
+
+            count++;
+            item = value->GetNextItem(item);
+        }
+
+        return count;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+//-----------------------------------------------------------------------------
+double Profile::GetDoubleValue(const char* key, double default_val) const
+{
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value) && value->Type == JSON_Number)
+        return value->dValue;
+    else
+        return default_val;
+}
+
+//-----------------------------------------------------------------------------
+int Profile::GetDoubleValues(const char* key, double* values, int num_vals) const
+{
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value) && value->Type == JSON_Array)
+    {
+        int val_count = Alg::Min(value->GetArraySize(), num_vals);
+        JSON* item = value->GetFirstItem();
+        int count=0;
+        while (item && count < val_count)
+        {
+            if (item->Type == JSON_Number)
+                values[count] = item->dValue;
+            else
+                break;
+
+            count++;
+            item = value->GetNextItem(item);
+        }
+
+        return count;
+    }
+    else
+    {
+        return 0;
+    }
+}
+
+//-----------------------------------------------------------------------------
+void Profile::SetValue(JSON* val)
+{
+    if (val->Type == JSON_Number)
+        SetDoubleValue(val->Name, val->dValue);
+    else if (val->Type == JSON_Bool)
+        SetBoolValue(val->Name, (val->dValue != 0));
+    else if (val->Type == JSON_String)
+        SetValue(val->Name, val->Value);
+    else if (val->Type == JSON_Array)
+    {
+        if (val == NULL)
+            return;
+
+        // Create a copy of the array
+        JSON* value = val->Copy();
+        Values.PushBack(value);
+        ValMap.Set(value->Name, value);
+    }
+}
+
+//-----------------------------------------------------------------------------
+void Profile::SetValue(const char* key, const char* val)
+{
+    if (key == NULL || val == NULL)
+        return;
+
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value))
+    {
+        value->Value = val;
+    }
+    else
+    {
+        value = JSON::CreateString(val);
+        value->Name = key;
+
+        Values.PushBack(value);
+        ValMap.Set(key, value);
+    }
+}
+
+//-----------------------------------------------------------------------------
+void Profile::SetBoolValue(const char* key, bool val)
+{
+    if (key == NULL)
+        return;
+
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value))
+    {
+        value->dValue = val;
+    }
+    else
+    {
+        value = JSON::CreateBool(val);
+        value->Name = key;
+
+        Values.PushBack(value);
+        ValMap.Set(key, value);
+    }
+}
+
+//-----------------------------------------------------------------------------
+void Profile::SetIntValue(const char* key, int val)
+{
+    SetDoubleValue(key, val);
+}
+
+//-----------------------------------------------------------------------------
+void Profile::SetFloatValue(const char* key, float val)
+{
+    SetDoubleValue(key, val);
+}
+
+//-----------------------------------------------------------------------------
+void Profile::SetFloatValues(const char* key, const float* vals, int num_vals)
+{
+    JSON* value = NULL;
+    int val_count = 0;
+    if (ValMap.Get(key, &value))
+    {
+        if (value->Type == JSON_Array)
+        {
+            // truncate the existing array if fewer entries provided
+            int num_existing_vals = value->GetArraySize();
+            for (int i=num_vals; i<num_existing_vals; i++)
+                value->RemoveLast();
+            
+            JSON* item = value->GetFirstItem();
+            while (item && val_count < num_vals)
+            {
+                if (item->Type == JSON_Number)
+                    item->dValue = vals[val_count];
+
+                item = value->GetNextItem(item);
+                val_count++;
+            }
+        }
+        else
+        {
+            return;  // Maybe we should change the data type?
+        }
+    }
+    else
+    {
+        value = JSON::CreateArray();
+        value->Name = key;
+
+        Values.PushBack(value);
+        ValMap.Set(key, value);
+    }
+
+    for (; val_count < num_vals; val_count++)
+        value->AddArrayNumber(vals[val_count]);
+}
+
+//-----------------------------------------------------------------------------
+void Profile::SetDoubleValue(const char* key, double val)
+{
+    JSON* value = NULL;
+    if (ValMap.Get(key, &value))
+    {
+        value->dValue = val;
+    }
+    else
+    {
+        value = JSON::CreateNumber(val);
+        value->Name = key;
+
+        Values.PushBack(value);
+        ValMap.Set(key, value);
+    }
+}
+
+//-----------------------------------------------------------------------------
+void Profile::SetDoubleValues(const char* key, const double* vals, int num_vals)
+{
+    JSON* value = NULL;
+    int val_count = 0;
+    if (ValMap.Get(key, &value))
+    {
+        if (value->Type == JSON_Array)
+        {
+            // truncate the existing array if fewer entries provided
+            int num_existing_vals = value->GetArraySize();
+            for (int i=num_vals; i<num_existing_vals; i++)
+                value->RemoveLast();
+            
+            JSON* item = value->GetFirstItem();
+            while (item && val_count < num_vals)
+            {
+                if (item->Type == JSON_Number)
+                    item->dValue = vals[val_count];
+
+                item = value->GetNextItem(item);
+                val_count++;
+            }
+        }
+        else
+        {
+            return;  // Maybe we should change the data type?
+        }
+    }
+    else
+    {
+        value = JSON::CreateArray();
+        value->Name = key;
+
+        Values.PushBack(value);
+        ValMap.Set(key, value);
+    }
+
+    for (; val_count < num_vals; val_count++)
+        value->AddArrayNumber(vals[val_count]);
+}
+
+}  // OVR
diff --git a/LibOVR/Src/OVR_Profile.h b/LibOVR/Src/OVR_Profile.h
new file mode 100644
index 0000000..e34820a
--- /dev/null
+++ b/LibOVR/Src/OVR_Profile.h
@@ -0,0 +1,203 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Profile.h
+Content     :   Structs and functions for loading and storing device profile settings
+Created     :   February 14, 2013
+Notes       :
+   Profiles are used to store per-user settings that can be transferred and used
+   across multiple applications.  For example, player IPD can be configured once 
+   and reused for a unified experience across games.  Configuration and saving of profiles
+   can be accomplished in game via the Profile API or by the official Oculus Configuration
+   Utility.
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Profile_h
+#define OVR_Profile_h
+
+#include "OVR_DeviceConstants.h"
+#include "Kernel/OVR_String.h"
+#include "Kernel/OVR_RefCount.h"
+#include "Kernel/OVR_Array.h"
+#include "Kernel/OVR_StringHash.h"
+
+namespace OVR {
+
+class Profile;
+class DeviceBase;
+class JSON;
+
+// -----------------------------------------------------------------------------
+// ***** ProfileManager
+
+// Profiles are interfaced through a ProfileManager object.  Applications should
+// create a ProfileManager each time they intend to read or write user profile data.
+// The scope of the ProfileManager object defines when disk I/O is performed.  Disk
+// reads are performed on the first profile access and disk writes are performed when
+// the ProfileManager goes out of scope.  All profile interactions between these times
+// are performed in local memory and are fast.  A typical profile interaction might
+// look like this:
+//
+// {
+//     Ptr<ProfileManager> pm      = *ProfileManager::Create();
+//     Ptr<Profile>        profile = pm->LoadProfile(Profile_RiftDK1,
+//                                                   pm->GetDefaultProfileName(Profile_RiftDK1));
+//     if (profile)
+//     {   // Retrieve the current profile settings
+//     }
+// }   // Profile will be destroyed and any disk I/O completed when going out of scope
+class ProfileManager : public RefCountBase<ProfileManager>
+{
+protected:
+    // Synchronize ProfileManager access since it may be accessed from multiple threads,
+    // as it's shared through DeviceManager.
+    Lock                ProfileLock;
+    Ptr<JSON>           ProfileCache;
+    bool                Changed;
+    String              TempBuff;
+    
+public:
+    static ProfileManager* Create();
+
+    int                 GetUserCount();
+    const char*         GetUser(unsigned int index);
+    bool                CreateUser(const char* user, const char* name);
+    bool                RemoveUser(const char* user);
+    const char*         GetDefaultUser(const DeviceBase* device);
+    bool                SetDefaultUser(const DeviceBase* device, const char* user);
+
+    virtual Profile*    CreateProfile();
+    Profile*            GetProfile(const DeviceBase* device, const char* user);
+    Profile*            GetDefaultProfile(const DeviceBase* device);
+    Profile*            GetTaggedProfile(const char** key_names, const char** keys, int num_keys);
+    bool                SetTaggedProfile(const char** key_names, const char** keys, int num_keys, Profile* profile);
+    
+    bool                GetDeviceTags(const DeviceBase* device, String& product, String& serial);
+    
+protected:
+    ProfileManager();
+    ~ProfileManager();
+    String              GetProfilePath(bool create_dir);
+    void                LoadCache(bool create);
+    void                ClearCache();
+    void                LoadV1Profiles(JSON* v1);
+    
+
+};
+
+
+//-------------------------------------------------------------------
+// ***** Profile
+
+// The base profile for all users.  This object is not created directly.
+// Instead derived device objects provide add specific device members to 
+// the base profile
+class Profile : public RefCountBase<Profile>
+{
+protected:
+    OVR::Hash<String, JSON*, String::HashFunctor>   ValMap;
+    OVR::Array<JSON*>   Values;  
+    OVR::String         TempVal;
+
+public:
+    ~Profile();
+
+    int                 GetNumValues(const char* key) const;
+    const char*         GetValue(const char* key);
+    char*               GetValue(const char* key, char* val, int val_length) const;
+    bool                GetBoolValue(const char* key, bool default_val) const;
+    int                 GetIntValue(const char* key, int default_val) const;
+    float               GetFloatValue(const char* key, float default_val) const;
+    int                 GetFloatValues(const char* key, float* values, int num_vals) const;
+    double              GetDoubleValue(const char* key, double default_val) const;
+    int                 GetDoubleValues(const char* key, double* values, int num_vals) const;
+
+    void                SetValue(const char* key, const char* val);
+    void                SetBoolValue(const char* key, bool val);
+    void                SetIntValue(const char* key, int val);
+    void                SetFloatValue(const char* key, float val);
+    void                SetFloatValues(const char* key, const float* vals, int num_vals);
+    void                SetDoubleValue(const char* key, double val);
+    void                SetDoubleValues(const char* key, const double* vals, int num_vals);
+    
+    bool Close();
+
+protected:
+    Profile() {};
+
+    
+    void                SetValue(JSON* val);
+
+   
+    static bool         LoadProfile(const DeviceBase* device,
+                                    const char* user,
+                                    Profile** profile);
+    void                CopyItems(JSON* root, String prefix);
+    
+    bool                LoadDeviceFile(unsigned int device_id, const char* serial);
+    bool                LoadDeviceProfile(const DeviceBase* device);
+
+    bool                LoadProfile(JSON* root,
+                                    const char* user,
+                                    const char* device_model,
+                                    const char* device_serial);
+
+    bool                LoadUser(JSON* root,
+                                 const char* user,
+                                 const char* device_name,
+                                 const char* device_serial);
+
+    
+    friend class ProfileManager;
+};
+
+// # defined() check for CAPI compatibility near term that re-defines these
+//   for now. To be unified.
+#if !defined(OVR_KEY_USER)
+
+#define OVR_KEY_USER                        "User"
+#define OVR_KEY_NAME                        "Name"
+#define OVR_KEY_GENDER                      "Gender"
+#define OVR_KEY_PLAYER_HEIGHT               "PlayerHeight"
+#define OVR_KEY_EYE_HEIGHT                  "EyeHeight"
+#define OVR_KEY_IPD                         "IPD"
+#define OVR_KEY_NECK_TO_EYE_DISTANCE        "NeckEyeDistance"
+#define OVR_KEY_EYE_RELIEF_DIAL             "EyeReliefDial"
+#define OVR_KEY_EYE_TO_NOSE_DISTANCE        "EyeToNoseDist"
+#define OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE   "MaxEyeToPlateDist"
+#define OVR_KEY_EYE_CUP                     "EyeCup"
+#define OVR_KEY_CUSTOM_EYE_RENDER           "CustomEyeRender"
+
+#define OVR_DEFAULT_GENDER                  "Male"
+#define OVR_DEFAULT_PLAYER_HEIGHT           1.778f
+#define OVR_DEFAULT_EYE_HEIGHT              1.675f
+#define OVR_DEFAULT_IPD                     0.064f
+#define OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL  0.09f
+#define OVR_DEFAULT_NECK_TO_EYE_VERTICAL    0.15f
+#define OVR_DEFAULT_EYE_RELIEF_DIAL         3
+
+#endif // OVR_KEY_USER
+
+String GetBaseOVRPath(bool create_dir);
+
+}
+
+#endif // OVR_Profile_h
\ No newline at end of file
diff --git a/LibOVR/Src/OVR_Recording.cpp b/LibOVR/Src/OVR_Recording.cpp
new file mode 100644
index 0000000..a2006c8
--- /dev/null
+++ b/LibOVR/Src/OVR_Recording.cpp
@@ -0,0 +1,38 @@
+/************************************************************************************
+
+Filename    :   Recording.h
+Content     :   Support for recording sensor + camera data
+Created     :   May 12, 2014
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "Kernel/OVR_Math.h"
+#include "Kernel/OVR_Array.h"
+#include "OVR_DeviceMessages.h"
+#include "OVR_Recording.h"
+
+namespace OVR { namespace Recording {
+
+// global instance that doesn't do anything
+Recorder r;
+
+}} // OVR::Recording
+
diff --git a/LibOVR/Src/OVR_Recording.h b/LibOVR/Src/OVR_Recording.h
new file mode 100644
index 0000000..fc83270
--- /dev/null
+++ b/LibOVR/Src/OVR_Recording.h
@@ -0,0 +1,83 @@
+/************************************************************************************
+
+Filename    :   Recording.h
+Content     :   Support for recording sensor + camera data
+Created     :   March 14, 2014
+Notes       : 
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_Recording_h
+#define OVR_Recording_h
+
+namespace OVR { namespace Recording {
+
+enum RecordingMode
+{
+    RecordingOff = 0x0,
+    RecordForPlayback = 0x1,
+    RecordForLogging = 0x2
+};
+
+}} // OVR::Recording
+
+#ifdef ENABLE_RECORDING
+
+#include "Recording/Recording_Recorder.h"
+
+#else
+// If Recording is not enabled, then stub it out
+
+namespace OVR { 
+    
+struct PositionCalibrationReport;
+namespace Vision {
+    class CameraIntrinsics;
+    class DistortionCoefficients;
+    class Blob;
+};
+
+namespace Recording {
+
+class Recorder
+{
+public:
+    OVR_FORCE_INLINE void RecordCameraParams(const Vision::CameraIntrinsics&, 
+                                             const Vision::DistortionCoefficients&) { }
+    OVR_FORCE_INLINE void RecordLedPositions(const Array<PositionCalibrationReport>&) { }
+    OVR_FORCE_INLINE void RecordUserParams(const Vector3f&, float) { }
+    OVR_FORCE_INLINE void RecordDeviceIfcVersion(UByte) { }
+    OVR_FORCE_INLINE void RecordMessage(const Message&) { }
+    OVR_FORCE_INLINE void RecordCameraFrameUsed(UInt32) { }
+    OVR_FORCE_INLINE void RecordVisionSuccess(UInt32) { }
+    template<typename T> OVR_FORCE_INLINE void LogData(const char*, const T&) { }
+    OVR_FORCE_INLINE void SetRecordingMode(RecordingMode) { }
+    OVR_FORCE_INLINE RecordingMode GetRecordingMode() { return RecordingOff; }
+};
+
+extern Recorder r;
+
+OVR_FORCE_INLINE Recorder& GetRecorder() { return r; }
+    
+}} // namespace OVR::Recording
+
+#endif // ENABLE_RECORDING
+
+#endif // OVR_Recording_h
\ No newline at end of file
diff --git a/LibOVR/Src/OVR_Sensor2Impl.cpp b/LibOVR/Src/OVR_Sensor2Impl.cpp
new file mode 100644
index 0000000..95d486c
--- /dev/null
+++ b/LibOVR/Src/OVR_Sensor2Impl.cpp
@@ -0,0 +1,1124 @@
+/************************************************************************************
+
+Filename    :   OVR_Sensor2Impl.cpp
+Content     :   DK2 sensor device specific implementation.
+Created     :   January 21, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_Sensor2Impl.h"
+#include "OVR_SensorImpl_Common.h"
+#include "OVR_Sensor2ImplUtil.h"
+#include "Kernel/OVR_Alg.h"
+
+//extern FILE *SF_LOG_fp;
+
+namespace OVR {
+
+//-------------------------------------------------------------------------------------
+// ***** Oculus Sensor2-specific packet data structures
+
+enum {    
+    Sensor2_VendorId            = Oculus_VendorId,
+    Sensor2_ProductId           = 0x0021,
+
+    Sensor2_BootLoader          = 0x1001,
+
+    Sensor2_DefaultReportRate   = 1000, // Hz
+};
+
+
+// Messages we care for
+enum Tracker2MessageType
+{
+    Tracker2Message_None              = 0,
+    Tracker2Message_Sensors           = 11,
+    Tracker2Message_Unknown           = 0x100,
+    Tracker2Message_SizeError         = 0x101,
+};
+
+
+struct Tracker2Sensors
+{
+    UInt16	LastCommandID;
+    UByte	NumSamples;
+    UInt16	RunningSampleCount;				// Named 'SampleCount' in the firmware docs.
+    SInt16	Temperature;
+	UInt32	SampleTimestamp;
+    TrackerSample Samples[2];
+    SInt16	MagX, MagY, MagZ;
+    UInt16	FrameCount;
+	UInt32	FrameTimestamp;
+    UByte	FrameID;
+    UByte	CameraPattern;
+    UInt16	CameraFrameCount;				// Named 'CameraCount' in the firmware docs.
+	UInt32	CameraTimestamp;
+
+    Tracker2MessageType Decode(const UByte* buffer, int size)
+    {
+        if (size < 64)
+            return Tracker2Message_SizeError;
+
+		LastCommandID		= DecodeUInt16(buffer + 1);
+        NumSamples			= buffer[3];
+        RunningSampleCount	= DecodeUInt16(buffer + 4);
+        Temperature			= DecodeSInt16(buffer + 6);
+        SampleTimestamp		= DecodeUInt32(buffer + 8);
+        
+		// Only unpack as many samples as there actually are.
+        UByte iterationCount = (NumSamples > 1) ? 2 : NumSamples;
+
+        for (UByte i = 0; i < iterationCount; i++)
+        {
+			UnpackSensor(buffer + 12 + 16 * i, &Samples[i].AccelX, &Samples[i].AccelY, &Samples[i].AccelZ);
+            UnpackSensor(buffer + 20 + 16 * i, &Samples[i].GyroX,  &Samples[i].GyroY,  &Samples[i].GyroZ);
+		}
+
+        MagX = DecodeSInt16(buffer + 44);
+        MagY = DecodeSInt16(buffer + 46);
+        MagZ = DecodeSInt16(buffer + 48);
+
+		FrameCount = DecodeUInt16(buffer + 50);
+
+		FrameTimestamp		= DecodeUInt32(buffer + 52);
+		FrameID				= buffer[56];
+		CameraPattern		= buffer[57];
+		CameraFrameCount	= DecodeUInt16(buffer + 58);
+		CameraTimestamp		= DecodeUInt32(buffer + 60);
+        
+        return Tracker2Message_Sensors;
+    }
+};
+
+struct Tracker2Message
+{
+    Tracker2MessageType Type;
+    Tracker2Sensors     Sensors;
+};
+
+// Sensor reports data in the following coordinate system:
+// Accelerometer: 10^-4 m/s^2; X forward, Y right, Z Down.
+// Gyro:          10^-4 rad/s; X positive roll right, Y positive pitch up; Z positive yaw right.
+
+
+// We need to convert it to the following RHS coordinate system:
+// X right, Y Up, Z Back (out of screen)
+//
+Vector3f AccelFromBodyFrameUpdate(const Tracker2Sensors& update, UByte sampleNumber)
+{
+    const TrackerSample& sample = update.Samples[sampleNumber];
+    float                ax = (float)sample.AccelX;
+    float                ay = (float)sample.AccelY;
+    float                az = (float)sample.AccelZ;
+
+    return Vector3f(ax, ay, az) * 0.0001f;
+}
+
+
+Vector3f MagFromBodyFrameUpdate(const Tracker2Sensors& update)
+{   
+    return Vector3f( (float)update.MagX, (float)update.MagY, (float)update.MagZ) * 0.0001f;
+}
+
+Vector3f EulerFromBodyFrameUpdate(const Tracker2Sensors& update, UByte sampleNumber)
+{
+    const TrackerSample& sample = update.Samples[sampleNumber];
+    float                gx = (float)sample.GyroX;
+    float                gy = (float)sample.GyroY;
+    float                gz = (float)sample.GyroZ;
+
+    return Vector3f(gx, gy, gz) * 0.0001f;
+}
+
+bool  Sensor2DeviceImpl::decodeTracker2Message(Tracker2Message* message, UByte* buffer, int size)
+{
+    memset(message, 0, sizeof(Tracker2Message));
+
+    if (size < 4)
+    {
+        message->Type = Tracker2Message_SizeError;
+        return false;
+    }
+
+    switch (buffer[0])
+    {
+    case Tracker2Message_Sensors:
+        message->Type = message->Sensors.Decode(buffer, size);
+        break;
+
+    default:
+        message->Type = Tracker2Message_Unknown;
+        break;
+    }
+
+    return (message->Type < Tracker2Message_Unknown) && (message->Type != Tracker2Message_None);
+}
+
+//-------------------------------------------------------------------------------------
+// ***** Sensor2Device
+
+Sensor2DeviceImpl::Sensor2DeviceImpl(SensorDeviceCreateDesc* createDesc)
+    :   SensorDeviceImpl(createDesc),
+        LastNumSamples(0),
+        LastRunningSampleCount(0),
+        FullCameraFrameCount(0),
+        LastCameraTime("C"),
+        LastFrameTime("F"),
+        LastSensorTime("S"),
+        LastFrameTimestamp(0)
+{
+    // 15 samples ok in min-window for DK2 since it uses microsecond clock.
+    TimeFilter = SensorTimeFilter(SensorTimeFilter::Settings(15));
+
+    pCalibration = new SensorCalibration(this);
+}
+
+Sensor2DeviceImpl::~Sensor2DeviceImpl()
+{
+    delete pCalibration;
+}
+
+void Sensor2DeviceImpl::openDevice()
+{
+
+    // Read the currently configured range from sensor.
+    SensorRangeImpl sr(SensorRange(), 0);
+
+    if (GetInternalDevice()->GetFeatureReport(sr.Buffer, SensorRangeImpl::PacketSize))
+    {
+        sr.Unpack();
+        sr.GetSensorRange(&CurrentRange);
+    }
+
+    // Read the currently configured calibration from sensor.
+    SensorFactoryCalibrationImpl sc;
+    if (GetInternalDevice()->GetFeatureReport(sc.Buffer, SensorFactoryCalibrationImpl::PacketSize))
+    {
+        sc.Unpack();
+        AccelCalibrationOffset = sc.AccelOffset;
+        GyroCalibrationOffset  = sc.GyroOffset;
+        AccelCalibrationMatrix = sc.AccelMatrix;
+        GyroCalibrationMatrix  = sc.GyroMatrix;
+        CalibrationTemperature = sc.Temperature;
+    }
+
+    // If the sensor has "DisplayInfo" data, use HMD coordinate frame by default.
+    SensorDisplayInfoImpl displayInfo;
+    if (GetInternalDevice()->GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize))
+    {
+        displayInfo.Unpack();
+        Coordinates = (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) ?
+                      Coord_HMD : Coord_Sensor;
+    }
+	Coordinates = Coord_HMD; // TODO temporary to force it behave
+
+    // Read/Apply sensor config.
+    setCoordinateFrame(Coordinates);
+    setReportRate(Sensor2_DefaultReportRate);
+    setOnboardCalibrationEnabled(false);
+
+    // Must send DK2 keep-alive. Set Keep-alive at 10 seconds.
+    KeepAliveMuxReport keepAlive;
+    keepAlive.CommandId = 0;
+    keepAlive.INReport = 11;
+    keepAlive.Interval = 10 * 1000;
+
+    // Device creation is done from background thread so we don't need to add this to the command queue.
+    KeepAliveMuxImpl keepAliveImpl(keepAlive);
+    GetInternalDevice()->SetFeatureReport(keepAliveImpl.Buffer, KeepAliveMuxImpl::PacketSize);
+
+    // Read the temperature  data from the device
+    pCalibration->Initialize();
+}
+
+bool Sensor2DeviceImpl::SetTrackingReport(const TrackingReport& data)
+{ 
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setTrackingReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setTrackingReport(const TrackingReport& data)
+{
+    TrackingImpl ci(data);
+    return GetInternalDevice()->SetFeatureReport(ci.Buffer, TrackingImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::GetTrackingReport(TrackingReport* data)
+{
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getTrackingReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::getTrackingReport(TrackingReport* data)
+{
+    TrackingImpl ci;
+    if (GetInternalDevice()->GetFeatureReport(ci.Buffer, TrackingImpl::PacketSize))
+    {
+        ci.Unpack();
+        *data = ci.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::SetDisplayReport(const DisplayReport& data)
+{ 
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setDisplayReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setDisplayReport(const DisplayReport& data)
+{
+    DisplayImpl di(data);
+    return GetInternalDevice()->SetFeatureReport(di.Buffer, DisplayImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::GetDisplayReport(DisplayReport* data)
+{
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getDisplayReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::getDisplayReport(DisplayReport* data)
+{
+    DisplayImpl di;
+    if (GetInternalDevice()->GetFeatureReport(di.Buffer, DisplayImpl::PacketSize))
+    {
+        di.Unpack();
+        *data = di.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::SetMagCalibrationReport(const MagCalibrationReport& data)
+{ 
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setMagCalibrationReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setMagCalibrationReport(const MagCalibrationReport& data)
+{
+    MagCalibrationImpl mci(data);
+    return GetInternalDevice()->SetFeatureReport(mci.Buffer, MagCalibrationImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::GetMagCalibrationReport(MagCalibrationReport* data)
+{
+    // direct call if we are already on the device manager thread
+    if (GetCurrentThreadId() == GetManagerImpl()->GetThreadId())
+    {
+        return getMagCalibrationReport(data);
+    }
+
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getMagCalibrationReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::getMagCalibrationReport(MagCalibrationReport* data)
+{
+    MagCalibrationImpl mci;
+    if (GetInternalDevice()->GetFeatureReport(mci.Buffer, MagCalibrationImpl::PacketSize))
+    {
+        mci.Unpack();
+        *data = mci.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::SetPositionCalibrationReport(const PositionCalibrationReport& data)
+{ 
+    bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setPositionCalibrationReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setPositionCalibrationReport(const PositionCalibrationReport& data)
+{
+	UByte version = GetDeviceInterfaceVersion();
+	if (version < 5)
+	{
+		PositionCalibrationImpl_Pre5 pci(data);
+		return GetInternalDevice()->SetFeatureReport(pci.Buffer, PositionCalibrationImpl_Pre5::PacketSize);
+	}
+	
+	PositionCalibrationImpl pci(data);
+    return GetInternalDevice()->SetFeatureReport(pci.Buffer, PositionCalibrationImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::getPositionCalibrationReport(PositionCalibrationReport* data)
+{
+	UByte version = GetDeviceInterfaceVersion();
+	if (version < 5)
+	{
+		PositionCalibrationImpl_Pre5 pci;
+		if (GetInternalDevice()->GetFeatureReport(pci.Buffer, PositionCalibrationImpl_Pre5::PacketSize))
+		{
+			pci.Unpack();
+			*data = pci.Settings;
+			return true;
+		}
+
+		return false;
+	}
+
+    PositionCalibrationImpl pci;
+    if (GetInternalDevice()->GetFeatureReport(pci.Buffer, PositionCalibrationImpl::PacketSize))
+    {
+        pci.Unpack();
+        *data = pci.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::GetAllPositionCalibrationReports(Array<PositionCalibrationReport>* data)
+{
+    bool result;
+    if (!GetManagerImpl()->GetThreadQueue()->
+        PushCallAndWaitResult(this, &Sensor2DeviceImpl::getAllPositionCalibrationReports, &result, data))
+    {
+        return false;
+    }
+
+    return result;
+}
+
+bool Sensor2DeviceImpl::getAllPositionCalibrationReports(Array<PositionCalibrationReport>* data)
+{
+    PositionCalibrationReport pc;
+    bool result = getPositionCalibrationReport(&pc);
+    if (!result)
+        return false;
+
+    int positions = pc.NumPositions;
+    data->Clear();
+    data->Resize(positions);
+
+    for (int i = 0; i < positions; i++)
+    {
+        result = getPositionCalibrationReport(&pc);
+        if (!result)
+            return false;
+        OVR_ASSERT(pc.NumPositions == positions);
+
+        (*data)[pc.PositionIndex] = pc;
+        // IMU should be the last one
+        OVR_ASSERT(pc.PositionType == (pc.PositionIndex == positions - 1) ? 
+            PositionCalibrationReport::PositionType_IMU : PositionCalibrationReport::PositionType_LED);
+    }
+    return true;
+}
+
+bool Sensor2DeviceImpl::SetCustomPatternReport(const CustomPatternReport& data)
+{ 
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setCustomPatternReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setCustomPatternReport(const CustomPatternReport& data)
+{
+    CustomPatternImpl cpi(data);
+    return GetInternalDevice()->SetFeatureReport(cpi.Buffer, CustomPatternImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::GetCustomPatternReport(CustomPatternReport* data)
+{
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getCustomPatternReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::getCustomPatternReport(CustomPatternReport* data)
+{
+    CustomPatternImpl cpi;
+    if (GetInternalDevice()->GetFeatureReport(cpi.Buffer, CustomPatternImpl::PacketSize))
+    {
+        cpi.Unpack();
+        *data = cpi.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::SetManufacturingReport(const ManufacturingReport& data)
+{ 
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setManufacturingReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setManufacturingReport(const ManufacturingReport& data)
+{
+    ManufacturingImpl mi(data);
+    return GetInternalDevice()->SetFeatureReport(mi.Buffer, ManufacturingImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::GetManufacturingReport(ManufacturingReport* data)
+{
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getManufacturingReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::getManufacturingReport(ManufacturingReport* data)
+{
+    ManufacturingImpl mi;
+    if (GetInternalDevice()->GetFeatureReport(mi.Buffer, ManufacturingImpl::PacketSize))
+    {
+        mi.Unpack();
+        *data = mi.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::SetLensDistortionReport(const LensDistortionReport& data)
+{ 
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setLensDistortionReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setLensDistortionReport(const LensDistortionReport& data)
+{
+    LensDistortionImpl ui(data);
+    return GetInternalDevice()->SetFeatureReport(ui.Buffer, LensDistortionImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::GetLensDistortionReport(LensDistortionReport* data)
+{
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getLensDistortionReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::getLensDistortionReport(LensDistortionReport* data)
+{
+    LensDistortionImpl ui;
+    if (GetInternalDevice()->GetFeatureReport(ui.Buffer, LensDistortionImpl::PacketSize))
+    {
+        ui.Unpack();
+        *data = ui.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::SetUUIDReport(const UUIDReport& data)
+{ 
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setUUIDReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setUUIDReport(const UUIDReport& data)
+{
+    UUIDImpl ui(data);
+    return GetInternalDevice()->SetFeatureReport(ui.Buffer, UUIDImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::GetUUIDReport(UUIDReport* data)
+{
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getUUIDReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::getUUIDReport(UUIDReport* data)
+{
+    UUIDImpl ui;
+    if (GetInternalDevice()->GetFeatureReport(ui.Buffer, UUIDImpl::PacketSize))
+    {
+        ui.Unpack();
+        *data = ui.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::SetKeepAliveMuxReport(const KeepAliveMuxReport& data)
+{ 
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setKeepAliveMuxReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setKeepAliveMuxReport(const KeepAliveMuxReport& data)
+{
+    KeepAliveMuxImpl kami(data);
+    return GetInternalDevice()->SetFeatureReport(kami.Buffer, KeepAliveMuxImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::GetKeepAliveMuxReport(KeepAliveMuxReport* data)
+{
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getKeepAliveMuxReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::getKeepAliveMuxReport(KeepAliveMuxReport* data)
+{
+    KeepAliveMuxImpl kami;
+    if (GetInternalDevice()->GetFeatureReport(kami.Buffer, KeepAliveMuxImpl::PacketSize))
+    {
+        kami.Unpack();
+        *data = kami.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::SetTemperatureReport(const TemperatureReport& data)
+{
+    // direct call if we are already on the device manager thread
+    if (GetCurrentThreadId() == GetManagerImpl()->GetThreadId())
+    {
+        return setTemperatureReport(data);
+    }
+
+    bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setTemperatureReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::setTemperatureReport(const TemperatureReport& data)
+{
+    TemperatureImpl ti(data);
+    return GetInternalDevice()->SetFeatureReport(ti.Buffer, TemperatureImpl::PacketSize);
+}
+
+bool Sensor2DeviceImpl::getTemperatureReport(TemperatureReport* data)
+{
+    TemperatureImpl ti;
+    if (GetInternalDevice()->GetFeatureReport(ti.Buffer, TemperatureImpl::PacketSize))
+    {
+        ti.Unpack();
+        *data = ti.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+bool Sensor2DeviceImpl::GetAllTemperatureReports(Array<Array<TemperatureReport> >* data)
+{
+    // direct call if we are already on the device manager thread
+    if (GetCurrentThreadId() == GetManagerImpl()->GetThreadId())
+    {
+        return getAllTemperatureReports(data);
+    }
+
+    bool result;
+    if (!GetManagerImpl()->GetThreadQueue()->
+        PushCallAndWaitResult(this, &Sensor2DeviceImpl::getAllTemperatureReports, &result, data))
+    {
+        return false;
+    }
+
+    return result;
+}
+
+bool Sensor2DeviceImpl::getAllTemperatureReports(Array<Array<TemperatureReport> >* data)
+{
+    TemperatureReport t;
+    bool result = getTemperatureReport(&t);
+    if (!result)
+        return false;
+
+    int bins = t.NumBins, samples = t.NumSamples;
+    data->Clear();
+    data->Resize(bins);
+    for (int i = 0; i < bins; i++)
+        (*data)[i].Resize(samples);
+
+    for (int i = 0; i < bins; i++)
+        for (int j = 0; j < samples; j++)
+        {
+            result = getTemperatureReport(&t);
+            if (!result)
+                return false;
+            OVR_ASSERT(t.NumBins == bins && t.NumSamples == samples);
+
+            (*data)[t.Bin][t.Sample] = t;
+        }
+    return true;
+}
+
+bool Sensor2DeviceImpl::GetGyroOffsetReport(GyroOffsetReport* data)
+{
+    // direct call if we are already on the device manager thread
+    if (GetCurrentThreadId() == GetManagerImpl()->GetThreadId())
+    {
+        return getGyroOffsetReport(data);
+    }
+
+    bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getGyroOffsetReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool Sensor2DeviceImpl::getGyroOffsetReport(GyroOffsetReport* data)
+{
+    GyroOffsetImpl goi;
+    if (GetInternalDevice()->GetFeatureReport(goi.Buffer, GyroOffsetImpl::PacketSize))
+    {
+        goi.Unpack();
+        *data = goi.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+void Sensor2DeviceImpl::onTrackerMessage(Tracker2Message* message)
+{
+    if (message->Type != Tracker2Message_Sensors)
+        return;
+    
+    const float     sampleIntervalTimeUnit   = (1.0f / 1000.f);
+    double          scaledSampleIntervalTimeUnit  = sampleIntervalTimeUnit;
+    Tracker2Sensors& s = message->Sensors;
+    
+    double       absoluteTimeSeconds = 0.0;
+
+    if (SequenceValid)
+    {
+        UInt32 runningSampleCountDelta;
+
+        if (s.RunningSampleCount < LastRunningSampleCount)
+        {
+            // The running sample count on the device rolled around the 16 bit counter
+            // (expect to happen about once per minute), so RunningSampleCount 
+            // needs a high word increment.
+            runningSampleCountDelta = ((((int)s.RunningSampleCount) + 0x10000) - (int)LastRunningSampleCount);
+        }
+        else
+        {
+            runningSampleCountDelta = (s.RunningSampleCount - LastRunningSampleCount);
+        }
+
+        absoluteTimeSeconds = LastSensorTime.TimeSeconds;
+        scaledSampleIntervalTimeUnit = TimeFilter.ScaleTimeUnit(sampleIntervalTimeUnit);
+ 
+        // If we missed a small number of samples, replicate the last sample.
+        if ((runningSampleCountDelta > LastNumSamples) && (runningSampleCountDelta <= 254))
+        {
+            if (HandlerRef.HasHandlers())
+            {
+                MessageBodyFrame sensors(this);
+
+                sensors.AbsoluteTimeSeconds = absoluteTimeSeconds - s.NumSamples * scaledSampleIntervalTimeUnit;
+                sensors.TimeDelta     = (float) ((runningSampleCountDelta - LastNumSamples) * scaledSampleIntervalTimeUnit);
+                sensors.Acceleration  = LastAcceleration;
+                sensors.RotationRate  = LastRotationRate;
+                sensors.MagneticField = LastMagneticField;
+                sensors.Temperature   = LastTemperature;
+
+                pCalibration->Apply(sensors);
+                HandlerRef.Call(sensors);
+            }
+        }
+    }
+    else
+    {
+        LastAcceleration = Vector3f(0);
+        LastRotationRate = Vector3f(0);
+        LastMagneticField= Vector3f(0);
+        LastTemperature  = 0;
+        SequenceValid    = true;
+    }
+
+    LastNumSamples = s.NumSamples;
+    LastRunningSampleCount = s.RunningSampleCount;
+
+    if (HandlerRef.HasHandlers())
+    {
+        MessageBodyFrame sensors(this);        
+        UByte            iterations = s.NumSamples;
+
+        if (s.NumSamples > 2)
+        {
+            iterations        = 2;
+            sensors.TimeDelta = (float) ((s.NumSamples - 1) * scaledSampleIntervalTimeUnit);
+        }
+        else
+        {
+            sensors.TimeDelta = (float) scaledSampleIntervalTimeUnit;
+        }
+
+        for (UByte i = 0; i < iterations; i++)
+        {            
+            sensors.AbsoluteTimeSeconds = absoluteTimeSeconds - ( iterations - 1 - i ) * scaledSampleIntervalTimeUnit;
+            sensors.Acceleration = AccelFromBodyFrameUpdate(s, i);
+            sensors.RotationRate = EulerFromBodyFrameUpdate(s, i);
+            sensors.MagneticField= MagFromBodyFrameUpdate(s);
+            sensors.Temperature  = s.Temperature * 0.01f;
+
+            pCalibration->Apply(sensors);
+            HandlerRef.Call(sensors);
+
+            // TimeDelta for the last two sample is always fixed.
+            sensors.TimeDelta = (float) scaledSampleIntervalTimeUnit;
+        }
+
+        // Send pixel read only when frame timestamp changes.
+        if (LastFrameTimestamp != s.FrameTimestamp)
+        {
+            MessagePixelRead pixelRead(this);
+            // Prepare message for pixel read
+            pixelRead.PixelReadValue    = s.FrameID;
+            pixelRead.RawFrameTime      = s.FrameTimestamp;
+            pixelRead.RawSensorTime     = s.SampleTimestamp;
+            pixelRead.SensorTimeSeconds = LastSensorTime.TimeSeconds;
+            pixelRead.FrameTimeSeconds  = LastFrameTime.TimeSeconds;
+
+            HandlerRef.Call(pixelRead);
+            LastFrameTimestamp = s.FrameTimestamp;
+        }
+
+        UInt16 lowFrameCount = (UInt16) FullCameraFrameCount;
+        // Send message only when frame counter changes
+        if (lowFrameCount != s.CameraFrameCount)
+        {
+            // check for the rollover in the counter
+            if (s.CameraFrameCount < lowFrameCount)
+                FullCameraFrameCount += 0x10000;
+            // update the low bits
+            FullCameraFrameCount = (FullCameraFrameCount & ~0xFFFF) | s.CameraFrameCount;
+
+            MessageExposureFrame vision(this);
+            vision.CameraPattern = s.CameraPattern;
+            vision.CameraFrameCount = FullCameraFrameCount;
+            vision.CameraTimeSeconds = LastCameraTime.TimeSeconds;
+
+            HandlerRef.Call(vision);
+        }
+
+        LastAcceleration = sensors.Acceleration;
+        LastRotationRate = sensors.RotationRate;
+        LastMagneticField= sensors.MagneticField;
+        LastTemperature  = sensors.Temperature;
+
+        //LastPixelRead = pixelRead.PixelReadValue;
+        //LastPixelReadTimeStamp = LastFrameTime;
+    }
+    else
+    {
+        if (s.NumSamples != 0)
+		{
+			UByte i = (s.NumSamples > 1) ? 1 : 0;
+			LastAcceleration  = AccelFromBodyFrameUpdate(s, i);
+			LastRotationRate  = EulerFromBodyFrameUpdate(s, i);
+			LastMagneticField = MagFromBodyFrameUpdate(s);
+			LastTemperature   = s.Temperature * 0.01f;
+		}
+    }
+}
+
+// Helper function to handle wrap-around of timestamps from Tracker2Message and convert them
+// to system time.
+//   - Any timestamps that didn't increment keep their old system time.
+//   - This is a bit tricky since we don't know which one of timestamps has most recent time.
+//   - The first timestamp must be the IMU one; we assume that others can't be too much ahead of it
+
+void UpdateDK2Timestamps(SensorTimeFilter& tf,
+                         SensorTimestampMapping** timestamps, UInt32 *rawValues, int count)
+{
+    int     updateIndices[4];
+    int     updateCount = 0;
+    int     i;
+    double  now = Timer::GetSeconds();
+
+    OVR_ASSERT(count <= sizeof(updateIndices)/sizeof(int));
+
+    // Update timestamp wrapping for any values that changed.
+    for (i = 0; i < count; i++)
+    {        
+        UInt32 lowMks = (UInt32)timestamps[i]->TimestampMks;  // Low 32-bits are raw old timestamp.
+
+        if (rawValues[i] != lowMks)
+        {
+            if (i == 0)
+            {
+                // Only check for rollover in the IMU timestamp
+                if (rawValues[i] < lowMks)
+                {
+                    LogText("Timestamp %d rollover, was: %u, now: %u\n", i, lowMks, rawValues[i]);
+                    timestamps[i]->TimestampMks += 0x100000000;
+                }
+                // Update the low bits
+                timestamps[i]->TimestampMks = (timestamps[i]->TimestampMks & 0xFFFFFFFF00000000) | rawValues[i];
+            }
+            else
+            {
+                // Take the high bits from the main timestamp first (not a typo in the first argument!)
+                timestamps[i]->TimestampMks = 
+                    (timestamps[0]->TimestampMks & 0xFFFFFFFF00000000) | rawValues[i];
+                // Now force it into the reasonable range around the expanded main timestamp
+                if (timestamps[i]->TimestampMks > timestamps[0]->TimestampMks + 0x1000000)
+                    timestamps[i]->TimestampMks -= 0x100000000;
+                else if (timestamps[i]->TimestampMks + 0x100000000 < timestamps[0]->TimestampMks + 0x1000000)
+                    timestamps[i]->TimestampMks += 0x100000000;
+            }
+
+            updateIndices[updateCount] = i;
+            updateCount++;
+        }
+    }
+
+
+    // TBD: Simplify. Update indices should no longer be needed with new TimeFilter accepting
+    //      previous values.
+    // We might want to have multi-element checking time roll-over.
+
+    static const double mksToSec = 1.0 / 1000000.0;
+
+    for (int i = 0; i < updateCount; i++)
+    {
+        SensorTimestampMapping& ts  = *timestamps[updateIndices[i]];
+
+        ts.TimeSeconds = tf.SampleToSystemTime(((double)ts.TimestampMks) * mksToSec,
+                                               now, ts.TimeSeconds, ts.DebugTag);
+    }
+}
+
+
+void Sensor2DeviceImpl::OnInputReport(UByte* pData, UInt32 length)
+{
+	bool processed = false;
+    if (!processed)
+    {
+		Tracker2Message message;
+        if (decodeTracker2Message(&message, pData, length))
+        {
+            processed = true;
+
+            // Process microsecond timestamps from DK2 tracker.
+            // Mapped and raw values must correspond to one another in each array.
+            // IMU timestamp must be the first one!
+            SensorTimestampMapping* tsMaps[3] =
+            {                
+                &LastSensorTime,
+                &LastCameraTime,
+                &LastFrameTime
+            };
+            UInt32 tsRawMks[3] =
+            {                
+                message.Sensors.SampleTimestamp,
+                message.Sensors.CameraTimestamp,
+                message.Sensors.FrameTimestamp
+            };
+            // Handle wrap-around and convert samples to system time for any samples that changed.
+            UpdateDK2Timestamps(TimeFilter, tsMaps, tsRawMks, sizeof(tsRawMks)/sizeof(tsRawMks[0]));            
+
+            onTrackerMessage(&message);
+
+            /*
+            if (SF_LOG_fp)
+            {
+                static UInt32 lastFrameTs  = 0;
+                static UInt32 lastCameraTs = 0;
+                
+                if ((lastFrameTs != message.Sensors.FrameTimestamp) ||
+                    (lastCameraTs = message.Sensors.CameraTimestamp))
+                    fprintf(SF_LOG_fp, "msg cameraTs: 0x%X frameTs: 0x%X sensorTs: 0x%X\n",
+                            message.Sensors.CameraTimestamp, message.Sensors.FrameTimestamp,
+                            message.Sensors.SampleTimestamp);
+
+                lastFrameTs  = message.Sensors.FrameTimestamp;
+                lastCameraTs = message.Sensors.CameraTimestamp;
+            }
+            */            
+
+#if 0
+            // Checks for DK2 firmware bug.
+            static unsigned SLastSampleTime = 0;
+            if ((SLastSampleTime >  message.Sensors.SampleTimestamp) && message.Sensors.SampleTimestamp > 1000000 )
+            {
+                fprintf(SF_LOG_fp, "*** Sample Timestamp Wrap! ***\n");
+                OVR_ASSERT (SLastSampleTime <= message.Sensors.SampleTimestamp);
+            }            
+            SLastSampleTime = message.Sensors.SampleTimestamp;
+
+            static unsigned SLastCameraTime = 0;
+            if ((SLastCameraTime > message.Sensors.CameraTimestamp) && message.Sensors.CameraTimestamp > 1000000 )
+            {
+                fprintf(SF_LOG_fp, "*** Camera Timestamp Wrap! ***\n");
+                OVR_ASSERT (SLastCameraTime <= message.Sensors.CameraTimestamp);
+            }            
+            SLastCameraTime = message.Sensors.CameraTimestamp;
+
+            static unsigned SLastFrameTime = 0;
+            if ((SLastFrameTime > message.Sensors.FrameTimestamp) && message.Sensors.FrameTimestamp > 1000000 )
+            {
+                fprintf(SF_LOG_fp, "*** Frame Timestamp Wrap! ***\n");
+                OVR_ASSERT (SLastFrameTime <= message.Sensors.FrameTimestamp);
+            }                        
+            SLastFrameTime = message.Sensors.FrameTimestamp;
+#endif            
+        }       
+    }
+}
+
+double Sensor2DeviceImpl::OnTicks(double tickSeconds)
+{
+
+    if (tickSeconds >= NextKeepAliveTickSeconds)
+    {
+        // Must send DK2 keep-alive. Set Keep-alive at 10 seconds.
+        KeepAliveMuxReport keepAlive;
+        keepAlive.CommandId = 0;
+        keepAlive.INReport = 11;
+        keepAlive.Interval = 10 * 1000;
+
+        // Device creation is done from background thread so we don't need to add this to the command queue.
+        KeepAliveMuxImpl keepAliveImpl(keepAlive);
+        GetInternalDevice()->SetFeatureReport(keepAliveImpl.Buffer, KeepAliveMuxImpl::PacketSize);
+
+		// Emit keep-alive every few seconds.
+        double keepAliveDelta = 3.0;        // Use 3-second interval.
+        NextKeepAliveTickSeconds = tickSeconds + keepAliveDelta;
+    }
+    return NextKeepAliveTickSeconds - tickSeconds;
+}
+
+/*
+// TBD: don't report calibration for now, until we figure out the logic between camera and mag yaw correction
+bool Sensor2DeviceImpl::IsMagCalibrated()
+{
+    return pCalibration->IsMagCalibrated();
+}
+*/
+
+} // namespace OVR
diff --git a/LibOVR/Src/OVR_Sensor2Impl.h b/LibOVR/Src/OVR_Sensor2Impl.h
new file mode 100644
index 0000000..4555eed
--- /dev/null
+++ b/LibOVR/Src/OVR_Sensor2Impl.h
@@ -0,0 +1,153 @@
+/************************************************************************************
+
+Filename    :   OVR_Sensor2Impl.h
+Content     :   DK2 sensor device specific implementation.
+Created     :   January 21, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Sensor2Impl_h
+#define OVR_Sensor2Impl_h
+
+#include "OVR_SensorImpl.h"
+#include "OVR_SensorCalibration.h"
+
+namespace OVR {
+    
+struct Tracker2Message;
+
+//-------------------------------------------------------------------------------------
+// Used to convert DK2 Mks timestamps to system TimeSeconds
+struct SensorTimestampMapping
+{        
+    UInt64      TimestampMks;
+    double      TimeSeconds;
+    const char* DebugTag;
+
+    SensorTimestampMapping(const char* debugTag)
+        : TimestampMks(0), TimeSeconds(0.0), DebugTag(debugTag) { }
+};
+
+//-------------------------------------------------------------------------------------
+// ***** OVR::Sensor2DeviceImpl
+
+// Oculus Sensor2 interface.
+class Sensor2DeviceImpl : public SensorDeviceImpl
+{
+public:
+     Sensor2DeviceImpl(SensorDeviceCreateDesc* createDesc);
+    ~Sensor2DeviceImpl();
+
+    // HIDDevice::Notifier interface.
+    virtual void        OnInputReport(UByte* pData, UInt32 length);
+    virtual double      OnTicks(double tickSeconds);        
+
+    // Get/set feature reports added for DK2. See 'DK2 Firmware Specification' document details.
+    virtual bool        SetTrackingReport(const TrackingReport& data);
+	virtual bool        GetTrackingReport(TrackingReport* data);
+
+    virtual bool        SetDisplayReport(const DisplayReport& data);
+	virtual bool		GetDisplayReport(DisplayReport* data);
+
+    virtual bool		SetMagCalibrationReport(const MagCalibrationReport& data);
+	virtual bool		GetMagCalibrationReport(MagCalibrationReport* data);
+
+    virtual bool		SetPositionCalibrationReport(const PositionCalibrationReport& data);
+	virtual bool        GetAllPositionCalibrationReports(Array<PositionCalibrationReport>* data);
+
+    virtual bool		SetCustomPatternReport(const CustomPatternReport& data);
+	virtual bool		GetCustomPatternReport(CustomPatternReport* data);
+
+    virtual bool		SetKeepAliveMuxReport(const KeepAliveMuxReport& data);
+	virtual bool		GetKeepAliveMuxReport(KeepAliveMuxReport* data);
+
+    virtual bool		SetManufacturingReport(const ManufacturingReport& data);
+	virtual bool		GetManufacturingReport(ManufacturingReport* data);
+
+    virtual bool		SetUUIDReport(const UUIDReport& data);
+    virtual bool		GetUUIDReport(UUIDReport* data);
+
+    virtual bool		SetTemperatureReport(const TemperatureReport& data);
+    virtual bool        GetAllTemperatureReports(Array<Array<TemperatureReport> >*);
+
+    virtual bool        GetGyroOffsetReport(GyroOffsetReport* data);
+
+    virtual bool		SetLensDistortionReport(const LensDistortionReport& data);
+	virtual bool		GetLensDistortionReport(LensDistortionReport* data);
+
+protected:
+    virtual void        openDevice();
+
+    bool                decodeTracker2Message(Tracker2Message* message, UByte* buffer, int size);
+
+    bool	            setTrackingReport(const TrackingReport& data);
+    bool                getTrackingReport(TrackingReport* data);
+
+    bool	            setDisplayReport(const DisplayReport& data);
+    bool                getDisplayReport(DisplayReport* data);
+
+    bool	            setMagCalibrationReport(const MagCalibrationReport& data);
+    bool                getMagCalibrationReport(MagCalibrationReport* data);
+
+    bool	            setPositionCalibrationReport(const PositionCalibrationReport& data);
+    bool                getPositionCalibrationReport(PositionCalibrationReport* data);
+    bool                getAllPositionCalibrationReports(Array<PositionCalibrationReport>* data);
+
+    bool	            setCustomPatternReport(const CustomPatternReport& data);
+    bool                getCustomPatternReport(CustomPatternReport* data);
+
+    bool	            setKeepAliveMuxReport(const KeepAliveMuxReport& data);
+    bool                getKeepAliveMuxReport(KeepAliveMuxReport* data);
+
+    bool	            setManufacturingReport(const ManufacturingReport& data);
+    bool                getManufacturingReport(ManufacturingReport* data);
+
+    bool	            setUUIDReport(const UUIDReport& data);
+    bool                getUUIDReport(UUIDReport* data);
+
+    bool		        setTemperatureReport(const TemperatureReport& data);
+    bool		        getTemperatureReport(TemperatureReport* data);
+    bool                getAllTemperatureReports(Array<Array<TemperatureReport> >*);
+
+    bool                getGyroOffsetReport(GyroOffsetReport* data);
+
+    bool	            setLensDistortionReport(const LensDistortionReport& data);
+    bool                getLensDistortionReport(LensDistortionReport* data);
+
+    // Called for decoded messages
+    void                onTrackerMessage(Tracker2Message* message);
+
+    UByte                   LastNumSamples;
+    UInt16		            LastRunningSampleCount;
+    UInt32                  FullCameraFrameCount;
+
+    SensorTimestampMapping  LastCameraTime;
+    SensorTimestampMapping  LastFrameTime;
+    SensorTimestampMapping  LastSensorTime;
+    // Record last frame timestamp to know when to send pixelRead messages.
+    UInt32                  LastFrameTimestamp;
+
+    SensorCalibration       *pCalibration;
+};
+
+} // namespace OVR
+
+#endif // OVR_Sensor2Impl_h
diff --git a/LibOVR/Src/OVR_Sensor2ImplUtil.h b/LibOVR/Src/OVR_Sensor2ImplUtil.h
new file mode 100644
index 0000000..91b2195
--- /dev/null
+++ b/LibOVR/Src/OVR_Sensor2ImplUtil.h
@@ -0,0 +1,676 @@
+/************************************************************************************
+
+Filename    :   OVR_Sensor2ImplUtil.h
+Content     :   DK2 sensor device feature report utils.
+Created     :   January 27, 2014
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Sensor2ImplUtil_h
+#define OVR_Sensor2ImplUtil_h
+
+#include "OVR_Device.h"
+#include "OVR_SensorImpl_Common.h"
+#include "Kernel/OVR_Alg.h"
+
+namespace OVR {
+
+using namespace Alg;
+
+// Tracking feature report.
+struct TrackingImpl
+{
+    enum  { PacketSize = 13 };
+    UByte   Buffer[PacketSize];
+    
+    TrackingReport  Settings;
+
+	TrackingImpl()
+	{
+		for (int i=0; i<PacketSize; i++)
+		{
+			Buffer[i] = 0;
+		}
+
+		Buffer[0] = 12;
+	}
+
+    TrackingImpl(const TrackingReport& settings)
+		:	Settings(settings)
+    {
+		Pack();
+	}
+
+    void  Pack()
+    {
+
+        Buffer[0] = 12;
+        EncodeUInt16 ( Buffer+1, Settings.CommandId );
+        Buffer[3] = Settings.Pattern;
+        Buffer[4] = UByte(Settings.Enable << 0 |
+                          Settings.Autoincrement << 1 |
+                          Settings.UseCarrier << 2 |
+                          Settings.SyncInput << 3 |
+                          Settings.VsyncLock << 4 |
+                          Settings.CustomPattern << 5);
+        Buffer[5] = 0;
+        EncodeUInt16 ( Buffer+6, Settings.ExposureLength );
+        EncodeUInt16 ( Buffer+8, Settings.FrameInterval );
+        EncodeUInt16 ( Buffer+10, Settings.VsyncOffset );
+        Buffer[12] = Settings.DutyCycle;
+    }
+
+    void Unpack()
+    {
+        Settings.CommandId = DecodeUInt16(Buffer+1);
+        Settings.Pattern = Buffer[3];
+        Settings.Enable = (Buffer[4] & 0x01) != 0;
+        Settings.Autoincrement = (Buffer[4] & 0x02) != 0;
+        Settings.UseCarrier = (Buffer[4] & 0x04) != 0;
+        Settings.SyncInput = (Buffer[4] & 0x08) != 0;
+        Settings.VsyncLock = (Buffer[4] & 0x10) != 0;
+        Settings.CustomPattern = (Buffer[4] & 0x20) != 0;
+        Settings.ExposureLength = DecodeUInt16(Buffer+6);
+        Settings.FrameInterval = DecodeUInt16(Buffer+8);
+        Settings.VsyncOffset = DecodeUInt16(Buffer+10);
+        Settings.DutyCycle = Buffer[12];
+    }
+};
+
+// Display feature report.
+struct DisplayImpl
+{
+    enum  { PacketSize = 16 };
+    UByte   Buffer[PacketSize];
+    
+    DisplayReport Settings;
+
+	DisplayImpl()
+	{
+		for (int i=0; i<PacketSize; i++)
+		{
+			Buffer[i] = 0;
+		}
+
+		Buffer[0] = 13;
+	}
+
+    DisplayImpl(const DisplayReport& settings)
+		:	Settings(settings)
+    {
+		Pack();
+	}
+
+    void  Pack()
+    {
+
+        Buffer[0] = 13;
+        EncodeUInt16 ( Buffer+1, Settings.CommandId );
+        Buffer[3] = Settings.Brightness;
+        Buffer[4] = UByte(  (Settings.ShutterType & 0x0F) |
+                            (Settings.CurrentLimit & 0x03) << 4 |
+                            (Settings.UseRolling ? 0x40 : 0) |
+                            (Settings.ReverseRolling ? 0x80 : 0));
+        Buffer[5] = UByte(  (Settings.HighBrightness ? 0x01 : 0) |
+                            (Settings.SelfRefresh ? 0x02 : 0) |
+                            (Settings.ReadPixel ? 0x04 : 0) |
+                            (Settings.DirectPentile ? 0x08 : 0));
+        EncodeUInt16 ( Buffer+8, Settings.Persistence );
+        EncodeUInt16 ( Buffer+10, Settings.LightingOffset );
+        EncodeUInt16 ( Buffer+12, Settings.PixelSettle );
+        EncodeUInt16 ( Buffer+14, Settings.TotalRows );
+    }
+
+    void Unpack()
+    {
+
+        Settings.CommandId = DecodeUInt16(Buffer+1);
+        Settings.Brightness = Buffer[3];
+        Settings.ShutterType = DisplayReport::ShutterTypeEnum(Buffer[4] & 0x0F);
+        Settings.CurrentLimit = DisplayReport::CurrentLimitEnum((Buffer[4] >> 4) & 0x02);
+        Settings.UseRolling = (Buffer[4] & 0x40) != 0;
+        Settings.ReverseRolling = (Buffer[4] & 0x80) != 0;
+        Settings.HighBrightness = (Buffer[5] & 0x01) != 0;
+        Settings.SelfRefresh = (Buffer[5] & 0x02) != 0;
+        Settings.ReadPixel = (Buffer[5] & 0x04) != 0;
+        Settings.DirectPentile = (Buffer[5] & 0x08) != 0;
+        Settings.Persistence = DecodeUInt16(Buffer+8);
+        Settings.LightingOffset = DecodeUInt16(Buffer+10);
+        Settings.PixelSettle = DecodeUInt16(Buffer+12);
+        Settings.TotalRows = DecodeUInt16(Buffer+14);
+    }
+};
+
+// MagCalibration feature report.
+struct MagCalibrationImpl
+{
+    enum  { PacketSize = 52 };
+    UByte   Buffer[PacketSize];
+
+    MagCalibrationReport Settings;
+
+    MagCalibrationImpl()
+    {
+        memset(Buffer, 0, sizeof(Buffer));
+        Buffer[0] = 14;
+    }
+
+    MagCalibrationImpl(const MagCalibrationReport& settings)
+        :	Settings(settings)
+    {
+        Pack();
+    }
+
+    void  Pack()
+    {
+        Buffer[0] = 14;
+        EncodeUInt16(Buffer+1, Settings.CommandId);
+        Buffer[3] = Settings.Version;
+
+        for (int i = 0; i < 3; i++)
+            for (int j = 0; j < 4; j++)
+            {
+                SInt32 value = SInt32(Settings.Calibration.M[i][j] * 1e4f);
+                EncodeSInt32(Buffer + 4 + 4 * (4 * i + j), value);
+            }
+    }
+
+    void Unpack()
+    {
+        Settings.CommandId = DecodeUInt16(Buffer+1);
+        Settings.Version = Buffer[3];
+
+        for (int i = 0; i < 3; i++)
+            for (int j = 0; j < 4; j++)
+            {
+                SInt32 value = DecodeSInt32(Buffer + 4 + 4 * (4 * i + j));
+                Settings.Calibration.M[i][j] = (float)value * 1e-4f;
+            }
+    }
+};
+
+//-------------------------------------------------------------------------------------
+// PositionCalibration feature report.
+// - Sensor interface versions before 5 do not support Normal and Rotation.
+
+struct PositionCalibrationImpl
+{
+	enum  { PacketSize = 30 };
+	UByte   Buffer[PacketSize];
+
+	PositionCalibrationReport Settings;
+
+	PositionCalibrationImpl()
+	{
+		for (int i=0; i<PacketSize; i++)
+		{
+			Buffer[i] = 0;
+		}
+
+		Buffer[0] = 15;
+	}
+
+	PositionCalibrationImpl(const PositionCalibrationReport& settings)
+		:	Settings(settings)
+	{
+		Pack();
+	}
+
+	void  Pack()
+	{
+
+		Buffer[0] = 15;
+		EncodeUInt16(Buffer+1, Settings.CommandId);
+		Buffer[3] = Settings.Version;
+
+        Vector3d position = Settings.Position * 1e6;
+		EncodeSInt32(Buffer+4,  (SInt32) position.x);
+		EncodeSInt32(Buffer+8,  (SInt32) position.y);
+		EncodeSInt32(Buffer+12, (SInt32) position.z);
+
+        Vector3d normal = Settings.Normal * 1e6;
+        EncodeSInt16(Buffer+16, (SInt16) normal.x);
+		EncodeSInt16(Buffer+18, (SInt16) normal.y);
+		EncodeSInt16(Buffer+20, (SInt16) normal.z);
+
+        double rotation = Settings.Angle * 1e4;
+		EncodeSInt16(Buffer+22, (SInt16) rotation);
+
+		EncodeUInt16(Buffer+24, Settings.PositionIndex);
+		EncodeUInt16(Buffer+26, Settings.NumPositions);
+		EncodeUInt16(Buffer+28, UInt16(Settings.PositionType));
+	}
+
+	void Unpack()
+	{
+		Settings.CommandId = DecodeUInt16(Buffer+1);
+		Settings.Version = Buffer[3];
+
+		Settings.Position.x = DecodeSInt32(Buffer + 4) * 1e-6;
+		Settings.Position.y = DecodeSInt32(Buffer + 8) * 1e-6;
+		Settings.Position.z = DecodeSInt32(Buffer + 12) * 1e-6;
+
+		Settings.Normal.x = DecodeSInt16(Buffer + 16) * 1e-6;
+		Settings.Normal.y = DecodeSInt16(Buffer + 18) * 1e-6;
+		Settings.Normal.z = DecodeSInt16(Buffer + 20) * 1e-6;
+
+		Settings.Angle = DecodeSInt16(Buffer + 22) * 1e-4;
+
+		Settings.PositionIndex = DecodeUInt16(Buffer + 24);
+		Settings.NumPositions  = DecodeUInt16(Buffer + 26);
+
+		Settings.PositionType  = PositionCalibrationReport::PositionTypeEnum(DecodeUInt16(Buffer + 28));
+	}
+};
+
+struct PositionCalibrationImpl_Pre5
+{
+	enum  { PacketSize = 22 };
+	UByte   Buffer[PacketSize];
+
+	PositionCalibrationReport Settings;
+
+	PositionCalibrationImpl_Pre5()
+	{
+		for (int i=0; i<PacketSize; i++)
+		{
+			Buffer[i] = 0;
+		}
+
+		Buffer[0] = 15;
+	}
+
+	PositionCalibrationImpl_Pre5(const PositionCalibrationReport& settings)
+		:	Settings(settings)
+	{
+		Pack();
+	}
+
+	void  Pack()
+	{
+
+		Buffer[0] = 15;
+		EncodeUInt16(Buffer+1, Settings.CommandId);
+		Buffer[3] = Settings.Version;
+
+        Vector3d position = Settings.Position * 1e6;
+        EncodeSInt32(Buffer+4 , (SInt32) position.x);
+        EncodeSInt32(Buffer+8 , (SInt32) position.y);
+        EncodeSInt32(Buffer+12, (SInt32) position.z);
+
+		EncodeUInt16(Buffer+16, Settings.PositionIndex);
+		EncodeUInt16(Buffer+18, Settings.NumPositions);
+		EncodeUInt16(Buffer+20, UInt16(Settings.PositionType));
+	}
+
+	void Unpack()
+	{
+
+		Settings.CommandId = DecodeUInt16(Buffer+1);
+		Settings.Version = Buffer[3];
+
+		Settings.Position.x = DecodeSInt32(Buffer + 4) * 1e-6;
+		Settings.Position.y = DecodeSInt32(Buffer + 8) * 1e-6;
+		Settings.Position.z = DecodeSInt32(Buffer + 12) * 1e-6;
+
+		Settings.PositionIndex = DecodeUInt16(Buffer + 16);
+		Settings.NumPositions  = DecodeUInt16(Buffer + 18);
+		Settings.PositionType  = PositionCalibrationReport::PositionTypeEnum(DecodeUInt16(Buffer + 20));
+	}
+};
+
+// CustomPattern feature report.
+struct CustomPatternImpl
+{
+    enum  { PacketSize = 12 };
+    UByte   Buffer[PacketSize];
+    
+    CustomPatternReport Settings;
+
+	CustomPatternImpl()
+	{
+		for (int i=0; i<PacketSize; i++)
+		{
+			Buffer[i] = 0;
+		}
+
+		Buffer[0] = 16;
+	}
+
+    CustomPatternImpl(const CustomPatternReport& settings)
+		:	Settings(settings)
+    {
+		Pack();
+	}
+
+    void  Pack()
+    {
+
+        Buffer[0] = 16;
+        EncodeUInt16(Buffer+1, Settings.CommandId);
+        Buffer[3] = Settings.SequenceLength;
+        EncodeUInt32(Buffer+4 , Settings.Sequence);
+        EncodeUInt16(Buffer+8 , Settings.LEDIndex);
+        EncodeUInt16(Buffer+10, Settings.NumLEDs);
+    }
+
+    void Unpack()
+    {
+        Settings.CommandId = DecodeUInt16(Buffer+1);
+        Settings.SequenceLength = Buffer[3];
+        Settings.Sequence = DecodeUInt32(Buffer+4);
+        Settings.LEDIndex = DecodeUInt16(Buffer+8);
+        Settings.NumLEDs = DecodeUInt16(Buffer+10);
+    }
+};
+
+// Manufacturing feature report.
+struct ManufacturingImpl
+{
+    enum  { PacketSize = 16 };
+    UByte   Buffer[PacketSize];
+
+    ManufacturingReport Settings;
+
+	ManufacturingImpl()
+	{
+		memset(Buffer, 0, sizeof(Buffer));
+		Buffer[0] = 18;
+	}
+
+    ManufacturingImpl(const ManufacturingReport& settings)
+        :   Settings(settings)
+    {
+        Pack();
+    }
+
+    void  Pack()
+    {
+        Buffer[0] = 18;
+        EncodeUInt16(Buffer+1, Settings.CommandId);
+        Buffer[3] = Settings.NumStages;
+        Buffer[4] = Settings.Stage;
+        Buffer[5] = Settings.StageVersion;
+        EncodeUInt16(Buffer+6, Settings.StageLocation);
+        EncodeUInt32(Buffer+8, Settings.StageTime);
+        EncodeUInt32(Buffer+12, Settings.Result);
+    }
+
+    void Unpack()
+    {
+        Settings.CommandId = DecodeUInt16(Buffer+1);
+        Settings.NumStages = Buffer[3];
+        Settings.Stage = Buffer[4];
+        Settings.StageVersion = Buffer[5];
+        Settings.StageLocation = DecodeUInt16(Buffer+6);
+        Settings.StageTime = DecodeUInt32(Buffer+8);
+        Settings.Result = DecodeUInt32(Buffer+12);
+    }
+};
+
+// UUID feature report.
+struct UUIDImpl
+{
+    enum  { PacketSize = 23 };
+    UByte   Buffer[PacketSize];
+
+    UUIDReport Settings;
+
+	UUIDImpl()
+	{
+		memset(Buffer, 0, sizeof(Buffer));
+		Buffer[0] = 19;
+	}
+
+    UUIDImpl(const UUIDReport& settings)
+        :   Settings(settings)
+    {
+        Pack();
+    }
+
+    void  Pack()
+    {
+        Buffer[0] = 19;
+        EncodeUInt16(Buffer+1, Settings.CommandId);
+		for (int i = 0; i < 20; ++i)
+			Buffer[3 + i] = Settings.UUIDValue[i];
+    }
+
+    void Unpack()
+    {
+        Settings.CommandId = DecodeUInt16(Buffer+1);
+		for (int i = 0; i < 20; ++i)
+			Settings.UUIDValue[i] = Buffer[3 + i];
+    }
+};
+
+// LensDistortion feature report.
+struct LensDistortionImpl
+{
+    enum  { PacketSize = 64 };
+    UByte   Buffer[PacketSize];
+
+    LensDistortionReport Settings;
+
+	LensDistortionImpl()
+	{
+		memset(Buffer, 0, sizeof(Buffer));
+		Buffer[0] = 22;
+	}
+
+    LensDistortionImpl(const LensDistortionReport& settings)
+        :   Settings(settings)
+    {
+        Pack();
+    }
+
+    void  Pack()
+    {
+        Buffer[0] = 19;
+        EncodeUInt16(Buffer+1, Settings.CommandId);
+		
+		Buffer[3] = Settings.NumDistortions;
+		Buffer[4] = Settings.DistortionIndex;
+		Buffer[5] = Settings.Bitmask;
+		EncodeUInt16(Buffer+6, Settings.LensType);
+		EncodeUInt16(Buffer+8, Settings.Version);
+		EncodeUInt16(Buffer+10, Settings.EyeRelief);
+
+		for (int i = 0; i < 11; ++i)
+			EncodeUInt16(Buffer+12+2*i, Settings.KCoefficients[i]);
+
+		EncodeUInt16(Buffer+34, Settings.MaxR);
+		EncodeUInt16(Buffer+36, Settings.MetersPerTanAngleAtCenter);
+				
+		for (int i = 0; i < 4; ++i)
+			EncodeUInt16(Buffer+38+2*i, Settings.ChromaticAberration[i]);
+    }
+
+    void Unpack()
+    {
+        Settings.CommandId = DecodeUInt16(Buffer+1);
+		
+		Settings.NumDistortions = Buffer[3];
+		Settings.DistortionIndex = Buffer[4];
+		Settings.Bitmask = Buffer[5];
+		Settings.LensType = DecodeUInt16(Buffer+6);
+		Settings.Version = DecodeUInt16(Buffer+8);
+		Settings.EyeRelief = DecodeUInt16(Buffer+10);
+
+		for (int i = 0; i < 11; ++i)
+			Settings.KCoefficients[i] = DecodeUInt16(Buffer+12+2*i);
+
+		Settings.MaxR = DecodeUInt16(Buffer+34);
+		Settings.MetersPerTanAngleAtCenter = DecodeUInt16(Buffer+36);
+				
+		for (int i = 0; i < 4; ++i)
+			Settings.ChromaticAberration[i] = DecodeUInt16(Buffer+38+2*i);
+    }
+};
+
+// KeepAliveMux feature report.
+struct KeepAliveMuxImpl
+{
+    enum  { PacketSize = 6 };
+    UByte   Buffer[PacketSize];
+
+    KeepAliveMuxReport Settings;
+
+	KeepAliveMuxImpl()
+	{
+		memset(Buffer, 0, sizeof(Buffer));
+		Buffer[0] = 17;
+	}
+
+    KeepAliveMuxImpl(const KeepAliveMuxReport& settings)
+        :   Settings(settings)
+    {
+        Pack();
+    }
+
+    void  Pack()
+    {
+        Buffer[0] = 17;
+        EncodeUInt16(Buffer+1, Settings.CommandId);
+        Buffer[3] = Settings.INReport;
+        EncodeUInt16(Buffer+4, Settings.Interval);
+    }
+
+    void Unpack()
+    {
+        Settings.CommandId = DecodeUInt16(Buffer+1);
+        Settings.INReport = Buffer[3];
+        Settings.Interval = DecodeUInt16(Buffer+4);
+    }
+};
+
+// Temperature feature report.
+struct TemperatureImpl
+{
+    enum  { PacketSize = 24 };
+    UByte   Buffer[PacketSize];
+    
+    TemperatureReport Settings;
+
+	TemperatureImpl()
+	{
+		memset(Buffer, 0, sizeof(Buffer));
+		Buffer[0] = 20;
+	}
+
+    TemperatureImpl(const TemperatureReport& settings)
+		:	Settings(settings)
+    {
+		Pack();
+	}
+
+    void  Pack()
+    {
+
+        Buffer[0] = 20;
+        EncodeUInt16(Buffer + 1, Settings.CommandId);
+        Buffer[3] = Settings.Version;
+
+        Buffer[4] = Settings.NumBins;
+        Buffer[5] = Settings.Bin;
+        Buffer[6] = Settings.NumSamples;
+        Buffer[7] = Settings.Sample;
+
+        EncodeSInt16(Buffer + 8 , SInt16(Settings.TargetTemperature * 1e2));
+        EncodeSInt16(Buffer + 10, SInt16(Settings.ActualTemperature * 1e2));
+
+        EncodeUInt32(Buffer + 12, Settings.Time);
+
+        Vector3d offset = Settings.Offset * 1e4;
+        PackSensor(Buffer + 16, (SInt16) offset.x, (SInt16) offset.y, (SInt16) offset.z);
+    }
+
+    void Unpack()
+    {
+        Settings.CommandId = DecodeUInt16(Buffer + 1);
+        Settings.Version = Buffer[3];
+
+        Settings.NumBins    = Buffer[4];
+        Settings.Bin        = Buffer[5];
+        Settings.NumSamples = Buffer[6];
+        Settings.Sample     = Buffer[7];
+
+        Settings.TargetTemperature = DecodeSInt16(Buffer + 8) * 1e-2;
+        Settings.ActualTemperature = DecodeSInt16(Buffer + 10) * 1e-2;
+
+        Settings.Time = DecodeUInt32(Buffer + 12);
+
+        SInt32 x, y, z;
+        UnpackSensor(Buffer + 16, &x, &y, &z);
+        Settings.Offset = Vector3d(x, y, z) * 1e-4;
+    }
+};
+
+// GyroOffset feature report.
+struct GyroOffsetImpl
+{
+    enum  { PacketSize = 18 };
+    UByte   Buffer[PacketSize];
+
+    GyroOffsetReport Settings;
+
+    GyroOffsetImpl()
+    {
+        memset(Buffer, 0, sizeof(Buffer));
+        Buffer[0] = 21;
+    }
+
+   GyroOffsetImpl(const GyroOffsetReport& settings)
+		:	Settings(settings)
+    {
+		Pack();
+	}
+
+    void  Pack()
+    {
+
+        Buffer[0] = 21;
+        Buffer[1] = UByte(Settings.CommandId & 0xFF);
+        Buffer[2] = UByte(Settings.CommandId >> 8);
+        Buffer[3] = UByte(Settings.Version);
+
+		Vector3d offset = Settings.Offset * 1e4;
+		PackSensor(Buffer + 4, (SInt32) offset.x, (SInt32) offset.y, (SInt32) offset.z);
+
+        EncodeSInt16(Buffer + 16, SInt16(Settings.Temperature * 1e2));
+    }
+
+    void Unpack()
+    {
+        Settings.CommandId   = DecodeUInt16(Buffer + 1);
+        Settings.Version     = GyroOffsetReport::VersionEnum(Buffer[3]);
+
+        SInt32 x, y, z;
+        UnpackSensor(Buffer + 4, &x, &y, &z);
+        Settings.Offset      = Vector3d(x, y, z) * 1e-4f;
+
+        Settings.Temperature = DecodeSInt16(Buffer + 16) * 1e-2;
+    }
+};
+
+} // namespace OVR
+
+#endif // OVR_Sensor2ImplUtil_h
diff --git a/LibOVR/Src/OVR_SensorCalibration.cpp b/LibOVR/Src/OVR_SensorCalibration.cpp
new file mode 100644
index 0000000..94fbb27
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorCalibration.cpp
@@ -0,0 +1,354 @@
+/************************************************************************************
+
+Filename    :   OVR_SensorCalibration.cpp
+Content     :   Calibration data implementation for the IMU messages 
+Created     :   January 28, 2014
+Authors     :   Max Katsev
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_SensorCalibration.h"
+#include "Kernel/OVR_Log.h"
+#include "Kernel/OVR_Threads.h"
+#include <time.h>
+
+namespace OVR {
+
+using namespace Alg;
+
+const UByte VERSION = 2;
+const UByte MAX_COMPAT_VERSION = 15;
+
+SensorCalibration::SensorCalibration(SensorDevice* pSensor)
+    : MagCalibrated(false), GyroFilter(6000), GyroAutoTemperature(0)
+{
+    this->pSensor = pSensor;
+};
+
+void SensorCalibration::Initialize()
+{
+    // read factory calibration
+    pSensor->GetFactoryCalibration(&AccelOffset, &GyroAutoOffset, &AccelMatrix, &GyroMatrix, &GyroAutoTemperature);
+
+    // if the headset has an autocalibrated offset, prefer it over the factory defaults
+    GyroOffsetReport gyroReport;
+    bool result = pSensor->GetGyroOffsetReport(&gyroReport);
+    if (result && gyroReport.Version != GyroOffsetReport::Version_NoOffset)
+    {
+        GyroAutoOffset = (Vector3f) gyroReport.Offset;
+        GyroAutoTemperature = (float) gyroReport.Temperature;
+    }
+    
+    // read the temperature tables and prepare the interpolation structures
+    result = pSensor->GetAllTemperatureReports(&TemperatureReports);
+    OVR_ASSERT(result);
+    for (int i = 0; i < 3; i++)
+        Interpolators[i].Initialize(TemperatureReports, i);
+
+    // read the mag calibration
+    MagCalibrationReport report;
+    result = pSensor->GetMagCalibrationReport(&report);
+    MagCalibrated = result && report.Version > 0;
+    MagMatrix = report.Calibration;
+    if (!MagCalibrated)
+    {
+        // OVR_ASSERT(false);
+        LogError("Magnetometer calibration not found!\n");
+    }
+}
+
+void SensorCalibration::DebugPrintLocalTemperatureTable()
+{
+	LogText("TemperatureReports:\n");
+	for (int i = 0; i < (int)TemperatureReports.GetSize(); i++)
+	{
+		for (int j = 0; j < (int)TemperatureReports[i].GetSize(); j++)
+		{
+			TemperatureReport& tr = TemperatureReports[i][j];
+
+			LogText("[%d][%d]: Version=%3d, Bin=%d/%d, "
+					"Sample=%d/%d, TargetTemp=%3.1lf, "
+					"ActualTemp=%4.1lf, "
+					"Offset=(%7.2lf, %7.2lf, %7.2lf), "
+					"Time=%d\n",	i, j, tr.Version,
+									tr.Bin, tr.NumBins,
+									tr.Sample, tr.NumSamples,
+									tr.TargetTemperature,
+									tr.ActualTemperature,
+									tr.Offset.x, tr.Offset.y, tr.Offset.z,
+									tr.Time);
+		}
+	}
+}
+
+void SensorCalibration::DebugClearHeadsetTemperatureReports()
+{
+    OVR_ASSERT(pSensor != NULL);
+
+    bool result;
+
+	Array<Array<TemperatureReport> > temperatureReports;
+	pSensor->GetAllTemperatureReports(&temperatureReports);
+
+	OVR_ASSERT(temperatureReports.GetSize() > 0);
+	OVR_ASSERT(temperatureReports[0].GetSize() > 0);
+
+	TemperatureReport& tr = TemperatureReports[0][0];
+
+	tr.ActualTemperature = 0.0;
+	tr.Time = 0;
+	tr.Version = 0;
+	tr.Offset.x = tr.Offset.y = tr.Offset.z = 0.0;
+
+	for (UByte i = 0; i < tr.NumBins; i++)
+	{
+		tr.Bin = i;
+
+		for (UByte j = 0; j < tr.NumSamples; j++)
+		{
+			tr.Sample = j;
+
+			result = pSensor->SetTemperatureReport(tr);
+			OVR_ASSERT(result);
+			
+			// Need to wait for the tracker board to finish writing to eeprom.
+			Thread::MSleep(50);
+		}
+	}
+}
+
+void SensorCalibration::Apply(MessageBodyFrame& msg)
+{
+    AutocalibrateGyro(msg);
+
+    // compute the interpolated offset
+    Vector3f gyroOffset;
+    for (int i = 0; i < 3; i++)
+        gyroOffset[i] = (float) Interpolators[i].GetOffset(msg.Temperature, GyroAutoTemperature, GyroAutoOffset[i]);
+
+    // apply calibration
+    msg.RotationRate = GyroMatrix.Transform(msg.RotationRate - gyroOffset);
+    msg.Acceleration = AccelMatrix.Transform(msg.Acceleration - AccelOffset);
+    if (MagCalibrated)
+        msg.MagneticField = MagMatrix.Transform(msg.MagneticField);
+}
+
+void SensorCalibration::AutocalibrateGyro(MessageBodyFrame const& msg)
+{
+    const float alpha = 0.4f;
+    // 1.25f is a scaling factor related to conversion from per-axis comparison to length comparison
+    const float absLimit = 1.25f * 0.349066f;
+    const float noiseLimit = 1.25f * 0.03f;
+
+    Vector3f gyro = msg.RotationRate;
+    // do a moving average to reject short term noise
+    Vector3f avg = (GyroFilter.IsEmpty()) ? gyro : gyro * alpha + GyroFilter.PeekBack() * (1 - alpha);
+
+    // Make sure the absolute value is below what is likely motion
+    // Make sure it is close enough to the current average that it is probably noise and not motion
+    if (avg.Length() >= absLimit || (avg - GyroFilter.Mean()).Length() >= noiseLimit)
+        GyroFilter.Clear();
+    GyroFilter.PushBack(avg);
+
+    // if had a reasonable number of samples already use it for the current offset
+    if (GyroFilter.GetSize() > GyroFilter.GetCapacity() / 2)
+    {
+        GyroAutoOffset = GyroFilter.Mean();
+        GyroAutoTemperature = msg.Temperature;
+        // After ~6 seconds of no motion, use the average as the new zero rate offset
+        if (GyroFilter.IsFull())
+            StoreAutoOffset();
+    }
+}
+
+void SensorCalibration::StoreAutoOffset()
+{
+    const double maxDeltaT = 2.5;
+    const double minExtraDeltaT = 0.5;
+    const UInt32 minDelay = 24 * 3600; // 1 day in seconds
+
+    // find the best bin
+    UPInt binIdx = 0;
+    for (UPInt i = 1; i < TemperatureReports.GetSize(); i++) 
+        if (Abs(GyroAutoTemperature - TemperatureReports[i][0].TargetTemperature) < 
+            Abs(GyroAutoTemperature - TemperatureReports[binIdx][0].TargetTemperature))
+            binIdx = i;
+
+    // find the oldest and newest samples
+    // NB: uninitialized samples have Time == 0, so they will get picked as the oldest
+    UPInt newestIdx = 0, oldestIdx = 0;
+    for (UPInt i = 1; i < TemperatureReports[binIdx].GetSize(); i++)
+    {
+        // if the version is newer - do nothing
+        if (TemperatureReports[binIdx][i].Version > VERSION)
+            return;
+        if (TemperatureReports[binIdx][i].Time > TemperatureReports[binIdx][newestIdx].Time)
+            newestIdx = i;
+        if (TemperatureReports[binIdx][i].Time < TemperatureReports[binIdx][oldestIdx].Time)
+            oldestIdx = i;
+    }
+    TemperatureReport& oldestReport = TemperatureReports[binIdx][oldestIdx];
+    TemperatureReport& newestReport = TemperatureReports[binIdx][newestIdx];
+    OVR_ASSERT((oldestReport.Sample == 0 && newestReport.Sample == 0 && newestReport.Version == 0) || 
+                oldestReport.Sample == (newestReport.Sample + 1) % newestReport.NumSamples);
+
+    bool writeSuccess = false;
+    UInt32 now = (UInt32) time(0);
+    if (now - newestReport.Time > minDelay)
+    {
+        // only write a new sample if the temperature is close enough
+        if (Abs(GyroAutoTemperature - oldestReport.TargetTemperature) < maxDeltaT)
+        {
+            oldestReport.Time = now;
+            oldestReport.ActualTemperature = GyroAutoTemperature;
+            oldestReport.Offset = (Vector3d) GyroAutoOffset;
+            oldestReport.Version = VERSION;
+            writeSuccess = pSensor->SetTemperatureReport(oldestReport);
+            OVR_ASSERT(writeSuccess);
+        }
+    }
+    else
+    {
+        // if the newest sample is too recent - _update_ it if significantly closer to the target temp
+        if (Abs(GyroAutoTemperature - newestReport.TargetTemperature) + minExtraDeltaT
+            < Abs(newestReport.ActualTemperature - newestReport.TargetTemperature))
+        {
+            // (do not update the time!)
+            newestReport.ActualTemperature = GyroAutoTemperature;
+            newestReport.Offset = (Vector3d) GyroAutoOffset;
+            newestReport.Version = VERSION;
+            writeSuccess = pSensor->SetTemperatureReport(newestReport);
+            OVR_ASSERT(writeSuccess);
+        }
+    }
+
+    // update the interpolators with the new data
+    // this is not particularly expensive call and would only happen rarely
+    // but if performance is a problem, it's possible to only recompute the data that has changed
+    if (writeSuccess)
+        for (int i = 0; i < 3; i++)
+            Interpolators[i].Initialize(TemperatureReports, i);
+}
+
+const TemperatureReport& median(const Array<TemperatureReport>& temperatureReportsBin, int coord)
+{
+    Array<double> values;
+    values.Reserve(temperatureReportsBin.GetSize());
+    for (unsigned i = 0; i < temperatureReportsBin.GetSize(); i++)
+        if (temperatureReportsBin[i].ActualTemperature != 0)
+            values.PushBack(temperatureReportsBin[i].Offset[coord]);
+    if (values.GetSize() > 0)
+    {
+        double med = Median(values);
+        // this is kind of a hack
+        for (unsigned i = 0; i < temperatureReportsBin.GetSize(); i++)
+            if (temperatureReportsBin[i].Offset[coord] == med)
+                return temperatureReportsBin[i];
+        // if we haven't found the median in the original array, something is wrong
+        OVR_DEBUG_BREAK;
+    }
+    return temperatureReportsBin[0];
+}
+
+void OffsetInterpolator::Initialize(Array<Array<TemperatureReport> > const& temperatureReports, int coord)
+{
+    int bins = (int) temperatureReports.GetSize();
+    Temperatures.Clear();
+    Temperatures.Reserve(bins);
+    Values.Clear();
+    Values.Reserve(bins);
+
+    for (int bin = 0; bin < bins; bin++)
+    {
+        OVR_ASSERT(temperatureReports[bin].GetSize() == temperatureReports[0].GetSize());
+        const TemperatureReport& report = median(temperatureReports[bin], coord);
+        if (report.Version > 0 && report.Version <= MAX_COMPAT_VERSION)
+        {
+            Temperatures.PushBack(report.ActualTemperature);
+            Values.PushBack(report.Offset[coord]);
+        }
+    }
+}
+
+double OffsetInterpolator::GetOffset(double targetTemperature, double autoTemperature, double autoValue)
+{
+    const double autoRangeExtra = 1.0;
+    const double minInterpolationDist = 0.5;
+
+    // difference between current and autocalibrated temperature adjusted for preference over historical data
+    const double adjustedDeltaT = Abs(autoTemperature - targetTemperature) - autoRangeExtra;
+
+    int count = (int) Temperatures.GetSize();
+    // handle special cases when we don't have enough data for proper interpolation
+    if (count == 0)
+        return autoValue;
+    if (count == 1)
+    {
+        if (adjustedDeltaT < Abs(Temperatures[0] - targetTemperature))
+            return autoValue;
+        else
+            return Values[0];
+    }
+
+    // first, find the interval that contains targetTemperature
+    // if all points are on the same side of targetTemperature, find the adjacent interval
+    int l;
+    if (targetTemperature < Temperatures[1])
+        l = 0;
+    else if (targetTemperature >= Temperatures[count - 2])
+        l = count - 2;
+    else
+        for (l = 1; l < count - 2; l++)
+            if (Temperatures[l] <= targetTemperature && targetTemperature < Temperatures[l+1])
+                break;
+    int u = l + 1;
+
+    // extend the interval if it's too small and the interpolation is unreliable
+    if (Temperatures[u] - Temperatures[l] < minInterpolationDist)
+    {
+        if (l > 0 
+            && (u == count - 1 || Temperatures[u] - Temperatures[l - 1] < Temperatures[u + 1] - Temperatures[l]))
+            l--;
+        else if (u < count - 1)
+            u++;
+    }
+
+    // verify correctness
+    OVR_ASSERT(l >= 0 && u < count);
+    OVR_ASSERT(l == 0 || Temperatures[l] <= targetTemperature);
+    OVR_ASSERT(u == count - 1 || targetTemperature < Temperatures[u]);
+    OVR_ASSERT((l == 0 && u == count - 1) || Temperatures[u] - Temperatures[l] > minInterpolationDist);
+    OVR_ASSERT(Temperatures[l] <= Temperatures[u]);
+
+    // perform the interpolation
+    double slope;
+    if (Temperatures[u] - Temperatures[l] >= minInterpolationDist)
+        slope = (Values[u] - Values[l]) / (Temperatures[u] - Temperatures[l]);
+    else
+        // avoid a badly conditioned problem
+        slope = 0;
+    if (adjustedDeltaT < Abs(Temperatures[u] - targetTemperature))
+        // use the autocalibrated value, if it's close
+        return autoValue + slope * (targetTemperature - autoTemperature);
+    else
+        return Values[u] + slope * (targetTemperature - Temperatures[u]);
+}
+
+} // namespace OVR
diff --git a/LibOVR/Src/OVR_SensorCalibration.h b/LibOVR/Src/OVR_SensorCalibration.h
new file mode 100644
index 0000000..62883d2
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorCalibration.h
@@ -0,0 +1,82 @@
+/************************************************************************************
+
+Filename    :   OVR_SensorCalibration.h
+Content     :   Calibration data implementation for the IMU messages 
+Created     :   January 28, 2014
+Authors     :   Max Katsev
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_SensorCalibration_h
+#define OVR_SensorCalibration_h
+
+#include "OVR_Device.h"
+#include "OVR_SensorFilter.h"
+
+namespace OVR {
+
+class OffsetInterpolator
+{
+public:
+    void Initialize(Array<Array<TemperatureReport> > const& temperatureReports, int coord);
+    double GetOffset(double targetTemperature, double autoTemperature, double autoValue);
+
+    Array<double> Temperatures;
+    Array<double> Values;
+};
+
+class SensorCalibration : public NewOverrideBase
+{
+public:
+    SensorCalibration(SensorDevice* pSensor);
+
+    // Load data from the HW and perform the necessary preprocessing
+    void Initialize();
+    // Apply the calibration
+    void Apply(MessageBodyFrame& msg);
+    // Is mag calibration available?
+    bool IsMagCalibrated() { return MagCalibrated; }
+
+protected:
+    void StoreAutoOffset();
+    void AutocalibrateGyro(MessageBodyFrame const& msg);
+
+	void DebugPrintLocalTemperatureTable();
+	void DebugClearHeadsetTemperatureReports();
+
+    SensorDevice* pSensor;
+
+    // Factory calibration data
+    bool MagCalibrated;
+    Matrix4f AccelMatrix, GyroMatrix, MagMatrix;
+    Vector3f AccelOffset;
+    
+    // Temperature based data
+    Array<Array<TemperatureReport> > TemperatureReports;
+    OffsetInterpolator Interpolators[3];
+
+    // Autocalibration data
+    SensorFilterf GyroFilter;
+    Vector3f GyroAutoOffset;
+    float GyroAutoTemperature;
+};
+
+} // namespace OVR
+#endif //OVR_SensorCalibration_h
diff --git a/LibOVR/Src/OVR_SensorFilter.cpp b/LibOVR/Src/OVR_SensorFilter.cpp
new file mode 100644
index 0000000..2c660ae
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorFilter.cpp
@@ -0,0 +1,99 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_SensorFilter.cpp
+Content     :   Basic filtering of sensor this->Data
+Created     :   March 7, 2013
+Authors     :   Steve LaValle, Anna Yershova, Max Katsev
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_SensorFilter.h"
+
+namespace OVR {
+
+template <typename T>
+Vector3<T> SensorFilter<T>::Median() const
+{
+    Vector3<T> result;
+    T* slice = (T*) OVR_ALLOC(this->ElemCount * sizeof(T));
+
+    for (int coord = 0; coord < 3; coord++)
+    {
+        for (int i = 0; i < this->ElemCount; i++)
+            slice[i] = this->Data[i][coord];
+        result[coord] = Alg::Median(ArrayAdaptor(slice, this->ElemCount));
+    }
+
+    OVR_FREE(slice);
+    return result;
+}
+
+//  Only the diagonal of the covariance matrix.
+template <typename T>
+Vector3<T> SensorFilter<T>::Variance() const
+{
+    Vector3<T> mean = this->Mean();
+    Vector3<T> total;
+    for (int i = 0; i < this->ElemCount; i++) 
+    {
+        total.x += (this->Data[i].x - mean.x) * (this->Data[i].x - mean.x);
+        total.y += (this->Data[i].y - mean.y) * (this->Data[i].y - mean.y);
+        total.z += (this->Data[i].z - mean.z) * (this->Data[i].z - mean.z);
+    }
+    return total / (float) this->ElemCount;
+}
+
+template <typename T>
+Matrix3<T> SensorFilter<T>::Covariance() const
+{
+    Vector3<T> mean = this->Mean();
+    Matrix3<T> total;
+    for (int i = 0; i < this->ElemCount; i++) 
+    {
+        total.M[0][0] += (this->Data[i].x - mean.x) * (this->Data[i].x - mean.x);
+        total.M[1][0] += (this->Data[i].y - mean.y) * (this->Data[i].x - mean.x);
+        total.M[2][0] += (this->Data[i].z - mean.z) * (this->Data[i].x - mean.x);
+        total.M[1][1] += (this->Data[i].y - mean.y) * (this->Data[i].y - mean.y);
+        total.M[2][1] += (this->Data[i].z - mean.z) * (this->Data[i].y - mean.y);
+        total.M[2][2] += (this->Data[i].z - mean.z) * (this->Data[i].z - mean.z);
+    }
+    total.M[0][1] = total.M[1][0];
+    total.M[0][2] = total.M[2][0];
+    total.M[1][2] = total.M[2][1];
+    for (int i = 0; i < 3; i++)
+        for (int j = 0; j < 3; j++)
+            total.M[i][j] /= (float) this->ElemCount;
+    return total;
+}
+
+template <typename T>
+Vector3<T> SensorFilter<T>::PearsonCoefficient() const
+{
+    Matrix3<T> cov = this->Covariance();
+    Vector3<T> pearson;
+    pearson.x = cov.M[0][1]/(sqrt(cov.M[0][0])*sqrt(cov.M[1][1]));
+    pearson.y = cov.M[1][2]/(sqrt(cov.M[1][1])*sqrt(cov.M[2][2]));
+    pearson.z = cov.M[2][0]/(sqrt(cov.M[2][2])*sqrt(cov.M[0][0]));
+
+    return pearson;
+}
+
+} //namespace OVR
diff --git a/LibOVR/Src/OVR_SensorFilter.h b/LibOVR/Src/OVR_SensorFilter.h
new file mode 100644
index 0000000..0805d57
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorFilter.h
@@ -0,0 +1,307 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_SensorFilter.h
+Content     :   Basic filtering of sensor data
+Created     :   March 7, 2013
+Authors     :   Steve LaValle, Anna Yershova, Max Katsev
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_SensorFilter_h
+#define OVR_SensorFilter_h
+
+#include "Kernel/OVR_Math.h"
+#include "Kernel/OVR_Deque.h"
+#include "Kernel/OVR_Alg.h"
+
+namespace OVR {
+
+// A base class for filters that maintains a buffer of sensor data taken over time and implements
+// various simple filters, most of which are linear functions of the data history.
+// Maintains the running sum of its elements for better performance on large capacity values
+template <typename T>
+class SensorFilterBase : public CircularBuffer<T>
+{
+protected:
+    T RunningTotal;               // Cached sum of the elements
+
+public:
+    SensorFilterBase(int capacity = CircularBuffer<T>::DefaultCapacity)
+        : CircularBuffer<T>(capacity), RunningTotal() 
+    {
+        this->Clear();
+    };
+
+    // The following methods are augmented to update the cached running sum value
+    void PushBack(const T &e)
+    {
+        CircularBuffer<T>::PushBack(e);
+        RunningTotal += e;
+        if (this->End == 0)
+        {
+            // update the cached total to avoid error accumulation
+            RunningTotal = T();
+            for (int i = 0; i < this->ElemCount; i++)
+                RunningTotal += this->Data[i];
+        } 
+    }
+
+    void PushFront(const T &e)
+    {
+        CircularBuffer<T>::PushFront(e);
+        RunningTotal += e;
+        if (this->Beginning == 0)
+        {
+            // update the cached total to avoid error accumulation
+            RunningTotal = T();
+            for (int i = 0; i < this->ElemCount; i++)
+                RunningTotal += this->Data[i];
+        }
+    }
+
+    T PopBack() 
+    { 
+        T e = CircularBuffer<T>::PopBack();
+        RunningTotal -= e;
+        return e;
+    }
+
+    T PopFront() 
+    { 
+        T e = CircularBuffer<T>::PopFront();
+        RunningTotal -= e;
+        return e;
+    }
+
+    void Clear()
+    {
+        CircularBuffer<T>::Clear();
+        RunningTotal = T();
+    }
+
+    // Simple statistics
+    T Total() const 
+    { 
+        return RunningTotal; 
+    }
+
+    T Mean() const
+    {
+        return this->IsEmpty() ? T() : (Total() / (float) this->ElemCount);
+    }
+
+	T MeanN(int n) const
+	{
+        OVR_ASSERT(n > 0);
+        OVR_ASSERT(this->Capacity >= n);
+		T total = T();
+        for (int i = 0; i < n; i++) 
+        {
+			total += this->PeekBack(i);
+		}
+		return total / n;
+	}
+
+    // A popular family of smoothing filters and smoothed derivatives
+
+    T SavitzkyGolaySmooth4() 
+    {
+        OVR_ASSERT(this->Capacity >= 4);
+        return this->PeekBack(0)*0.7f +
+               this->PeekBack(1)*0.4f +
+               this->PeekBack(2)*0.1f -
+               this->PeekBack(3)*0.2f;
+    }
+
+    T SavitzkyGolaySmooth8() const
+    {
+        OVR_ASSERT(this->Capacity >= 8);
+        return this->PeekBack(0)*0.41667f +
+               this->PeekBack(1)*0.33333f +
+               this->PeekBack(2)*0.25f +
+               this->PeekBack(3)*0.16667f +
+               this->PeekBack(4)*0.08333f -
+               this->PeekBack(6)*0.08333f -
+               this->PeekBack(7)*0.16667f;
+    }
+
+    T SavitzkyGolayDerivative4() const
+    {
+        OVR_ASSERT(this->Capacity >= 4);
+        return this->PeekBack(0)*0.3f +
+               this->PeekBack(1)*0.1f -
+               this->PeekBack(2)*0.1f -
+               this->PeekBack(3)*0.3f;
+    }
+
+    T SavitzkyGolayDerivative5() const
+    {
+            OVR_ASSERT(this->Capacity >= 5);
+            return this->PeekBack(0)*0.2f +
+                   this->PeekBack(1)*0.1f -
+                   this->PeekBack(3)*0.1f -
+                   this->PeekBack(4)*0.2f;
+   }
+
+    T SavitzkyGolayDerivative12() const
+    {
+        OVR_ASSERT(this->Capacity >= 12);
+        return this->PeekBack(0)*0.03846f +
+               this->PeekBack(1)*0.03147f +
+               this->PeekBack(2)*0.02448f +
+               this->PeekBack(3)*0.01748f +
+               this->PeekBack(4)*0.01049f +
+               this->PeekBack(5)*0.0035f -
+               this->PeekBack(6)*0.0035f -
+               this->PeekBack(7)*0.01049f -
+               this->PeekBack(8)*0.01748f -
+               this->PeekBack(9)*0.02448f -
+               this->PeekBack(10)*0.03147f -
+               this->PeekBack(11)*0.03846f;
+    } 
+
+    T SavitzkyGolayDerivativeN(int n) const
+    {    
+        OVR_ASSERT(this->capacity >= n);
+        int m = (n-1)/2;
+        T result = T();
+        for (int k = 1; k <= m; k++) 
+        {
+            int ind1 = m - k;
+            int ind2 = n - m + k - 1;
+            result += (this->PeekBack(ind1) - this->PeekBack(ind2)) * (float) k;
+        }
+        float coef = 3.0f/(m*(m+1.0f)*(2.0f*m+1.0f));
+        result = result*coef;
+        return result;
+    }
+
+    T Median() const
+    {
+        T* copy = (T*) OVR_ALLOC(this->ElemCount * sizeof(T));
+        T result = Alg::Median(ArrayAdaptor(copy));
+        OVR_FREE(copy);
+        return result;
+    }
+};
+
+// This class maintains a buffer of sensor data taken over time and implements
+// various simple filters, most of which are linear functions of the data history.
+template <typename T>
+class SensorFilter : public SensorFilterBase<Vector3<T> >
+{
+public:
+	SensorFilter(int capacity = SensorFilterBase<Vector3<T> >::DefaultCapacity) : SensorFilterBase<Vector3<T> >(capacity) { };
+
+    // Simple statistics
+    Vector3<T> Median() const;
+    Vector3<T> Variance() const; // The diagonal of covariance matrix
+    Matrix3<T> Covariance() const;
+    Vector3<T> PearsonCoefficient() const;
+};
+
+typedef SensorFilter<float> SensorFilterf;
+typedef SensorFilter<double> SensorFilterd;
+
+// This filter operates on the values that are measured in the body frame and rotate with the device
+class SensorFilterBodyFrame : public SensorFilterBase<Vector3d>
+{
+private:
+    // low pass filter gain
+    double gain;
+    // sum of squared norms of the values
+    double runningTotalLengthSq;
+    // cumulative rotation quaternion
+    Quatd Q;
+    // current low pass filter output
+    Vector3d output;
+
+    // make private so it isn't used by accident
+    // in addition to the normal SensorFilterBase::PushBack, keeps track of running sum of LengthSq
+    // for the purpose of variance computations
+    void PushBack(const Vector3d &e)
+    {
+        runningTotalLengthSq += this->IsFull() ? (e.LengthSq() - this->PeekFront().LengthSq()) : e.LengthSq();
+        SensorFilterBase<Vector3d>::PushBack(e);
+        if (this->End == 0)
+        {
+            // update the cached total to avoid error accumulation
+            runningTotalLengthSq = 0;
+            for (int i = 0; i < this->ElemCount; i++)
+                runningTotalLengthSq += this->Data[i].LengthSq();
+        } 
+    }
+
+public:
+	SensorFilterBodyFrame(int capacity = SensorFilterBase<Vector3d>::DefaultCapacity) 
+        : SensorFilterBase<Vector3d>(capacity), gain(2.5), 
+        runningTotalLengthSq(0), Q(), output()  { };
+
+    // return the scalar variance of the filter values (rotated to be in the same frame)
+    double Variance() const
+    {
+        return this->IsEmpty() ? 0 : (runningTotalLengthSq / this->ElemCount - this->Mean().LengthSq());
+    }
+    
+    // return the scalar standard deviation of the filter values (rotated to be in the same frame)
+    double StdDev() const
+    {
+        return sqrt(Variance());
+    }
+
+    // confidence value based on the stddev of the data (between 0.0 and 1.0, more is better)
+    double Confidence() const
+    {
+        return Alg::Clamp(0.48 - 0.1 * log(StdDev()), 0.0, 1.0) * this->ElemCount / this->Capacity;
+    }
+
+    // add a new element to the filter
+    // takes rotation increment since the last update 
+    // in order to rotate the previous value to the current body frame
+    void Update(Vector3d value, double deltaT, Quatd deltaQ = Quatd())
+    {
+        if (this->IsEmpty())
+        {
+            output = value;
+        }
+        else 
+        {
+            // rotate by deltaQ
+            output = deltaQ.Inverted().Rotate(output);
+            // apply low-pass filter
+            output += (value - output) * gain * deltaT;
+        }
+        
+        // put the value into the fixed frame for the stddev computation
+        Q = Q * deltaQ;
+        PushBack(Q.Rotate(output));
+    }
+
+    // returns the filter average in the current body frame
+    Vector3d GetFilteredValue() const
+    {
+        return Q.Inverted().Rotate(this->Mean());
+    }
+};
+
+} //namespace OVR
+
+#endif // OVR_SensorFilter_h
diff --git a/LibOVR/Src/OVR_SensorFusion.cpp b/LibOVR/Src/OVR_SensorFusion.cpp
new file mode 100644
index 0000000..5c21178
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorFusion.cpp
@@ -0,0 +1,904 @@
+/************************************************************************************
+
+Filename    :   OVR_SensorFusion.cpp
+Content     :   Methods that determine head orientation from sensor data over time
+Created     :   October 9, 2012
+Authors     :   Michael Antonov, Steve LaValle, Dov Katz, Max Katsev, Dan Gierl
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_SensorFusion.h"
+#include "Kernel/OVR_Log.h"
+#include "Kernel/OVR_System.h"
+#include "OVR_JSON.h"
+#include "OVR_Profile.h"
+#include "OVR_Stereo.h"
+#include "OVR_Recording.h"
+
+// Temporary for debugging
+bool Global_Flag_1 = true;
+
+//Convenient global variables to temporarily extract this data.
+float  TPH_CameraPoseOrientationWxyz[4];
+double TPH_CameraPoseConfidence;
+double TPH_CameraPoseConfidenceThresholdOverrideIfNonZero = 0;
+bool   TPH_IsPositionTracked = false;
+
+
+namespace OVR {
+
+const Transformd DefaultWorldFromCamera(Quatd(), Vector3d(0, 0, -1));
+
+//-------------------------------------------------------------------------------------
+// ***** Sensor Fusion
+
+SensorFusion::SensorFusion(SensorDevice* sensor)
+  : ExposureRecordHistory(100), LastMessageExposureFrame(NULL),
+    FocusDirection(Vector3d(0, 0, 0)), FocusFOV(0.0),
+    FAccelInImuFrame(1000), FAccelInCameraFrame(1000), FAngV(20),
+    EnableGravity(true), EnableYawCorrection(true), MagCalibrated(false),
+    EnableCameraTiltCorrection(true),
+    MotionTrackingEnabled(true), VisionPositionEnabled(true),
+    CenterPupilDepth(0.0)
+{
+   pHandler = new BodyFrameHandler(this);
+
+   // And the clock is running...
+   LogText("*** SensorFusion Startup: TimeSeconds = %f\n", Timer::GetSeconds());
+
+   if (sensor)
+       AttachToSensor(sensor);
+   
+   Reset();
+}
+
+SensorFusion::~SensorFusion()
+{   
+    delete(pHandler);
+}
+
+bool SensorFusion::AttachToSensor(SensorDevice* sensor)
+{
+    pHandler->RemoveHandlerFromDevices();
+    Reset();
+
+    if (sensor != NULL)
+    {
+        // cache mag calibration state
+        MagCalibrated = sensor->IsMagCalibrated();
+        
+        // Load IMU position
+        Array<PositionCalibrationReport> reports;
+        bool result = sensor->GetAllPositionCalibrationReports(&reports);
+        if (result)
+        {
+            PositionCalibrationReport imu = reports[reports.GetSize() - 1];
+            OVR_ASSERT(imu.PositionType == PositionCalibrationReport::PositionType_IMU);
+            // convert from vision to the world frame
+            // TBD convert rotation as necessary?
+            imu.Position.x *= -1.0;
+            imu.Position.z *= -1.0;
+
+            ImuFromScreen = Transformd(Quatd(imu.Normal, imu.Angle), imu.Position).Inverted();
+
+            Recording::GetRecorder().RecordLedPositions(reports);
+            Recording::GetRecorder().RecordDeviceIfcVersion(sensor->GetDeviceInterfaceVersion());
+		}
+        
+        // Repopulate CPFOrigin
+        SetCenterPupilDepth(CenterPupilDepth);
+
+        // Subscribe to sensor updates
+        sensor->AddMessageHandler(pHandler);
+
+        // Initialize the sensor state
+        // TBD: This is a hack to avoid a race condition if sensor status is checked immediately 
+        // after sensor creation but before any data has flowed through.  We should probably
+        // not depend strictly on data flow to determine capabilities like orientation and position
+        // tracking, or else use some sort of synchronous method to wait for data
+        LocklessState init;
+        init.StatusFlags = Status_OrientationTracked;   
+        UpdatedState.SetState(init);
+    }
+
+    return true;
+}
+
+// Resets the current orientation
+void SensorFusion::Reset()
+{
+    Lock::Locker lockScope(pHandler->GetHandlerLock());
+
+    UpdatedState.SetState(LocklessState());
+    WorldFromImu                        = PoseState<double>();
+    WorldFromImu.Pose                   = ImuFromCpf.Inverted(); // place CPF at the origin, not the IMU
+    CameraFromImu                       = PoseState<double>();
+    VisionError                         = PoseState<double>();
+    WorldFromCamera                     = DefaultWorldFromCamera;
+    WorldFromCameraConfidence           = -1;
+
+    ExposureRecordHistory.Clear();
+    NextExposureRecord                  = ExposureRecord();
+    LastMessageExposureFrame            = MessageExposureFrame(NULL);
+    LastVisionAbsoluteTime              = 0;
+    Stage                               = 0;
+    
+    MagRefs.Clear();
+    MagRefIdx                           = -1;
+    MagCorrectionIntegralTerm           = Quatd();
+    AccelOffset                         = Vector3d();
+
+    FAccelInCameraFrame.Clear();
+    FAccelInImuFrame.Clear();
+    FAngV.Clear();
+
+    setNeckPivotFromPose ( WorldFromImu.Pose );
+}
+
+//-------------------------------------------------------------------------------------
+//  Vision & message processing
+
+void SensorFusion::OnVisionFailure()
+{
+    // do nothing
+    Recording::GetRecorder().RecordVisionSuccess(false);
+}
+
+void SensorFusion::OnVisionPreviousFrame(const Transform<double>& cameraFromImu)
+{
+    // simply save the observation for use in the next OnVisionSuccess call;
+    // this should not have unintended side-effects for position filtering, 
+    // since the vision time is not updated and the system keeps thinking we don't have vision yet
+    CameraFromImu.Pose = cameraFromImu;
+}
+
+void SensorFusion::OnVisionSuccess(const Transform<double>& cameraFromImu, UInt32 exposureCounter)
+{
+    Lock::Locker lockScope(pHandler->GetHandlerLock());
+
+    Recording::GetRecorder().RecordVisionSuccess(true);
+
+    LastVisionAbsoluteTime = GetTime();
+
+    // ********* LastVisionExposureRecord *********
+
+    // Skip old data and use the record that matches the exposure counter
+    while (!ExposureRecordHistory.IsEmpty() &&
+           (ExposureRecordHistory.PeekFront().ExposureCounter <= exposureCounter))
+    {
+        LastVisionExposureRecord = ExposureRecordHistory.PopFront();
+    }
+
+    // Use current values if we don't have historical data
+    // Right now, this will happen if we get first frame after prediction failure,
+    // and this exposure wasn't in the buffer.  (TBD: Unlikely.. unless IMU message wasn't sent?)
+    if (LastVisionExposureRecord.ExposureCounter != exposureCounter)
+        LastVisionExposureRecord = ExposureRecord(exposureCounter, GetTime(), WorldFromImu, PoseState<double>());
+
+    // ********* CameraFromImu *********
+    
+    // This is stored in the camera frame, so need to be careful when combining with the IMU data,
+    // which is in the world frame
+
+    Transformd cameraFromImuPrev = CameraFromImu.Pose;
+    CameraFromImu.Pose = cameraFromImu; 
+    CameraFromImu.TimeInSeconds = LastVisionExposureRecord.ExposureTime;
+
+    // Check LastVisionExposureRecord.Delta.TimeInSeconds to avoid divide by zero, which we could (rarely)
+    // get if we didn't have exposures delta for history (skipped exposure counters
+    // due to video mode change that stalls USB, etc).
+    if (LastVisionExposureRecord.ImuOnlyDelta.TimeInSeconds > 0.001)
+    {
+        Vector3d visionVelocityInImuFrame = (cameraFromImu.Translation - cameraFromImuPrev.Translation) /
+                                            LastVisionExposureRecord.ImuOnlyDelta.TimeInSeconds;
+        // Use the accel data to estimate the velocity at the exposure time
+        // (as opposed to the average velocity between exposures)
+        Vector3d imuVelocityInWorldFrame = LastVisionExposureRecord.ImuOnlyDelta.LinearVelocity -
+            LastVisionExposureRecord.ImuOnlyDelta.Pose.Translation / LastVisionExposureRecord.ImuOnlyDelta.TimeInSeconds;
+        CameraFromImu.LinearVelocity = visionVelocityInImuFrame + 
+            WorldFromCamera.Inverted().Rotate(imuVelocityInWorldFrame);
+    }
+    else
+    {
+        CameraFromImu.LinearVelocity = Vector3d(0,0,0);
+    }
+}
+
+PoseStated SensorFusion::computeVisionError()
+{
+    PoseStated worldFromImuVision = WorldFromCamera * CameraFromImu;
+    // Here we need to compute the difference between worldFromImuVision and WorldFromImu.
+    // However this difference needs to be represented in the World frame, not IMU frame.
+    // Therefore the computation is different from simply worldFromImuVision.Pose * WorldFromImu.Pose.Inverted().
+    PoseStated err;
+    err.Pose.Rotation = worldFromImuVision.Pose.Rotation * 
+        LastVisionExposureRecord.WorldFromImu.Pose.Rotation.Inverted();
+    err.Pose.Translation = worldFromImuVision.Pose.Translation - 
+        LastVisionExposureRecord.WorldFromImu.Pose.Translation;
+    err.LinearVelocity = worldFromImuVision.LinearVelocity - 
+        LastVisionExposureRecord.WorldFromImu.LinearVelocity;
+    return err;
+}
+
+Transform<double> SensorFusion::GetVisionPrediction(UInt32 exposureCounter)
+{
+    Lock::Locker lockScope(pHandler->GetHandlerLock());
+
+    // Combine the small deltas together
+    // Should only be one iteration, unless we are skipping camera frames
+    ExposureRecord record;
+    PoseState<double> delta = PoseState<double>();
+
+    while (!ExposureRecordHistory.IsEmpty() && 
+           (ExposureRecordHistory.PeekFront().ExposureCounter <= exposureCounter))
+    {
+        record = ExposureRecordHistory.PopFront();
+        delta.AdvanceByDelta(record.ImuOnlyDelta);
+    }
+    // Put the combine exposure record back in the history, for use in HandleVisionSuccess(...)
+    record.ImuOnlyDelta = delta;
+    ExposureRecordHistory.PushFront(record);
+
+    Transformd result;
+    if (record.VisionTrackingAvailable)
+    {
+        // if the tracking is working normally, use the change in the main state (SFusion output)
+        // to compute the prediction
+        result = CameraFromImu.Pose *
+            LastVisionExposureRecord.WorldFromImu.Pose.Inverted() * record.WorldFromImu.Pose;
+    }
+    else
+    {
+        // if we just acquired vision, the main state probably doesn't have the correct position,
+        // so can't rely on it for prediction
+
+        // solution: use the accelerometer and vision velocity to propagate the previous sample forward
+        // (don't forget to transform IMU to the camera frame)
+        result = Transform<double>
+            (
+                CameraFromImu.Pose.Rotation * delta.Pose.Rotation,
+                CameraFromImu.Pose.Translation + CameraFromImu.LinearVelocity * delta.TimeInSeconds +
+                WorldFromCamera.Inverted().Rotate(delta.Pose.Translation)
+            );
+    }
+
+    return result;
+}
+
+void SensorFusion::handleMessage(const MessageBodyFrame& msg)
+{
+    if (msg.Type != Message_BodyFrame || !IsMotionTrackingEnabled())
+        return;
+
+    // Put the sensor readings into convenient local variables
+    Vector3d gyro(msg.RotationRate); 
+    Vector3d accel(msg.Acceleration); 
+    Vector3d mag(msg.MagneticField);
+    double DeltaT = msg.TimeDelta;
+
+    // Keep track of time
+    WorldFromImu.TimeInSeconds = msg.AbsoluteTimeSeconds;
+    // We got an update in the last 60ms and the data is not very old
+    bool visionIsRecent = (GetTime() - LastVisionAbsoluteTime < 0.07) && (GetVisionLatency() < 0.25);
+    Stage++;
+
+    // Insert current sensor data into filter history
+    FAngV.PushBack(gyro);
+    FAccelInImuFrame.Update(accel, DeltaT, Quatd(gyro, gyro.Length() * DeltaT));
+
+    // Process raw inputs
+    // in the future the gravity offset can be calibrated using vision feedback
+    Vector3d accelInWorldFrame = WorldFromImu.Pose.Rotate(accel) - Vector3d(0, 9.8, 0);
+
+    // Recompute the vision error to account for all the corrections and the new data
+    VisionError = computeVisionError();
+
+    // Update headset orientation   
+    WorldFromImu.StoreAndIntegrateGyro(gyro, DeltaT);
+    // Tilt correction based on accelerometer
+    if (EnableGravity)
+        applyTiltCorrection(DeltaT);
+    // Yaw correction based on camera
+    if (EnableYawCorrection && visionIsRecent)
+        applyVisionYawCorrection(DeltaT);
+    // Yaw correction based on magnetometer
+	if (EnableYawCorrection && MagCalibrated) // MagCalibrated is always false for DK2 for now
+		applyMagYawCorrection(mag, DeltaT);
+	// Focus Correction
+	if ((FocusDirection.x != 0.0f || FocusDirection.z != 0.0f) && FocusFOV < Mathf::Pi)
+		applyFocusCorrection(DeltaT);
+
+    // Update camera orientation
+    if (EnableCameraTiltCorrection && visionIsRecent)
+        applyCameraTiltCorrection(accel, DeltaT);
+
+    // The quaternion magnitude may slowly drift due to numerical error,
+    // so it is periodically normalized.
+    if ((Stage & 0xFF) == 0)
+    {
+        WorldFromImu.Pose.Rotation.Normalize();
+        WorldFromCamera.Rotation.Normalize();
+    }
+
+    // Update headset position
+    if (VisionPositionEnabled && visionIsRecent)
+    {
+        // Integrate UMI and velocity here up to a fixed amount of time after vision. 
+        WorldFromImu.StoreAndIntegrateAccelerometer(accelInWorldFrame + AccelOffset, DeltaT);
+        // Position correction based on camera
+        applyPositionCorrection(DeltaT); 
+        // Compute where the neck pivot would be.
+        setNeckPivotFromPose(WorldFromImu.Pose);
+    }
+    else
+    {
+        // Fall back onto internal head model
+        // Use the last-known neck pivot position to figure out the expected IMU position.
+        // (should be the opposite of SensorFusion::setNeckPivotFromPose)
+        WorldFromNeck.Rotation = WorldFromImu.Pose.Rotation;
+        WorldFromImu.Pose = WorldFromNeck * (ImuFromCpf * CpfFromNeck).Inverted();
+
+        // We can't trust velocity past this point.
+        WorldFromImu.LinearVelocity = Vector3d(0,0,0);
+        WorldFromImu.LinearAcceleration = accelInWorldFrame;
+    }
+
+    // Compute the angular acceleration
+    WorldFromImu.AngularAcceleration = (FAngV.GetSize() >= 12 && DeltaT > 0) ? 
+        (FAngV.SavitzkyGolayDerivative12() / DeltaT) : Vector3d();
+
+    // Update the dead reckoning state used for incremental vision tracking
+    NextExposureRecord.ImuOnlyDelta.StoreAndIntegrateGyro(gyro, DeltaT);
+    NextExposureRecord.ImuOnlyDelta.StoreAndIntegrateAccelerometer(accelInWorldFrame, DeltaT);
+    NextExposureRecord.ImuOnlyDelta.TimeInSeconds = WorldFromImu.TimeInSeconds - LastMessageExposureFrame.CameraTimeSeconds;
+    NextExposureRecord.VisionTrackingAvailable &= (VisionPositionEnabled && visionIsRecent);
+
+	Recording::GetRecorder().LogData("sfTimeSeconds", WorldFromImu.TimeInSeconds);
+    Recording::GetRecorder().LogData("sfStage", (double)Stage);
+	Recording::GetRecorder().LogData("sfPose", WorldFromImu.Pose);
+	//Recorder::LogData("sfAngAcc", State.AngularAcceleration);
+	//Recorder::LogData("sfAngVel", State.AngularVelocity);
+	//Recorder::LogData("sfLinAcc", State.LinearAcceleration);
+	//Recorder::LogData("sfLinVel", State.LinearVelocity);
+
+    // Store the lockless state.    
+    LocklessState lstate;
+    lstate.StatusFlags       = Status_OrientationTracked;
+    if (VisionPositionEnabled)
+        lstate.StatusFlags  |= Status_PositionConnected;
+    if (VisionPositionEnabled && visionIsRecent)
+        lstate.StatusFlags  |= Status_PositionTracked;
+
+	//A convenient means to temporarily extract this flag
+	TPH_IsPositionTracked = visionIsRecent;
+
+    lstate.State        = WorldFromImu;
+    lstate.Temperature  = msg.Temperature;
+    lstate.Magnetometer = mag;    
+    UpdatedState.SetState(lstate);
+}
+
+void SensorFusion::handleExposure(const MessageExposureFrame& msg)
+{
+    NextExposureRecord.ExposureCounter = msg.CameraFrameCount;
+    NextExposureRecord.ExposureTime = msg.CameraTimeSeconds;
+    NextExposureRecord.WorldFromImu = WorldFromImu;
+    NextExposureRecord.ImuOnlyDelta.TimeInSeconds = msg.CameraTimeSeconds - LastMessageExposureFrame.CameraTimeSeconds;
+    ExposureRecordHistory.PushBack(NextExposureRecord);
+
+    // Every new exposure starts from zero
+    NextExposureRecord = ExposureRecord(); 
+    LastMessageExposureFrame = msg;
+}
+
+// If you have a known-good pose, this sets the neck pivot position.
+void SensorFusion::setNeckPivotFromPose(Transformd const &worldFromImu)
+{
+    WorldFromNeck = worldFromImu * ImuFromCpf * CpfFromNeck;
+}
+
+// These two functions need to be moved into Quat class
+// Compute a rotation required to transform "from" into "to". 
+Quatd vectorAlignmentRotation(const Vector3d &from, const Vector3d &to)
+{
+    Vector3d axis = from.Cross(to);
+    if (axis.LengthSq() == 0)
+        // this handles both collinear and zero-length input cases
+        return Quatd();
+    double angle = from.Angle(to);
+    return Quatd(axis, angle);
+}
+
+// Compute the part of the quaternion that rotates around Y axis
+Quatd extractYawRotation(const Quatd &error)
+{
+    if (error.y == 0)
+        return Quatd();
+    double phi = atan2(error.w, error.y);
+    double alpha = Mathd::Pi - 2 * phi;
+    return Quatd(Axis_Y, alpha);
+}
+
+void SensorFusion::applyPositionCorrection(double deltaT)
+{
+    // Each component of gainPos is equivalent to a Kalman gain of (sigma_process / sigma_observation)
+	const Vector3d gainPos = Vector3d(10, 10, 8);
+    const Vector3d gainVel = gainPos.EntrywiseMultiply(gainPos) * 0.5;
+    const Vector3d gainAccel = gainVel * 0.5;
+    const double snapThreshold = 0.1; // Large value (previously 0.01, which caused frequent jumping)
+
+    Vector3d correctionPos, correctionVel;
+    if (VisionError.Pose.Translation.LengthSq() > (snapThreshold * snapThreshold) ||
+        !(UpdatedState.GetState().StatusFlags & Status_PositionTracked))
+    {
+        // high error or just reacquired position from vision - apply full correction
+
+        // to know where we are right now, take the vision pose (which is slightly old)
+        // and update it using the imu data since then
+        PoseStated worldFromImuVision = WorldFromCamera * CameraFromImu;
+        for (unsigned int i = 0; i < ExposureRecordHistory.GetSize(); i++)
+            worldFromImuVision.AdvanceByDelta(ExposureRecordHistory.PeekFront(i).ImuOnlyDelta);
+        worldFromImuVision.AdvanceByDelta(NextExposureRecord.ImuOnlyDelta);
+
+        correctionPos = worldFromImuVision.Pose.Translation - WorldFromImu.Pose.Translation;
+        correctionVel = worldFromImuVision.LinearVelocity - WorldFromImu.LinearVelocity;
+        AccelOffset   = Vector3d();
+    }
+    else
+    {
+        correctionPos = VisionError.Pose.Translation.EntrywiseMultiply(gainPos) * deltaT;
+        correctionVel = VisionError.Pose.Translation.EntrywiseMultiply(gainVel) * deltaT;
+        AccelOffset  += VisionError.Pose.Translation.EntrywiseMultiply(gainAccel) * deltaT;
+    }
+
+    WorldFromImu.Pose.Translation += correctionPos;
+    WorldFromImu.LinearVelocity += correctionVel;
+
+    // Update the exposure records so that we don't apply the same correction twice
+    LastVisionExposureRecord.WorldFromImu.Pose.Translation += correctionPos;
+    LastVisionExposureRecord.WorldFromImu.LinearVelocity += correctionVel;
+    for (unsigned int i = 0; i < ExposureRecordHistory.GetSize(); i++)
+    {
+        PoseStated& state = ExposureRecordHistory.PeekBack(i).WorldFromImu;
+        state.Pose.Translation += correctionPos;
+        state.LinearVelocity += correctionVel;
+    }
+}
+
+void SensorFusion::applyVisionYawCorrection(double deltaT)
+{
+    const double gain = 0.25;
+    const double snapThreshold = 0.1;
+
+    Quatd yawError = extractYawRotation(VisionError.Pose.Rotation);
+
+    Quatd correction;
+    if (Alg::Abs(yawError.w) < cos(snapThreshold / 2)) // angle(yawError) > snapThreshold
+        // high error, jump to the vision position
+        correction = yawError;
+    else
+        correction = yawError.Nlerp(Quatd(), gain * deltaT);
+
+    WorldFromImu.Pose.Rotation = correction * WorldFromImu.Pose.Rotation;
+
+    // Update the exposure records so that we don't apply the same correction twice
+    LastVisionExposureRecord.WorldFromImu.Pose.Rotation = correction * LastVisionExposureRecord.WorldFromImu.Pose.Rotation;
+    for (unsigned int i = 0; i < ExposureRecordHistory.GetSize(); i++)
+    {
+        PoseStated& state = ExposureRecordHistory.PeekBack(i).WorldFromImu;
+        state.Pose.Rotation = correction * state.Pose.Rotation;
+    }
+}
+
+void SensorFusion::applyMagYawCorrection(Vector3d mag, double deltaT)
+{
+    const double minMagLengthSq   = Mathd::Tolerance; // need to use a real value to discard very weak fields
+    const double maxMagRefDist    = 0.1;
+    const double maxTiltError     = 0.05;
+    const double proportionalGain = 0.01;
+    const double integralGain     = 0.0005;
+
+    Vector3d magInWorldFrame = WorldFromImu.Pose.Rotate(mag);
+    // verify that the horizontal component is sufficient
+    if (magInWorldFrame.x * magInWorldFrame.x + magInWorldFrame.z * magInWorldFrame.z < minMagLengthSq)
+        return;
+    magInWorldFrame.Normalize();
+
+    // Delete a bad point
+    if (MagRefIdx >= 0 && MagRefs[MagRefIdx].Score < 0)
+    {
+        MagRefs.RemoveAtUnordered(MagRefIdx);
+        MagRefIdx = -1;
+    }
+
+    // Update the reference point if needed
+    if (MagRefIdx < 0 || mag.Distance(MagRefs[MagRefIdx].InImuFrame) > maxMagRefDist)
+    {
+        // Find a new one
+        MagRefIdx = -1;
+        double bestDist = maxMagRefDist;
+        for (unsigned int i = 0; i < MagRefs.GetSize(); i++)
+        {
+            double dist = mag.Distance(MagRefs[i].InImuFrame);
+            if (bestDist > dist)
+            {
+                bestDist = dist;
+                MagRefIdx = i;
+            }
+        }
+
+        // Create one if needed
+        if (MagRefIdx < 0 && MagRefs.GetSize() < MagMaxReferences)
+		{
+            MagRefs.PushBack(MagReferencePoint(mag, WorldFromImu.Pose, 1000));
+		}
+    }
+
+    if (MagRefIdx >= 0)
+    {
+        Vector3d magRefInWorldFrame = MagRefs[MagRefIdx].WorldFromImu.Rotate(MagRefs[MagRefIdx].InImuFrame);
+        magRefInWorldFrame.Normalize();
+
+        // If the vertical angle is wrong, decrease the score and do nothing
+        if (Alg::Abs(magRefInWorldFrame.y - magInWorldFrame.y) > maxTiltError)
+        {
+            MagRefs[MagRefIdx].Score -= 1;
+            return;
+        }
+
+        MagRefs[MagRefIdx].Score += 2;
+#if 0
+        // this doesn't seem to work properly, need to investigate
+        Quatd error = vectorAlignmentRotation(magW, magRefW);
+        Quatd yawError = extractYawRotation(error);
+#else
+        // Correction is computed in the horizontal plane
+        magInWorldFrame.y = magRefInWorldFrame.y = 0;
+        Quatd yawError = vectorAlignmentRotation(magInWorldFrame, magRefInWorldFrame);
+#endif                                                 
+        Quatd correction = yawError.Nlerp(Quatd(), proportionalGain * deltaT) *
+                           MagCorrectionIntegralTerm.Nlerp(Quatd(), deltaT);
+        MagCorrectionIntegralTerm = MagCorrectionIntegralTerm * yawError.Nlerp(Quatd(), integralGain * deltaT);
+
+        WorldFromImu.Pose.Rotation = correction * WorldFromImu.Pose.Rotation;
+    }
+}
+
+void SensorFusion::applyTiltCorrection(double deltaT)
+{
+    const double gain = 0.25;
+    const double snapThreshold = 0.1;
+    const Vector3d up(0, 1, 0);
+
+    Vector3d accelInWorldFrame = WorldFromImu.Pose.Rotate(FAccelInImuFrame.GetFilteredValue());
+    Quatd error = vectorAlignmentRotation(accelInWorldFrame, up);
+
+    Quatd correction;
+    if (FAccelInImuFrame.GetSize() == 1 || 
+        ((Alg::Abs(error.w) < cos(snapThreshold / 2) && FAccelInImuFrame.Confidence() > 0.75)))
+        // full correction for start-up
+        // or large error with high confidence
+        correction = error;
+    else if (FAccelInImuFrame.Confidence() > 0.5)
+        correction = error.Nlerp(Quatd(), gain * deltaT);
+    else
+        // accelerometer is unreliable due to movement
+        return;
+
+    WorldFromImu.Pose.Rotation = correction * WorldFromImu.Pose.Rotation;
+}
+
+void SensorFusion::applyCameraTiltCorrection(Vector3d accel, double deltaT)
+{
+    const double snapThreshold = 0.02; // in radians
+    const double maxCameraPositionOffset = 0.2;
+    const Vector3d up(0, 1, 0), forward(0, 0, -1);
+
+    // for startup use filtered value instead of instantaneous for stability
+    if (FAccelInCameraFrame.IsEmpty())
+        accel = FAccelInImuFrame.GetFilteredValue();
+
+    Transformd cameraFromImu = WorldFromCamera.Inverted() * VisionError.Pose * WorldFromImu.Pose;
+    // this is what the hypothetical camera-mounted accelerometer would show
+    Vector3d accelInCameraFrame = cameraFromImu.Rotate(accel);
+    FAccelInCameraFrame.Update(accelInCameraFrame, deltaT);
+    Vector3d cameraAccelInWorldFrame = WorldFromCamera.Rotate(FAccelInCameraFrame.GetFilteredValue());
+   
+    Quatd error1 = vectorAlignmentRotation(cameraAccelInWorldFrame, up);
+    // cancel out yaw rotation
+    Vector3d forwardCamera = (error1 * WorldFromCamera.Rotation).Rotate(forward);
+    forwardCamera.y = 0;
+    Quatd error2 = vectorAlignmentRotation(forwardCamera, forward);
+    // combined error
+    Quatd error = error2 * error1;
+
+    double confidence = FAccelInCameraFrame.Confidence();
+    // penalize the confidence if looking away from the camera
+    // TODO: smooth fall-off
+    if (CameraFromImu.Pose.Rotate(forward).Angle(forward) > 1)
+        confidence *= 0.5;
+
+	//Convenient global variable to temporarily extract this data.
+	TPH_CameraPoseConfidence = confidence;
+	//Allow override of confidence threshold
+	double confidenceThreshold = 0.75f;
+	if (TPH_CameraPoseConfidenceThresholdOverrideIfNonZero)
+    {
+		confidenceThreshold = TPH_CameraPoseConfidenceThresholdOverrideIfNonZero;
+	}
+
+    Quatd correction;
+    if (FAccelInCameraFrame.GetSize() == 1 ||
+        confidence > WorldFromCameraConfidence + 0.2 ||
+        // disabled due to false positives when moving side to side
+//        (Alg::Abs(error.w) < cos(5 * snapThreshold / 2) && confidence > 0.55) ||    
+        (Alg::Abs(error.w) < cos(snapThreshold / 2) && confidence > confidenceThreshold))
+    {
+        // large error with high confidence
+        correction = error;
+        // update the confidence level
+        WorldFromCameraConfidence = confidence;
+    }
+    else
+    {
+        // accelerometer is unreliable due to movement
+        return;
+    }
+
+    Transformd newWorldFromCamera(correction * WorldFromCamera.Rotation, Vector3d());
+
+    // compute a camera position change that together with the camera rotation would result in zero player movement
+    newWorldFromCamera.Translation += (WorldFromCamera * CameraFromImu.Pose).Translation -
+        (newWorldFromCamera * CameraFromImu.Pose).Translation;
+    // if the new position is too far, reset to default 
+    // (can't hide the rotation, might as well use it to reset the position)
+    if (newWorldFromCamera.Translation.DistanceSq(DefaultWorldFromCamera.Translation) > maxCameraPositionOffset * maxCameraPositionOffset)
+        newWorldFromCamera.Translation = DefaultWorldFromCamera.Translation;
+
+    WorldFromCamera = newWorldFromCamera;
+
+	//Convenient global variable to temporarily extract this data.
+	TPH_CameraPoseOrientationWxyz[0] = (float) WorldFromCamera.Rotation.w;
+	TPH_CameraPoseOrientationWxyz[1] = (float) WorldFromCamera.Rotation.x;
+	TPH_CameraPoseOrientationWxyz[2] = (float) WorldFromCamera.Rotation.y;
+	TPH_CameraPoseOrientationWxyz[3] = (float) WorldFromCamera.Rotation.z;
+}
+
+void SensorFusion::applyFocusCorrection(double deltaT)
+{
+	Vector3d up = Vector3d(0, 1, 0);
+	double gain = 0.01;
+	Vector3d currentDir = WorldFromImu.Pose.Rotate(Vector3d(0, 0, 1));
+
+	Vector3d focusYawComponent = FocusDirection.ProjectToPlane(up);
+	Vector3d currentYawComponent = currentDir.ProjectToPlane(up);
+
+	double angle = focusYawComponent.Angle(currentYawComponent);
+
+	if( angle > FocusFOV )
+	{
+		Quatd yawError;
+		if ( FocusFOV != 0.0f)
+		{
+			Vector3d lFocus = Quatd(up, -FocusFOV).Rotate(focusYawComponent);
+			Vector3d rFocus = Quatd(up, FocusFOV).Rotate(focusYawComponent);
+			double lAngle = lFocus.Angle(currentYawComponent);
+			double rAngle = rFocus.Angle(currentYawComponent);
+			if(lAngle < rAngle)
+			{
+				yawError = vectorAlignmentRotation(currentDir, lFocus);
+			} 
+            else
+			{
+				yawError = vectorAlignmentRotation(currentDir, rFocus);
+			}
+		} 
+        else
+		{
+			yawError = vectorAlignmentRotation(currentYawComponent, focusYawComponent);
+		}
+
+		Quatd correction = yawError.Nlerp(Quatd(), gain * deltaT);
+        WorldFromImu.Pose.Rotation = correction * WorldFromImu.Pose.Rotation;
+	}
+}
+
+//------------------------------------------------------------------------------------
+// Focus filter setting functions
+
+void SensorFusion::SetFocusDirection()
+{
+	SetFocusDirection(WorldFromImu.Pose.Rotate(Vector3d(0.0, 0.0, 1.0)));
+}
+
+void SensorFusion::SetFocusDirection(Vector3d direction)
+{
+	FocusDirection = direction;
+}
+
+void SensorFusion::SetFocusFOV(double fov)
+{
+	OVR_ASSERT(fov >= 0.0);
+	FocusFOV = fov;
+}
+
+void SensorFusion::ClearFocus()
+{
+	FocusDirection = Vector3d(0.0, 0.0, 0.0);
+	FocusFOV = 0.0f;
+}
+
+//-------------------------------------------------------------------------------------
+// Head model functions.
+
+// Sets up head-and-neck model and device-to-pupil dimensions from the user's profile.
+void SensorFusion::SetUserHeadDimensions(Profile const &profile, HmdRenderInfo const &hmdRenderInfo)
+{
+    float neckeye[2];
+    int count = profile.GetFloatValues(OVR_KEY_NECK_TO_EYE_DISTANCE, neckeye, 2);
+    // Make sure these are vaguely sensible values.
+    if (count == 2)
+    {
+        OVR_ASSERT ( ( neckeye[0] > 0.05f ) && ( neckeye[0] < 0.5f ) );
+        OVR_ASSERT ( ( neckeye[1] > 0.05f ) && ( neckeye[1] < 0.5f ) );
+        SetHeadModel ( Vector3f ( 0.0, neckeye[1], -neckeye[0] ) );
+    }
+
+    // Find the distance from the center of the screen to the "center eye"
+    // This center eye is used by systems like rendering & audio to represent the player,
+    // and they will handle the offsets needed from there to each actual eye.
+
+    // HACK HACK HACK
+    // We know for DK1 the screen->lens surface distance is roughly 0.049f, and that the faceplate->lens is 0.02357f.
+    // We're going to assume(!!!!) that all HMDs have the same screen->faceplate distance.
+    // Crystal Cove was measured to be roughly 0.025 screen->faceplate which agrees with this assumption.
+    // TODO: do this properly!  Update:  Measured this at 0.02733 with a CC prototype, CES era (PT7), on 2/19/14 -Steve
+    float screenCenterToMidplate = 0.02733f;
+    float centerEyeRelief = hmdRenderInfo.GetEyeCenter().ReliefInMeters;
+    float centerPupilDepth = screenCenterToMidplate + hmdRenderInfo.LensSurfaceToMidplateInMeters + centerEyeRelief;
+    SetCenterPupilDepth ( centerPupilDepth );
+
+    Recording::GetRecorder().RecordUserParams(GetHeadModel(), GetCenterPupilDepth());
+}
+
+Vector3f SensorFusion::GetHeadModel() const
+{
+    return (Vector3f)CpfFromNeck.Inverted().Translation;
+}
+
+void SensorFusion::SetHeadModel(const Vector3f &headModel, bool resetNeckPivot /*= true*/ )
+{
+    Lock::Locker lockScope(pHandler->GetHandlerLock());
+    // The head model should look something like (0, 0.12, -0.12), so
+    // these asserts are to try to prevent sign problems, as
+    // they can be subtle but nauseating!
+    OVR_ASSERT ( headModel.y > 0.0f );
+    OVR_ASSERT ( headModel.z < 0.0f );
+    CpfFromNeck = Transformd(Quatd(), (Vector3d)headModel).Inverted();
+    if ( resetNeckPivot )
+    {
+        setNeckPivotFromPose ( WorldFromImu.Pose );
+    }
+}
+
+float SensorFusion::GetCenterPupilDepth() const
+{
+    return CenterPupilDepth;
+}
+
+void SensorFusion::SetCenterPupilDepth(float centerPupilDepth)
+{
+    CenterPupilDepth = centerPupilDepth;
+
+    Transformd screenFromCpf(Quatd(), Vector3d(0, 0, centerPupilDepth));
+    ImuFromCpf = ImuFromScreen * screenFromCpf;
+	
+    setNeckPivotFromPose ( WorldFromImu.Pose );
+}
+
+//-------------------------------------------------------------------------------------
+
+// This is a "perceptually tuned predictive filter", which means that it is optimized
+// for improvements in the VR experience, rather than pure error.  In particular,
+// jitter is more perceptible at lower speeds whereas latency is more perceptible
+// after a high-speed motion.  Therefore, the prediction interval is dynamically
+// adjusted based on speed.  Significant more research is needed to further improve
+// this family of filters.
+static Transform<double> calcPredictedPose(const PoseState<double>& poseState, double predictionDt)
+{
+    Transform<double> pose   = poseState.Pose;
+	const double linearCoef  = 1.0;
+	Vector3d angularVelocity = poseState.AngularVelocity;
+	double   angularSpeed    = angularVelocity.Length();
+
+	// This could be tuned so that linear and angular are combined with different coefficients
+	double speed             = angularSpeed + linearCoef * poseState.LinearVelocity.Length();
+
+	const double slope       = 0.2; // The rate at which the dynamic prediction interval varies
+	double candidateDt       = slope * speed; // TODO: Replace with smoothstep function
+
+	double dynamicDt         = predictionDt;
+
+	// Choose the candidate if it is shorter, to improve stability
+	if (candidateDt < predictionDt)
+		dynamicDt = candidateDt;
+
+    if (angularSpeed > 0.001)
+        pose.Rotation = pose.Rotation * Quatd(angularVelocity, angularSpeed * dynamicDt);
+
+    pose.Translation += poseState.LinearVelocity * dynamicDt;
+
+    return pose;
+}
+
+
+Transformf SensorFusion::GetPoseAtTime(double absoluteTime) const
+{
+    SensorState ss = GetSensorStateAtTime ( absoluteTime );
+    return ss.Predicted.Pose;
+}
+
+
+SensorState SensorFusion::GetSensorStateAtTime(double absoluteTime) const
+{          
+     const LocklessState lstate = UpdatedState.GetState();
+     // Delta time from the last available data
+     const double pdt = absoluteTime - lstate.State.TimeInSeconds;
+     
+     SensorState ss;
+     ss.Recorded     = PoseStatef(lstate.State);
+     ss.Temperature  = lstate.Temperature;
+     ss.Magnetometer = Vector3f(lstate.Magnetometer);
+     ss.StatusFlags  = lstate.StatusFlags;
+
+     ss.Predicted               = ss.Recorded;
+     ss.Predicted.TimeInSeconds = absoluteTime;
+    
+     // Do prediction logic and ImuFromCpf transformation
+     ss.Recorded.Pose  = Transformf(lstate.State.Pose * ImuFromCpf);
+     ss.Predicted.Pose = Transformf(calcPredictedPose(lstate.State, pdt) * ImuFromCpf);
+     return ss;
+}
+
+unsigned SensorFusion::GetStatus() const
+{
+    return UpdatedState.GetState().StatusFlags;
+}
+
+//-------------------------------------------------------------------------------------
+
+void SensorFusion::OnMessage(const MessageBodyFrame& msg)
+{
+    OVR_ASSERT(!IsAttachedToSensor());
+    handleMessage(msg);
+}
+
+//-------------------------------------------------------------------------------------
+
+void SensorFusion::BodyFrameHandler::OnMessage(const Message& msg)
+{
+	Recording::GetRecorder().RecordMessage(msg);
+    if (msg.Type == Message_BodyFrame)
+        pFusion->handleMessage(static_cast<const MessageBodyFrame&>(msg));
+    if (msg.Type == Message_ExposureFrame)
+        pFusion->handleExposure(static_cast<const MessageExposureFrame&>(msg));
+}
+
+} // namespace OVR
diff --git a/LibOVR/Src/OVR_SensorFusion.h b/LibOVR/Src/OVR_SensorFusion.h
new file mode 100644
index 0000000..2a17920
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorFusion.h
@@ -0,0 +1,582 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_SensorFusion.h
+Content     :   Methods that determine head orientation from sensor data over time
+Created     :   October 9, 2012
+Authors     :   Michael Antonov, Steve LaValle, Dov Katz, Max Katsev, Dan Gierl
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_SensorFusion_h
+#define OVR_SensorFusion_h
+
+#include "OVR_Device.h"
+#include "OVR_SensorFilter.h"
+#include "Kernel/OVR_Timer.h"
+#include "Kernel/OVR_Threads.h"
+#include "Kernel/OVR_Lockless.h"
+
+// CAPI forward declarations.
+typedef struct ovrPoseStatef_ ovrPoseStatef;
+typedef struct ovrSensorState_ ovrSensorState;
+
+namespace OVR {
+
+struct HmdRenderInfo;
+
+//-------------------------------------------------------------------------------------
+// ***** Sensor State
+
+// These values are reported as compatible with C API.
+
+
+// PoseState describes the complete pose, or a rigid body configuration, at a
+// point in time, including first and second derivatives. It is used to specify
+// instantaneous location and movement of the headset.
+// SensorState is returned as a part of the sensor state.
+
+template<class T>
+class PoseState
+{
+public:
+    typedef typename CompatibleTypes<Transform<T> >::Type CompatibleType;
+
+    PoseState() : TimeInSeconds(0.0) { }
+    // float <-> double conversion constructor.
+    explicit PoseState(const PoseState<typename Math<T>::OtherFloatType> &src)
+        : Pose(src.Pose),
+          AngularVelocity(src.AngularVelocity), LinearVelocity(src.LinearVelocity),
+          AngularAcceleration(src.AngularAcceleration), LinearAcceleration(src.LinearAcceleration),
+          TimeInSeconds(src.TimeInSeconds)
+    { }
+
+    // C-interop support: PoseStatef <-> ovrPoseStatef
+    PoseState(const typename CompatibleTypes<PoseState<T> >::Type& src)
+        : Pose(src.Pose),
+          AngularVelocity(src.AngularVelocity), LinearVelocity(src.LinearVelocity),
+          AngularAcceleration(src.AngularAcceleration), LinearAcceleration(src.LinearAcceleration),
+          TimeInSeconds(src.TimeInSeconds)
+    { }
+
+    operator typename CompatibleTypes<PoseState<T> >::Type () const
+    {
+        typename CompatibleTypes<PoseState<T> >::Type result;
+        result.Pose		            = Pose;
+        result.AngularVelocity      = AngularVelocity;
+        result.LinearVelocity       = LinearVelocity;
+        result.AngularAcceleration  = AngularAcceleration;
+        result.LinearAcceleration   = LinearAcceleration;
+        result.TimeInSeconds        = TimeInSeconds;
+        return result;
+    }
+
+
+    Transform<T> Pose;
+    Vector3<T>  AngularVelocity;
+    Vector3<T>  LinearVelocity;
+    Vector3<T>  AngularAcceleration;
+    Vector3<T>  LinearAcceleration;
+    // Absolute time of this state sample; always a double measured in seconds.
+    double      TimeInSeconds;
+
+    
+    // ***** Helpers for Pose integration
+
+    // Stores and integrates gyro angular velocity reading for a given time step.
+    void StoreAndIntegrateGyro(Vector3d angVel, double dt);
+    // Stores and integrates position/velocity from accelerometer reading for a given time step.
+    void StoreAndIntegrateAccelerometer(Vector3d linearAccel, double dt);
+    
+    // Performs integration of state by adding next state delta to it
+    // to produce a combined state change
+    void AdvanceByDelta(const PoseState<T>& delta);
+};
+
+
+
+// External API returns pose as float, but uses doubles internally for quaternion precision.
+typedef PoseState<float>  PoseStatef;
+typedef PoseState<double> PoseStated;
+
+
+//-------------------------------------------------------------------------------------
+// ***** Sensor State
+
+
+// Bit flags describing the current status of sensor tracking.
+enum StatusBits
+{
+    Status_OrientationTracked    = 0x0001,   // Orientation is currently tracked (connected and in use).
+    Status_PositionTracked       = 0x0002,   // Position is currently tracked (false if out of range).
+    Status_PositionConnected     = 0x0020,   // Position tracking HW is conceded.
+   // Status_HMDConnected          = 0x0080    // HMD Display is available & connected.
+};
+
+
+// Full state of of the sensor reported by GetSensorState() at a given absolute time.
+class SensorState
+{
+public:
+    SensorState() : Temperature(0), StatusFlags(0) { }
+
+    // C-interop support
+    SensorState(const ovrSensorState& s);
+    operator ovrSensorState () const;
+
+    // Pose state at the time that SensorState was requested.
+    PoseStatef   Predicted;
+    // Actual recorded pose configuration based on sensor sample at a 
+    // moment closest to the requested time.
+    PoseStatef   Recorded;
+
+    // Calibrated magnetometer reading, in Gauss, at sample time.
+    Vector3f     Magnetometer;
+    // Sensor temperature reading, in degrees Celsius, at sample time.
+    float        Temperature;
+    // Sensor status described by ovrStatusBits.
+    unsigned int StatusFlags;
+};
+
+
+
+//-------------------------------------------------------------------------------------
+
+class VisionHandler
+{
+public:
+    virtual void        OnVisionSuccess(const Transform<double>& cameraFromImu, UInt32 exposureCounter) = 0;
+    virtual void        OnVisionPreviousFrame(const Transform<double>& cameraFromImu) = 0;
+	virtual void		OnVisionFailure() = 0;
+
+    // Get a configuration that represents the change over a short time interval
+    virtual Transform<double> GetVisionPrediction(UInt32 exposureCounter) = 0;
+};
+
+//-------------------------------------------------------------------------------------
+// ***** SensorFusion
+
+// SensorFusion class accumulates Sensor notification messages to keep track of
+// orientation, which involves integrating the gyro and doing correction with gravity.
+// Magnetometer based yaw drift correction is also supported; it is usually enabled
+// automatically based on loaded magnetometer configuration.
+// Orientation is reported as a quaternion, from which users can obtain either the
+// rotation matrix or Euler angles.
+//
+// The class can operate in two ways:
+//  - By user manually passing MessageBodyFrame messages to the OnMessage() function. 
+//  - By attaching SensorFusion to a SensorDevice, in which case it will
+//    automatically handle notifications from that device.
+
+
+class SensorFusion : public NewOverrideBase, public VisionHandler
+{
+	friend class SensorFusionDebug;
+
+    enum
+    {
+        MagMaxReferences = 1000
+    };        
+
+public:
+
+	// -------------------------------------------------------------------------------
+	// Critical components for tiny API
+
+    SensorFusion(SensorDevice* sensor = 0);
+    ~SensorFusion();
+
+    // Attaches this SensorFusion to the IMU sensor device, from which it will receive
+    // notification messages. If a sensor is attached, manual message notification
+    // is not necessary. Calling this function also resets SensorFusion state.
+    bool                        AttachToSensor(SensorDevice* sensor);
+
+    // Returns true if this Sensor fusion object is attached to the IMU.
+    bool                        IsAttachedToSensor() const;
+
+    // Sets up head-and-neck model and device-to-pupil dimensions from the user's profile and the HMD stats.
+    // This copes elegantly if profile is NULL.
+    void SetUserHeadDimensions(Profile const &profile, HmdRenderInfo const &hmdRenderInfo);
+
+	// Get the predicted pose (orientation, position) of the center pupil frame (CPF) at a specific point in time.
+	Transformf                  GetPoseAtTime(double absoluteTime) const;
+
+    // Get the full dynamical system state of the CPF, which includes velocities and accelerations,
+    // predicted at a specified absolute point in time.
+    SensorState                 GetSensorStateAtTime(double absoluteTime) const;
+
+    // Get the sensor status (same as GetSensorStateAtTime(...).Status)
+    unsigned int                GetStatus() const;
+
+	// End tiny API components
+    // -------------------------------------------------------------------------------
+
+    // Resets the current orientation.
+    void        Reset                        ();
+
+    // Configuration
+    void        EnableMotionTracking(bool enable = true)    { MotionTrackingEnabled = enable; }
+    bool        IsMotionTrackingEnabled() const             { return MotionTrackingEnabled;   }
+    
+    // Accelerometer/Gravity Correction Control
+    // Enables/disables gravity correction (on by default).
+    void        SetGravityEnabled   (bool enableGravity);
+    bool        IsGravityEnabled    () const;
+
+	// Vision Position and Orientation Configuration
+    // -----------------------------------------------
+	bool        IsVisionPositionEnabled       () const;
+	void        SetVisionPositionEnabled      (bool enableVisionPosition);
+    
+    // compensates for a tilted camera
+	void        SetCameraTiltCorrectionEnabled(bool enable);
+    bool        IsCameraTiltCorrectionEnabled () const;
+
+    // Message Handling Logic
+    // -----------------------------------------------
+    // Notifies SensorFusion object about a new BodyFrame 
+    // message from a sensor.
+    // Should be called by user if not attached to sensor.
+    void        OnMessage                (const MessageBodyFrame& msg);
+   
+
+	// Interaction with vision
+    // -----------------------------------------------
+	// Handle observation from vision system (orientation, position, time)
+    virtual void        OnVisionSuccess(const Transform<double>& cameraFromImu, UInt32 exposureCounter);
+
+    virtual void        OnVisionPreviousFrame(const Transform<double>& cameraFromImu);
+	virtual void		OnVisionFailure();
+    // Get a configuration that represents the change over a short time interval
+    virtual Transform<double> GetVisionPrediction(UInt32 exposureCounter);
+
+    double              GetTime                ()     const;
+    double              GetVisionLatency       ()     const;
+
+
+	// Detailed head dimension control
+    // -----------------------------------------------
+	// These are now deprecated in favour of SetUserHeadDimensions()
+	Vector3f                    GetHeadModel() const;
+    void                        SetHeadModel(const Vector3f &headModel, bool resetNeckPivot = true );
+	float                       GetCenterPupilDepth() const;
+    void                        SetCenterPupilDepth(float centerPupilDepth);
+
+
+    // Magnetometer and Yaw Drift Section:
+    // ---------------------------------------
+
+    // Enables/disables magnetometer based yaw drift correction. 
+    // Must also have mag calibration data for this correction to work.
+	void        SetYawCorrectionEnabled(bool enable);
+    // Determines if yaw correction is enabled.
+    bool        IsYawCorrectionEnabled () const;
+
+	// Clear the reference points associating
+    // mag readings with orientations
+	void        ClearMagReferences     ();
+
+	// Sets the focus filter direction to the current HMD direction
+    void		SetFocusDirection();
+    // Sets the focus filter to a direction in the body frame. Once set, a complementary filter
+    // will very slowly drag the world to keep the direction of the HMD within the FOV of the focus
+    void		SetFocusDirection(Vector3d direction);
+    // Sets the FOV (in radians) of the focus. When the yaw difference between the HMD's current pose
+    // and the focus is smaller than the FOV, the complementary filter does not act.
+    void		SetFocusFOV(double rads);
+    // Turns off the focus filter (equivalent to setting the focus to 0
+    void		ClearFocus();
+
+private:
+  
+    // -----------------------------------------------
+    
+	class BodyFrameHandler : public NewOverrideBase, public MessageHandler
+    {
+        SensorFusion* pFusion;
+    public:
+        BodyFrameHandler(SensorFusion* fusion) 
+            : pFusion(fusion) {}
+
+        ~BodyFrameHandler();
+
+        virtual void OnMessage(const Message& msg);
+        virtual bool SupportsMessageType(MessageType type) const;
+    };   
+
+
+    // -----------------------------------------------
+
+    // State version stored in lockless updater "queue" and used for 
+    // prediction by GetPoseAtTime/GetSensorStateAtTime
+    struct LocklessState
+    {        
+        PoseState<double>  State;
+        float              Temperature;
+        Vector3d           Magnetometer;
+        unsigned int       StatusFlags;
+
+        LocklessState() : Temperature(0.0), StatusFlags(0) { };
+    };
+
+
+    // -----------------------------------------------
+
+    // Entry describing the state of the headset at the time of an exposure as reported by the DK2 board.
+    // This is used in combination with the vision data for 
+    // incremental tracking based on IMU change and for drift correction
+    struct ExposureRecord
+    {
+		UInt32            ExposureCounter;
+        double            ExposureTime;
+        // State of the headset at the time of exposure
+        PoseState<double> WorldFromImu;  
+        // Change in state since the last exposure based on IMU data only
+        PoseState<double> ImuOnlyDelta;
+        // Did we have tracking for the entire interval between exposures
+        bool              VisionTrackingAvailable;
+
+		ExposureRecord() : ExposureCounter(0), ExposureTime(0.0), VisionTrackingAvailable(true) { }
+        ExposureRecord(UInt32 exposureCounter, double exposureTime, 
+            const PoseState<double>& worldFromImu, const PoseState<double>& imuOnlyDelta)
+            : ExposureCounter(exposureCounter), ExposureTime(exposureTime),
+              WorldFromImu(worldFromImu), ImuOnlyDelta(imuOnlyDelta), VisionTrackingAvailable(true) { }
+    };
+
+    // -----------------------------------------------
+
+    // Entry describing the magnetometer reference point
+    // Used for mag yaw correction
+    struct MagReferencePoint
+    {
+        Vector3d          InImuFrame;
+        Transformd        WorldFromImu;
+		int				  Score;
+
+        MagReferencePoint() { }
+        MagReferencePoint(const Vector3d& inImuFrame, const Transformd& worldFromImu, int score)
+            : InImuFrame(inImuFrame), WorldFromImu(worldFromImu), Score(score) { }
+    };
+
+    // -----------------------------------------------
+
+    // The phase of the head as estimated by sensor fusion
+	PoseState<double> WorldFromImu;
+
+    // State that can be read without any locks, so that high priority rendering thread
+    // doesn't have to worry about being blocked by a sensor/vision threads that got preempted.
+    LocklessUpdater<LocklessState>	UpdatedState;
+
+    // The pose we got from Vision, augmented with velocity information from numerical derivatives
+    PoseState<double>       CameraFromImu;    
+    // Difference between the vision and sensor fusion poses at the time of last exposure adjusted
+    // by all the corrections applied since then
+    // NB: this one is unlike all the other poses/transforms we use, since it's a difference 
+    // between 2 WorldFromImu transforms, but is stored in the world frame, not the IMU frame
+    // (see computeVisionError() for details)
+    // For composition purposes it should be considered a WorldFromWorld transform, where the left
+    // side comes from vision and the right - from sensor fusion
+    PoseState<double>       VisionError;
+    // Past exposure records between the last update from vision and now
+    // (should only be one record unless vision latency is high)
+    CircularBuffer<ExposureRecord> ExposureRecordHistory;
+    // ExposureRecord that corresponds to the last pose we got from vision
+    ExposureRecord          LastVisionExposureRecord;
+    // Incomplete ExposureRecord that will go into the history buffer when 
+    // the new MessageExposureFrame is received
+    ExposureRecord          NextExposureRecord;
+    // Timings of the previous exposure, used to populate ExposureRecordHistory
+    MessageExposureFrame    LastMessageExposureFrame;
+    // Time of the last vision update
+    double                  LastVisionAbsoluteTime;
+
+    unsigned int            Stage;
+    BodyFrameHandler       *pHandler;
+
+	Vector3d				FocusDirection;
+	double					FocusFOV;
+
+    SensorFilterBodyFrame   FAccelInImuFrame, FAccelInCameraFrame;
+    SensorFilterd           FAngV;
+
+    Vector3d                AccelOffset;
+
+    bool                    EnableGravity;
+
+    bool                    EnableYawCorrection;
+    bool                    MagCalibrated;
+    Array<MagReferencePoint> MagRefs;
+    int                     MagRefIdx;
+    Quatd                   MagCorrectionIntegralTerm;
+
+    bool                    EnableCameraTiltCorrection;
+    // Describes the pose of the camera in the world coordinate system
+    Transformd              WorldFromCamera;
+    double                  WorldFromCameraConfidence;
+
+    bool                    MotionTrackingEnabled;
+    bool                    VisionPositionEnabled;
+
+    // This is a signed distance, but positive because Z increases looking inward.
+    // This is expressed relative to the IMU in the HMD and corresponds to the location
+    // of the cyclopean virtual camera focal point if both the physical and virtual 
+    // worlds are isometrically mapped onto each other.  -Steve
+    float                   CenterPupilDepth;
+    // Describes the position of the user eyes relative to the IMU
+    Transformd              ImuFromCpf;
+    // Position of the center of the screen relative to the IMU (loaded from the headset firmware)
+    Transformd              ImuFromScreen;
+    // Built-in head model for faking position using orientation only 
+    Transformd              CpfFromNeck;
+    // Last known base of the neck pose used for head model computations
+    Transformd              WorldFromNeck;
+
+    //---------------------------------------------    
+
+    // Internal handler for messages
+    // bypasses error checking.
+    void        handleMessage(const MessageBodyFrame& msg);
+    void        handleExposure(const MessageExposureFrame& msg);
+
+    // Compute the difference between vision and sensor fusion data
+    PoseStated  computeVisionError();
+    // Apply headset yaw correction from magnetometer
+	// for models without camera or when camera isn't available
+	void        applyMagYawCorrection(Vector3d mag, double deltaT);
+    // Apply headset tilt correction from the accelerometer
+    void        applyTiltCorrection(double deltaT);
+    // Apply headset yaw correction from the camera
+    void        applyVisionYawCorrection(double deltaT);
+    // Apply headset position correction from the camera
+    void        applyPositionCorrection(double deltaT);
+    // Apply camera tilt correction from the accelerometer
+    void        applyCameraTiltCorrection(Vector3d accel, double deltaT);
+	// Apply camera focus correction
+	void		applyFocusCorrection(double deltaT);
+
+    // If you have a known-good pose, this sets the neck pivot position.
+    void        setNeckPivotFromPose ( Transformd const &pose );
+};
+
+
+
+//-------------------------------------------------------------------------------------
+// ***** SensorFusion - Inlines
+
+inline bool SensorFusion::IsAttachedToSensor() const  
+{ 
+    return pHandler->IsHandlerInstalled(); 
+}
+
+inline void SensorFusion::SetGravityEnabled(bool enableGravity)     
+{ 
+    EnableGravity = enableGravity; 
+}   
+
+inline bool SensorFusion::IsGravityEnabled() const
+{
+    return EnableGravity;
+}
+
+inline void SensorFusion::SetYawCorrectionEnabled(bool enable)
+{ 
+    EnableYawCorrection = enable; 
+}
+
+inline bool SensorFusion::IsYawCorrectionEnabled() const          
+{
+    return EnableYawCorrection;
+}
+
+inline bool SensorFusion::IsVisionPositionEnabled() const             
+{ 
+    return VisionPositionEnabled;
+}
+
+inline void SensorFusion::SetVisionPositionEnabled(bool enableVisionPosition)  
+{ 
+    VisionPositionEnabled = enableVisionPosition;
+}
+
+inline void SensorFusion::SetCameraTiltCorrectionEnabled(bool enable)   
+{
+    EnableCameraTiltCorrection = enable; 
+}
+
+inline bool SensorFusion::IsCameraTiltCorrectionEnabled() const       
+{
+    return EnableCameraTiltCorrection;
+}
+
+inline double SensorFusion::GetVisionLatency() const
+{
+    return LastVisionAbsoluteTime - CameraFromImu.TimeInSeconds;
+}
+
+inline double SensorFusion::GetTime() const 
+{ 
+    return Timer::GetSeconds(); 
+}
+
+inline SensorFusion::BodyFrameHandler::~BodyFrameHandler()
+{
+    RemoveHandlerFromDevices();
+}
+
+inline bool SensorFusion::BodyFrameHandler::SupportsMessageType(MessageType type) const
+{
+    return (type == Message_BodyFrame || type == Message_ExposureFrame);
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** PoseState - Inlines
+
+// Stores and integrates gyro angular velocity reading for a given time step.
+template<class T>
+void PoseState<T>::StoreAndIntegrateGyro(Vector3d angVel, double dt)
+{
+    AngularVelocity = angVel;
+    double angle = angVel.Length() * dt;
+    if (angle > 0)
+        Pose.Rotation = Pose.Rotation * Quatd(angVel, angle);
+}
+
+template<class T>
+void PoseState<T>::StoreAndIntegrateAccelerometer(Vector3d linearAccel, double dt)
+{
+    LinearAcceleration = linearAccel;
+    Pose.Translation  += LinearVelocity * dt + LinearAcceleration * (dt * dt * 0.5);
+    LinearVelocity    += LinearAcceleration * dt;
+}
+
+// Performs integration of state by adding next state delta to it
+// to produce a combined state change
+template<class T>
+void PoseState<T>::AdvanceByDelta(const PoseState<T>& delta)
+{
+    Pose.Rotation     = Pose.Rotation * delta.Pose.Rotation;
+    Pose.Translation += delta.Pose.Translation + LinearVelocity * delta.TimeInSeconds;
+    LinearVelocity   += delta.LinearVelocity;
+    TimeInSeconds    += delta.TimeInSeconds;
+}
+
+} // namespace OVR
+#endif
diff --git a/LibOVR/Src/OVR_SensorFusionDebug.h b/LibOVR/Src/OVR_SensorFusionDebug.h
new file mode 100644
index 0000000..0fc7eb5
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorFusionDebug.h
@@ -0,0 +1,82 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_SensorFusionDebug.h
+Content     :   Friend proxy to allow debugging access to SensorFusion
+Created     :   April 16, 2014
+Authors     :   Dan Gierl
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_SensorFusionDebug_h
+#define OVR_SensorFusionDebug_h
+
+#include "OVR_SensorFusion.h"
+
+namespace OVR {
+
+class SensorFusionDebug
+{
+private:
+
+	SensorFusion *	sf;
+
+public:
+
+	SensorFusionDebug (SensorFusion * const sf) :
+		sf(sf)
+	{
+	}
+	
+	// Returns the number of magnetometer reference points currently gathered
+	int			GetNumMagRefPoints		() const;
+	// Returns the index of the magnetometer reference point being currently used
+	int			GetCurMagRefPointIdx	() const;
+	// Returns a copy of all the data associated with a magnetometer reference point
+	// This includes it's score, the magnetometer reading as a vector,
+	// and the HMD's pose at the time it was gathered
+	void		GetMagRefData			(int idx, int * score, Vector3d * magBF, Quatd * magPose) const;
+
+};
+
+//------------------------------------------------------------------------------------
+// Magnetometer reference point access functions
+
+int SensorFusionDebug::GetNumMagRefPoints() const
+{
+	return (int)sf->MagRefs.GetSize();
+}
+
+int SensorFusionDebug::GetCurMagRefPointIdx() const
+{
+	return sf->MagRefIdx;
+}
+
+void SensorFusionDebug::GetMagRefData(int idx, int * score, Vector3d * magBF, Quatd * magPose) const
+{
+	OVR_ASSERT(idx >= 0 && idx < GetNumMagRefPoints());
+	*score = sf->MagRefs[idx].Score;
+	*magBF = sf->MagRefs[idx].InImuFrame;
+	*magPose = sf->MagRefs[idx].WorldFromImu.Rotation;
+}
+
+} // OVR
+
+#endif
\ No newline at end of file
diff --git a/LibOVR/Src/OVR_SensorImpl.cpp b/LibOVR/Src/OVR_SensorImpl.cpp
new file mode 100644
index 0000000..91ae7e0
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorImpl.cpp
@@ -0,0 +1,1165 @@
+/************************************************************************************
+
+Filename    :   OVR_SensorImpl.cpp
+Content     :   Oculus Sensor device implementation.
+Created     :   March 7, 2013
+Authors     :   Lee Cooper, Dov Katz
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_SensorImpl.h"
+#include "OVR_Sensor2Impl.h"
+#include "OVR_SensorImpl_Common.h"
+#include "OVR_JSON.h"
+#include "OVR_Profile.h"
+#include "Kernel/OVR_Alg.h"
+#include <time.h>
+
+// HMDDeviceDesc can be created/updated through Sensor carrying DisplayInfo.
+
+#include "Kernel/OVR_Timer.h"
+
+//extern FILE *SF_LOG_fp;
+
+namespace OVR {
+
+using namespace Alg;
+
+//-------------------------------------------------------------------------------------
+// ***** Oculus Sensor-specific packet data structures
+
+enum {    
+    Sensor_VendorId  = Oculus_VendorId,
+    Sensor_Tracker_ProductId = Device_Tracker_ProductId,
+    Sensor_Tracker2_ProductId = Device_Tracker2_ProductId,
+    Sensor_KTracker_ProductId = Device_KTracker_ProductId,
+
+    Sensor_BootLoader   = 0x1001,
+
+    Sensor_DefaultReportRate = 500, // Hz
+    Sensor_MaxReportRate     = 1000 // Hz
+};
+
+
+// Messages we care for
+enum TrackerMessageType
+{
+    TrackerMessage_None              = 0,
+    TrackerMessage_Sensors           = 1,
+    TrackerMessage_Unknown           = 0x100,
+    TrackerMessage_SizeError         = 0x101,
+};
+
+
+struct TrackerSensors
+{
+    UByte	SampleCount;
+    UInt16	Timestamp;
+    UInt16	LastCommandID;
+    SInt16	Temperature;
+
+    TrackerSample Samples[3];
+
+    SInt16	MagX, MagY, MagZ;
+
+    TrackerMessageType Decode(const UByte* buffer, int size)
+    {
+        if (size < 62)
+            return TrackerMessage_SizeError;
+
+        SampleCount		= buffer[1];
+        Timestamp		= DecodeUInt16(buffer + 2);
+        LastCommandID	= DecodeUInt16(buffer + 4);
+        Temperature		= DecodeSInt16(buffer + 6);
+        
+        //if (SampleCount > 2)        
+        //    OVR_DEBUG_LOG_TEXT(("TackerSensor::Decode SampleCount=%d\n", SampleCount));        
+
+        // Only unpack as many samples as there actually are
+        int iterationCount = (SampleCount > 2) ? 3 : SampleCount;
+
+        for (int i = 0; i < iterationCount; i++)
+        {
+            UnpackSensor(buffer + 8 + 16 * i,  &Samples[i].AccelX, &Samples[i].AccelY, &Samples[i].AccelZ);
+            UnpackSensor(buffer + 16 + 16 * i, &Samples[i].GyroX,  &Samples[i].GyroY,  &Samples[i].GyroZ);
+        }
+
+        MagX = DecodeSInt16(buffer + 56);
+        MagY = DecodeSInt16(buffer + 58);
+        MagZ = DecodeSInt16(buffer + 60);
+
+        return TrackerMessage_Sensors;
+    }
+};
+
+struct TrackerMessage
+{
+    TrackerMessageType Type;
+    TrackerSensors     Sensors;
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** SensorDisplayInfoImpl
+SensorDisplayInfoImpl::SensorDisplayInfoImpl()
+ :  CommandId(0), DistortionType(Base_None)
+{
+    memset(Buffer, 0, PacketSize);
+    Buffer[0] = 9;
+}
+
+void SensorDisplayInfoImpl::Unpack()
+{
+    CommandId                       = Buffer[1] | (UInt16(Buffer[2]) << 8);
+    DistortionType                  = Buffer[3];
+    HResolution                     = DecodeUInt16(Buffer+4);
+    VResolution                     = DecodeUInt16(Buffer+6);
+    HScreenSize                     = DecodeUInt32(Buffer+8) *  (1/1000000.f);
+    VScreenSize                     = DecodeUInt32(Buffer+12) * (1/1000000.f);
+    VCenter                         = DecodeUInt32(Buffer+16) * (1/1000000.f);
+    LensSeparation                  = DecodeUInt32(Buffer+20) * (1/1000000.f);
+
+#if 0
+    // These are not well-measured on most devices - probably best to ignore them.
+    OutsideLensSurfaceToScreen[0]   = DecodeUInt32(Buffer+24) * (1/1000000.f);
+    OutsideLensSurfaceToScreen[1]   = DecodeUInt32(Buffer+28) * (1/1000000.f);
+    // TODO: add spline-based distortion.
+    // TODO: currently these values are all zeros in the HMD itself.
+    DistortionK[0]                  = DecodeFloat(Buffer+32);
+    DistortionK[1]                  = DecodeFloat(Buffer+36);
+    DistortionK[2]                  = DecodeFloat(Buffer+40);
+    DistortionK[3]                  = DecodeFloat(Buffer+44);
+    DistortionK[4]                  = DecodeFloat(Buffer+48);
+    DistortionK[5]                  = DecodeFloat(Buffer+52);
+#else
+    // The above are either measured poorly, or don't have values at all.
+    // To remove the temptation to use them, set them to junk.
+    OutsideLensSurfaceToScreen[0]   = -1.0f;
+    OutsideLensSurfaceToScreen[1]   = -1.0f;
+    DistortionK[0]                  = -1.0f;
+    DistortionK[1]                  = -1.0f;
+    DistortionK[2]                  = -1.0f;
+    DistortionK[3]                  = -1.0f;
+    DistortionK[4]                  = -1.0f;
+    DistortionK[5]                  = -1.0f;
+#endif
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** SensorDeviceFactory
+
+SensorDeviceFactory &SensorDeviceFactory::GetInstance()
+{
+		static SensorDeviceFactory instance;
+		return instance;
+}
+
+void SensorDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
+{
+
+    class SensorEnumerator : public HIDEnumerateVisitor
+    {
+        // Assign not supported; suppress MSVC warning.
+        void operator = (const SensorEnumerator&) { }
+
+        DeviceFactory*     pFactory;
+        EnumerateVisitor&  ExternalVisitor;   
+    public:
+        SensorEnumerator(DeviceFactory* factory, EnumerateVisitor& externalVisitor)
+            : pFactory(factory), ExternalVisitor(externalVisitor) { }
+
+        virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId)
+        {
+            return pFactory->MatchVendorProduct(vendorId, productId);
+        }
+
+        virtual void Visit(HIDDevice& device, const HIDDeviceDesc& desc)
+        {
+            
+            if (desc.ProductId == Sensor_BootLoader)
+            {   // If we find a sensor in boot loader mode then notify the app
+                // about the existence of the device, but don't allow the app
+                // to create or access the device
+                BootLoaderDeviceCreateDesc createDesc(pFactory, desc);
+                ExternalVisitor.Visit(createDesc);
+                return;
+            }
+            
+            SensorDeviceCreateDesc createDesc(pFactory, desc);
+            ExternalVisitor.Visit(createDesc);
+
+            // Check if the sensor returns DisplayInfo. If so, try to use it to override potentially
+            // mismatching monitor information (in case wrong EDID is reported by splitter),
+            // or to create a new "virtualized" HMD Device.
+            
+            SensorDisplayInfoImpl displayInfo;
+
+            if (device.GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize))
+            {
+                displayInfo.Unpack();
+
+                // If we got display info, try to match / create HMDDevice as well
+                // so that sensor settings give preference.
+                if (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt)
+                {
+                    SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(displayInfo, ExternalVisitor);
+                }
+            }
+        }
+    };
+
+    //double start = Timer::GetProfileSeconds();
+
+    SensorEnumerator sensorEnumerator(this, visitor);
+    GetManagerImpl()->GetHIDDeviceManager()->Enumerate(&sensorEnumerator);
+
+    //double totalSeconds = Timer::GetProfileSeconds() - start; 
+}
+
+bool SensorDeviceFactory::MatchVendorProduct(UInt16 vendorId, UInt16 productId) const
+{
+    return 	((vendorId == Sensor_VendorId) && (productId == Sensor_Tracker_ProductId)) ||
+    		((vendorId == Sensor_VendorId) && (productId == Sensor_Tracker2_ProductId)) ||
+    		((vendorId == Sensor_VendorId) && (productId == Sensor_KTracker_ProductId));
+}
+
+bool SensorDeviceFactory::DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc)
+{
+    if (MatchVendorProduct(desc.VendorId, desc.ProductId))
+    {
+        if (desc.ProductId == Sensor_BootLoader)
+        {   // If we find a sensor in boot loader mode then notify the app
+            // about the existence of the device, but don't allow them
+            // to create or access the device
+            BootLoaderDeviceCreateDesc createDesc(this, desc);
+            pdevMgr->AddDevice_NeedsLock(createDesc);
+            return false;  // return false to allow upstream boot loader factories to catch the device
+        }
+        else
+        {
+            SensorDeviceCreateDesc createDesc(this, desc);
+            return pdevMgr->AddDevice_NeedsLock(createDesc).GetPtr() != NULL;
+        }
+    }
+    return false;
+}
+
+//-------------------------------------------------------------------------------------
+// ***** SensorDeviceCreateDesc
+
+DeviceBase* SensorDeviceCreateDesc::NewDeviceInstance()
+{
+    if (HIDDesc.ProductId == Sensor_Tracker2_ProductId)
+    {
+        return new Sensor2DeviceImpl(this);
+    }
+
+    return new SensorDeviceImpl(this);
+}
+
+bool SensorDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
+{
+    if ((info->InfoClassType != Device_Sensor) &&
+        (info->InfoClassType != Device_None))
+        return false;
+
+    info->Type =            Device_Sensor;
+    info->ProductName =     HIDDesc.Product;
+    info->Manufacturer =    HIDDesc.Manufacturer;
+    info->Version =         HIDDesc.VersionNumber;
+
+    if (info->InfoClassType == Device_Sensor)
+    {
+        SensorInfo* sinfo = (SensorInfo*)info;
+        sinfo->VendorId  = HIDDesc.VendorId;
+        sinfo->ProductId = HIDDesc.ProductId;
+        sinfo->MaxRanges = SensorRangeImpl::GetMaxSensorRange();
+        sinfo->SerialNumber = HIDDesc.SerialNumber;
+    }
+    return true;
+}
+
+//-------------------------------------------------------------------------------------
+// ***** SensorDevice
+
+SensorDeviceImpl::SensorDeviceImpl(SensorDeviceCreateDesc* createDesc)
+    : OVR::HIDDeviceImpl<OVR::SensorDevice>(createDesc, 0),
+      Coordinates(SensorDevice::Coord_Sensor),
+      HWCoordinates(SensorDevice::Coord_HMD), // HW reports HMD coordinates by default.
+      NextKeepAliveTickSeconds(0),
+      FullTimestamp(0),      
+      MaxValidRange(SensorRangeImpl::GetMaxSensorRange()),
+      magCalibrated(false)
+{
+    SequenceValid   = false;
+    LastSampleCount = 0;
+    LastTimestamp   = 0;
+
+    OldCommandId = 0;
+
+    PrevAbsoluteTime = 0.0;
+
+#ifdef OVR_OS_ANDROID
+    pPhoneSensors = PhoneSensors::Create();
+#endif
+}
+
+SensorDeviceImpl::~SensorDeviceImpl()
+{
+    // Check that Shutdown() was called.
+    OVR_ASSERT(!pCreateDesc->pDevice);    
+}
+
+
+// Internal creation APIs.
+bool SensorDeviceImpl::Initialize(DeviceBase* parent)
+{
+    if (HIDDeviceImpl<OVR::SensorDevice>::Initialize(parent))
+    {
+        openDevice();
+        return true;
+    }
+
+    return false;
+}
+
+void SensorDeviceImpl::openDevice()
+{
+
+    // Read the currently configured range from sensor.
+    SensorRangeImpl sr(SensorRange(), 0);
+
+    if (GetInternalDevice()->GetFeatureReport(sr.Buffer, SensorRangeImpl::PacketSize))
+    {
+        sr.Unpack();
+        sr.GetSensorRange(&CurrentRange);
+        // Increase the magnetometer range, since the default value is not enough in practice
+        CurrentRange.MaxMagneticField = 2.5f;
+        setRange(CurrentRange);
+    }
+
+    // Read the currently configured calibration from sensor.
+    SensorFactoryCalibrationImpl sc;
+    if (GetInternalDevice()->GetFeatureReport(sc.Buffer, SensorFactoryCalibrationImpl::PacketSize))
+    {
+        sc.Unpack();
+        AccelCalibrationOffset = sc.AccelOffset;
+        GyroCalibrationOffset  = sc.GyroOffset;
+        AccelCalibrationMatrix = sc.AccelMatrix;
+        GyroCalibrationMatrix  = sc.GyroMatrix;
+        CalibrationTemperature = sc.Temperature;
+    }
+
+    // If the sensor has "DisplayInfo" data, use HMD coordinate frame by default.
+    SensorDisplayInfoImpl displayInfo;
+    if (GetInternalDevice()->GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize))
+    {
+        displayInfo.Unpack();
+        Coordinates = (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) ?
+                      Coord_HMD : Coord_Sensor;
+    }
+
+    // Read/Apply sensor config.
+    setCoordinateFrame(Coordinates);
+    setReportRate(Sensor_DefaultReportRate);
+
+    // Set Keep-alive at 10 seconds.
+    SensorKeepAliveImpl skeepAlive(10 * 1000);
+    GetInternalDevice()->SetFeatureReport(skeepAlive.Buffer, SensorKeepAliveImpl::PacketSize);
+
+    // Load mag calibration
+    MagCalibrationReport report;
+    bool res = GetMagCalibrationReport(&report);
+    if (res && report.Version > 0)
+    {
+        magCalibration = report.Calibration;
+        magCalibrated = true;
+    }
+}
+
+void SensorDeviceImpl::closeDeviceOnError()
+{
+    LogText("OVR::SensorDevice - Lost connection to '%s'\n", getHIDDesc()->Path.ToCStr());
+    NextKeepAliveTickSeconds = 0;
+}
+
+void SensorDeviceImpl::Shutdown()
+{   
+    HIDDeviceImpl<OVR::SensorDevice>::Shutdown();
+
+    LogText("OVR::SensorDevice - Closed '%s'\n", getHIDDesc()->Path.ToCStr());
+}
+
+void SensorDeviceImpl::OnInputReport(UByte* pData, UInt32 length)
+{
+
+	bool processed = false;
+    if (!processed)
+    {
+        TrackerMessage message;
+        if (decodeTrackerMessage(&message, pData, length))
+        {
+            processed = true;
+            onTrackerMessage(&message);
+        }
+    }
+}
+
+double SensorDeviceImpl::OnTicks(double tickSeconds)
+{
+    if (tickSeconds >= NextKeepAliveTickSeconds)
+    {
+        // Use 3-seconds keep alive by default.
+        double keepAliveDelta = 3.0;
+
+        // Set Keep-alive at 10 seconds.
+        SensorKeepAliveImpl skeepAlive(10 * 1000);
+        // OnTicks is called from background thread so we don't need to add this to the command queue.
+        GetInternalDevice()->SetFeatureReport(skeepAlive.Buffer, SensorKeepAliveImpl::PacketSize);
+
+		// Emit keep-alive every few seconds.
+        NextKeepAliveTickSeconds = tickSeconds + keepAliveDelta;
+    }
+    return NextKeepAliveTickSeconds - tickSeconds;
+}
+
+bool SensorDeviceImpl::SetRange(const SensorRange& range, bool waitFlag)
+{
+    bool                 result = 0;
+    ThreadCommandQueue * threadQueue = GetManagerImpl()->GetThreadQueue();
+
+    if (!waitFlag)
+    {
+        return threadQueue->PushCall(this, &SensorDeviceImpl::setRange, range);
+    }
+    
+    if (!threadQueue->PushCallAndWaitResult(this, 
+                                            &SensorDeviceImpl::setRange,
+                                            &result, 
+                                            range))
+    {
+        return false;
+    }
+
+    return result;
+}
+
+void SensorDeviceImpl::GetRange(SensorRange* range) const
+{
+    Lock::Locker lockScope(GetLock());
+    *range = CurrentRange;
+}
+
+bool SensorDeviceImpl::setRange(const SensorRange& range)
+{
+    SensorRangeImpl sr(range);
+    
+    if (GetInternalDevice()->SetFeatureReport(sr.Buffer, SensorRangeImpl::PacketSize))
+    {
+        Lock::Locker lockScope(GetLock());
+        sr.GetSensorRange(&CurrentRange);
+        return true;
+    }
+    
+    return false;
+}
+
+void SensorDeviceImpl::SetCoordinateFrame(CoordinateFrame coordframe)
+{ 
+    // Push call with wait.
+    GetManagerImpl()->GetThreadQueue()->
+        PushCall(this, &SensorDeviceImpl::setCoordinateFrame, coordframe, true);
+}
+
+SensorDevice::CoordinateFrame SensorDeviceImpl::GetCoordinateFrame() const
+{
+    return Coordinates;
+}
+
+Void SensorDeviceImpl::setCoordinateFrame(CoordinateFrame coordframe)
+{
+
+    Coordinates = coordframe;
+
+    // Read the original coordinate frame, then try to change it.
+    SensorConfigImpl scfg;
+    if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize))
+    {
+        scfg.Unpack();
+    }
+
+    scfg.SetSensorCoordinates(coordframe == Coord_Sensor);
+    scfg.Pack();
+
+    GetInternalDevice()->SetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize);
+    
+    // Re-read the state, in case of older firmware that doesn't support Sensor coordinates.
+    if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize))
+    {
+        scfg.Unpack();
+        HWCoordinates = scfg.IsUsingSensorCoordinates() ? Coord_Sensor : Coord_HMD;
+    }
+    else
+    {
+        HWCoordinates = Coord_HMD;
+    }
+    return 0;
+}
+
+void SensorDeviceImpl::SetReportRate(unsigned rateHz)
+{ 
+    // Push call with wait.
+    GetManagerImpl()->GetThreadQueue()->
+        PushCall(this, &SensorDeviceImpl::setReportRate, rateHz, true);
+}
+
+unsigned SensorDeviceImpl::GetReportRate() const
+{
+    // Read the original configuration
+    SensorConfigImpl scfg;
+    if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize))
+    {
+        scfg.Unpack();
+        return Sensor_MaxReportRate / (scfg.PacketInterval + 1);
+    }
+    return 0; // error
+}
+
+Void SensorDeviceImpl::setReportRate(unsigned rateHz)
+{
+    // Read the original configuration
+    SensorConfigImpl scfg;
+    if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize))
+    {
+        scfg.Unpack();
+    }
+
+    if (rateHz > Sensor_MaxReportRate)
+        rateHz = Sensor_MaxReportRate;
+    else if (rateHz == 0)
+        rateHz = Sensor_DefaultReportRate;
+
+    scfg.PacketInterval = UInt16((Sensor_MaxReportRate / rateHz) - 1);
+
+    scfg.Pack();
+
+    GetInternalDevice()->SetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize);
+    return 0;
+}
+
+void SensorDeviceImpl::GetFactoryCalibration(Vector3f* AccelOffset, Vector3f* GyroOffset,
+                                             Matrix4f* AccelMatrix, Matrix4f* GyroMatrix, 
+                                             float* Temperature)
+{
+    *AccelOffset = AccelCalibrationOffset;
+    *GyroOffset  = GyroCalibrationOffset;
+    *AccelMatrix = AccelCalibrationMatrix;
+    *GyroMatrix  = GyroCalibrationMatrix;
+    *Temperature = CalibrationTemperature;
+}
+
+bool SensorDeviceImpl::IsMagCalibrated()
+{
+    return magCalibrated;
+}
+
+void SensorDeviceImpl::SetOnboardCalibrationEnabled(bool enabled)
+{
+    // Push call with wait.
+    GetManagerImpl()->GetThreadQueue()->
+        PushCall(this, &SensorDeviceImpl::setOnboardCalibrationEnabled, enabled, true);
+}
+
+Void SensorDeviceImpl::setOnboardCalibrationEnabled(bool enabled)
+{
+    // Read the original configuration
+    SensorConfigImpl scfg;
+    if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize))
+    {
+        scfg.Unpack();
+    }
+
+    if (enabled)
+        scfg.Flags |= (SensorConfigImpl::Flag_AutoCalibration | SensorConfigImpl::Flag_UseCalibration);
+    else
+        scfg.Flags &= ~(SensorConfigImpl::Flag_AutoCalibration | SensorConfigImpl::Flag_UseCalibration);
+
+    scfg.Pack();
+
+    GetInternalDevice()->SetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize);
+    return 0;
+}
+
+void SensorDeviceImpl::AddMessageHandler(MessageHandler* handler)
+{
+    if (handler)
+        SequenceValid = false;
+    DeviceBase::AddMessageHandler(handler);
+}
+
+// Sensor reports data in the following coordinate system:
+// Accelerometer: 10^-4 m/s^2; X forward, Y right, Z Down.
+// Gyro:          10^-4 rad/s; X positive roll right, Y positive pitch up; Z positive yaw right.
+
+
+// We need to convert it to the following RHS coordinate system:
+// X right, Y Up, Z Back (out of screen)
+//
+Vector3f AccelFromBodyFrameUpdate(const TrackerSensors& update, UByte sampleNumber,
+                                  bool convertHMDToSensor = false)
+{
+    const TrackerSample& sample = update.Samples[sampleNumber];
+    float                ax = (float)sample.AccelX;
+    float                ay = (float)sample.AccelY;
+    float                az = (float)sample.AccelZ;
+
+    Vector3f val = convertHMDToSensor ? Vector3f(ax, az, -ay) :  Vector3f(ax, ay, az);
+    return val * 0.0001f;
+}
+
+
+Vector3f MagFromBodyFrameUpdate(const TrackerSensors& update,
+                                Matrix4f magCalibration,
+                                bool convertHMDToSensor = false)
+{   
+    float mx = (float)update.MagX;
+    float my = (float)update.MagY;
+    float mz = (float)update.MagZ;
+    // Note: Y and Z are swapped in comparison to the Accel.  
+    // This accounts for DK1 sensor firmware axis swap, which should be undone in future releases.
+    Vector3f mag = convertHMDToSensor ? Vector3f(mx, my, -mz) : Vector3f(mx, mz, my);
+    mag *= 0.0001f;
+    // Apply calibration
+    return magCalibration.Transform(mag);
+}
+
+Vector3f EulerFromBodyFrameUpdate(const TrackerSensors& update, UByte sampleNumber,
+                                  bool convertHMDToSensor = false)
+{
+    const TrackerSample& sample = update.Samples[sampleNumber];
+    float                gx = (float)sample.GyroX;
+    float                gy = (float)sample.GyroY;
+    float                gz = (float)sample.GyroZ;
+
+    Vector3f val = convertHMDToSensor ? Vector3f(gx, gz, -gy) :  Vector3f(gx, gy, gz);
+    return val * 0.0001f;
+}
+
+bool  SensorDeviceImpl::decodeTrackerMessage(TrackerMessage* message, UByte* buffer, int size)
+{
+    memset(message, 0, sizeof(TrackerMessage));
+
+    if (size < 4)
+    {
+        message->Type = TrackerMessage_SizeError;
+        return false;
+    }
+
+    switch (buffer[0])
+    {
+    case TrackerMessage_Sensors:
+        message->Type = message->Sensors.Decode(buffer, size);
+        break;
+
+    default:
+        message->Type = TrackerMessage_Unknown;
+        break;
+    }
+
+    return (message->Type < TrackerMessage_Unknown) && (message->Type != TrackerMessage_None);
+}
+
+void SensorDeviceImpl::onTrackerMessage(TrackerMessage* message)
+{
+    if (message->Type != TrackerMessage_Sensors)
+        return;
+    
+    const double    timeUnit        = (1.0 / 1000.0);
+    double          scaledTimeUnit  = timeUnit;
+    TrackerSensors& s               = message->Sensors;
+    // DK1 timestamps the first sample, so the actual device time will be later
+    // by the time we get the message if there are multiple samples.
+    int             timestampAdjust = (s.SampleCount > 0) ? s.SampleCount-1 : 0;
+
+    const double now                 = Timer::GetSeconds();
+    double       absoluteTimeSeconds = 0.0;
+    
+
+    if (SequenceValid)
+    {
+        unsigned timestampDelta;
+
+        if (s.Timestamp < LastTimestamp)
+        {
+        	// The timestamp rolled around the 16 bit counter, so FullTimeStamp
+        	// needs a high word increment.
+        	FullTimestamp += 0x10000;
+            timestampDelta = ((((int)s.Timestamp) + 0x10000) - (int)LastTimestamp);
+        }
+        else
+        {
+            timestampDelta = (s.Timestamp - LastTimestamp);
+        }
+        // Update the low word of FullTimeStamp
+        FullTimestamp = ( FullTimestamp & ~0xffff ) | s.Timestamp;       
+
+        double deviceTime   = (FullTimestamp + timestampAdjust) * timeUnit;
+        absoluteTimeSeconds = TimeFilter.SampleToSystemTime(deviceTime, now, PrevAbsoluteTime);
+        scaledTimeUnit      = TimeFilter.ScaleTimeUnit(timeUnit);
+        PrevAbsoluteTime    = absoluteTimeSeconds;
+        
+        // If we missed a small number of samples, generate the sample that would have immediately
+        // proceeded the current one. Re-use the IMU values from the last processed sample.
+        if ((timestampDelta > LastSampleCount) && (timestampDelta <= 254))
+        {
+            if (HandlerRef.HasHandlers())
+            {
+                MessageBodyFrame sensors(this);
+
+                sensors.AbsoluteTimeSeconds = absoluteTimeSeconds - s.SampleCount * scaledTimeUnit;
+                sensors.TimeDelta           = (float)((timestampDelta - LastSampleCount) * scaledTimeUnit);
+                sensors.Acceleration        = LastAcceleration;
+                sensors.RotationRate        = LastRotationRate;
+                sensors.MagneticField       = LastMagneticField;
+                sensors.Temperature         = LastTemperature;
+
+                HandlerRef.Call(sensors);
+            }
+        }
+    }
+    else
+    {
+        LastAcceleration = Vector3f(0);
+        LastRotationRate = Vector3f(0);
+        LastMagneticField= Vector3f(0);
+        LastTemperature  = 0;
+        SequenceValid    = true;
+
+        // This is our baseline sensor to host time delta,
+        // it will be adjusted with each new message.
+        FullTimestamp = s.Timestamp;
+
+        double deviceTime   = (FullTimestamp + timestampAdjust) * timeUnit;
+        absoluteTimeSeconds = TimeFilter.SampleToSystemTime(deviceTime, now, PrevAbsoluteTime);
+        scaledTimeUnit      = TimeFilter.ScaleTimeUnit(timeUnit);
+        PrevAbsoluteTime    = absoluteTimeSeconds;
+    }
+
+    LastSampleCount = s.SampleCount;
+    LastTimestamp   = s.Timestamp;
+
+    bool convertHMDToSensor = (Coordinates == Coord_Sensor) && (HWCoordinates == Coord_HMD);
+	
+#ifdef OVR_OS_ANDROID
+    // LDC - Normally we get the coordinate system from the tracker.
+    // Since KTracker doesn't store it we'll always assume HMD coordinate system.
+    convertHMDToSensor = false;
+#endif
+
+    if (HandlerRef.HasHandlers())
+    {
+        MessageBodyFrame sensors(this);
+        UByte            iterations = s.SampleCount;
+
+        if (s.SampleCount > 3)
+        {
+            iterations        = 3;
+            sensors.TimeDelta = (float)((s.SampleCount - 2) * scaledTimeUnit);
+        }
+        else
+        {
+            sensors.TimeDelta = (float)scaledTimeUnit;
+        }
+
+        for (UByte i = 0; i < iterations; i++)
+        {     
+            sensors.AbsoluteTimeSeconds = absoluteTimeSeconds - ( iterations - 1 - i ) * scaledTimeUnit;
+            sensors.Acceleration        = AccelFromBodyFrameUpdate(s, i, convertHMDToSensor);
+            sensors.RotationRate        = EulerFromBodyFrameUpdate(s, i, convertHMDToSensor);
+            sensors.MagneticField       = MagFromBodyFrameUpdate(s, magCalibration, convertHMDToSensor);
+
+#ifdef OVR_OS_ANDROID
+            replaceWithPhoneMag(&(sensors.MagneticField));
+#endif
+            sensors.Temperature   = s.Temperature * 0.01f;
+            HandlerRef.Call(sensors);
+            // TimeDelta for the last two sample is always fixed.
+            sensors.TimeDelta = (float)scaledTimeUnit;
+        }
+
+        LastAcceleration = sensors.Acceleration;
+        LastRotationRate = sensors.RotationRate;
+        LastMagneticField= sensors.MagneticField;
+        LastTemperature  = sensors.Temperature;
+    }
+    else
+    {
+        UByte i = (s.SampleCount > 3) ? 2 : (s.SampleCount - 1);
+        LastAcceleration  = AccelFromBodyFrameUpdate(s, i, convertHMDToSensor);
+        LastRotationRate  = EulerFromBodyFrameUpdate(s, i, convertHMDToSensor);
+        LastMagneticField = MagFromBodyFrameUpdate(s, magCalibration, convertHMDToSensor);
+
+#ifdef OVR_OS_ANDROID
+        replaceWithPhoneMag(&LastMagneticField);
+#endif
+        LastTemperature   = s.Temperature * 0.01f;
+    }
+}
+
+
+#ifdef OVR_OS_ANDROID
+
+void SensorDeviceImpl::replaceWithPhoneMag(Vector3f* val)
+{
+
+	// Native calibrated.
+	pPhoneSensors->SetMagSource(PhoneSensors::MagnetometerSource_Native);
+
+	Vector3f magPhone;
+	pPhoneSensors->GetLatestMagValue(&magPhone);
+
+	// Phone value is in micro-Tesla. Convert it to Gauss and flip axes.
+	magPhone *= 10000.0f/1000000.0f;
+
+	Vector3f res;
+	res.x = -magPhone.y;
+	res.y = magPhone.x;
+	res.z = magPhone.z;
+
+	*val = res;
+}
+#endif 
+
+const int MAX_DEVICE_PROFILE_MAJOR_VERSION = 1;
+
+// Writes the current calibration for a particular device to a device profile file
+bool SensorDeviceImpl::SetMagCalibrationReport(const MagCalibrationReport &data)
+{
+    // Get device info
+    SensorInfo sinfo;
+    GetDeviceInfo(&sinfo);
+    
+    // A named calibration may be specified for calibration in different
+    // environments, otherwise the default calibration is used
+    const char* calibrationName = "default";
+
+    // Generate a mag calibration event
+    JSON* calibration = JSON::CreateObject();
+    // (hardcoded for now) the measurement and representation method 
+    calibration->AddStringItem("Version", "2.0");   
+    calibration->AddStringItem("Name", "default");
+
+    // time stamp the calibration
+    char time_str[64];
+   
+#ifdef OVR_OS_WIN32
+    struct tm caltime;
+    time_t now = time(0);
+    localtime_s(&caltime, &now);
+    strftime(time_str, 64, "%Y-%m-%d %H:%M:%S", &caltime);
+#else
+    struct tm* caltime;
+    time_t now = time(0);
+    caltime = localtime(&now);
+    strftime(time_str, 64, "%Y-%m-%d %H:%M:%S", caltime);
+#endif
+   
+    calibration->AddStringItem("Time", time_str);
+
+    // write the full calibration matrix
+    char matrix[256];
+    data.Calibration.ToString(matrix, 256);
+    calibration->AddStringItem("CalibrationMatrix", matrix);
+    // save just the offset, for backwards compatibility
+    // this can be removed when we don't want to support 0.2.4 anymore
+    Vector3f center(data.Calibration.M[0][3], data.Calibration.M[1][3], data.Calibration.M[2][3]);
+    Matrix4f tmp = data.Calibration; tmp.M[0][3] = tmp.M[1][3] = tmp.M[2][3] = 0; tmp.M[3][3] = 1;
+    center = tmp.Inverted().Transform(center);
+    Matrix4f oldcalmat; oldcalmat.M[0][3] = center.x; oldcalmat.M[1][3] = center.y; oldcalmat.M[2][3] = center.z; 
+    oldcalmat.ToString(matrix, 256);
+    calibration->AddStringItem("Calibration", matrix);
+    
+    String path = GetBaseOVRPath(true);
+    path += "/Devices.json";
+
+    // Look for a preexisting device file to edit
+    Ptr<JSON> root = *JSON::Load(path);
+    if (root)
+    {   // Quick sanity check of the file type and format before we parse it
+        JSON* version = root->GetFirstItem();
+        if (version && version->Name == "Oculus Device Profile Version")
+        {   
+            int major = atoi(version->Value.ToCStr());
+            if (major > MAX_DEVICE_PROFILE_MAJOR_VERSION)
+            {
+                // don't use the file on unsupported major version number
+                root->Release();
+                root = NULL;
+            }
+        }
+        else
+        {
+            root->Release();
+            root = NULL;
+        }
+    }
+
+    JSON* device = NULL;
+    if (root)
+    {
+        device = root->GetFirstItem();   // skip the header
+        device = root->GetNextItem(device);
+        while (device)
+        {   // Search for a previous calibration with the same name for this device
+            // and remove it before adding the new one
+            if (device->Name == "Device")
+            {   
+                JSON* item = device->GetItemByName("Serial");
+                if (item && item->Value == sinfo.SerialNumber)
+                {   // found an entry for this device
+                    item = device->GetNextItem(item);
+                    while (item)
+                    {
+                        if (item->Name == "MagCalibration")
+                        {   
+                            JSON* name = item->GetItemByName("Name");
+                            if (name && name->Value == calibrationName)
+                            {   // found a calibration of the same name
+                                item->RemoveNode();
+                                item->Release();
+                                break;
+                            } 
+                        }
+                        item = device->GetNextItem(item);
+                    }
+
+
+                    /*
+                    this is removed temporarily, since this is a sensor fusion setting, not sensor itself
+                    should be moved to the correct place when Brant has finished the user profile implementation
+                    // update the auto-mag flag
+                    item = device->GetItemByName("EnableYawCorrection");
+                    if (item)
+                        item->dValue = (double)EnableYawCorrection;
+                    else
+                        device->AddBoolItem("EnableYawCorrection", EnableYawCorrection);*/
+
+                    break;
+                }
+            }
+
+            device = root->GetNextItem(device);
+        }
+    }
+    else
+    {   // Create a new device root
+        root = *JSON::CreateObject();
+        root->AddStringItem("Oculus Device Profile Version", "1.0");
+    }
+
+    if (device == NULL)
+    {
+        device = JSON::CreateObject();
+        device->AddStringItem("Product", sinfo.ProductName);
+        device->AddNumberItem("ProductID", sinfo.ProductId);
+        device->AddStringItem("Serial", sinfo.SerialNumber);
+        // removed temporarily, see above
+        //device->AddBoolItem("EnableYawCorrection", EnableYawCorrection);
+
+        root->AddItem("Device", device);
+    }
+
+    // Create and the add the new calibration event to the device
+    device->AddItem("MagCalibration", calibration);
+    return root->Save(path);
+}
+
+// Loads a saved calibration for the specified device from the device profile file
+bool SensorDeviceImpl::GetMagCalibrationReport(MagCalibrationReport* data)
+{
+    data->Version = 0;
+    data->Calibration.SetIdentity();
+
+    // Get device info
+    SensorInfo sinfo;
+    GetDeviceInfo(&sinfo);
+
+    // A named calibration may be specified for calibration in different
+    // environments, otherwise the default calibration is used
+    const char* calibrationName = "default";
+
+    String path = GetBaseOVRPath(true);
+    path += "/Devices.json";
+
+    // Load the device profiles
+    Ptr<JSON> root = *JSON::Load(path);
+    if (root == NULL)
+        return false;
+
+    // Quick sanity check of the file type and format before we parse it
+    JSON* version = root->GetFirstItem();
+    if (version && version->Name == "Oculus Device Profile Version")
+    {   
+        int major = atoi(version->Value.ToCStr());
+        if (major > MAX_DEVICE_PROFILE_MAJOR_VERSION)
+            return false;   // don't parse the file on unsupported major version number
+    }
+    else
+    {
+        return false;
+    }
+
+    JSON* device = root->GetNextItem(version);
+    while (device)
+    {   // Search for a previous calibration with the same name for this device
+        // and remove it before adding the new one
+        if (device->Name == "Device")
+        {   
+            JSON* item = device->GetItemByName("Serial");
+            if (item && item->Value == sinfo.SerialNumber)
+            {   // found an entry for this device
+
+                JSON* autoyaw = device->GetItemByName("EnableYawCorrection");
+                // as a temporary HACK, return no calibration if EnableYawCorrection is off
+                // this will force disable yaw correction in SensorFusion
+                // proper solution would load the value in the Profile, which SensorFusion can access
+                if (autoyaw && autoyaw->dValue == 0)
+                    return true;
+
+                item = device->GetNextItem(item);
+                while (item)
+                {
+                    if (item->Name == "MagCalibration")
+                    {   
+                        JSON* calibration = item;
+                        JSON* name = calibration->GetItemByName("Name");
+                        if (name && name->Value == calibrationName)
+                        {   // found a calibration with this name
+                            
+                            int major = 0;
+                            JSON* version = calibration->GetItemByName("Version");
+                            if (version)
+                                major = atoi(version->Value.ToCStr());
+
+                            if (major > data->Version && major <= 2)
+                            {
+                                time_t now;
+                                time(&now);
+
+                                // parse the calibration time
+                                //time_t calibration_time = now;
+                                JSON* caltime = calibration->GetItemByName("Time");
+                                if (caltime)
+                                {
+                                    const char* caltime_str = caltime->Value.ToCStr();
+
+                                    tm ct;
+                                    memset(&ct, 0, sizeof(tm));
+                            
+#ifdef OVR_OS_WIN32
+                                    struct tm nowtime;
+                                    localtime_s(&nowtime, &now);
+                                    ct.tm_isdst = nowtime.tm_isdst;
+                                    sscanf_s(caltime_str, "%d-%d-%d %d:%d:%d", 
+                                        &ct.tm_year, &ct.tm_mon, &ct.tm_mday,
+                                        &ct.tm_hour, &ct.tm_min, &ct.tm_sec);
+#else
+                                    struct tm* nowtime = localtime(&now);
+                                    ct.tm_isdst = nowtime->tm_isdst;
+                                    sscanf(caltime_str, "%d-%d-%d %d:%d:%d", 
+                                        &ct.tm_year, &ct.tm_mon, &ct.tm_mday,
+                                        &ct.tm_hour, &ct.tm_min, &ct.tm_sec);
+#endif
+                                    ct.tm_year -= 1900;
+                                    ct.tm_mon--;
+                                    //calibration_time = mktime(&ct);
+                                }
+                                                        
+                                // parse the calibration matrix
+                                JSON* cal = calibration->GetItemByName("CalibrationMatrix");
+                                if (!cal)
+                                    cal = calibration->GetItemByName("Calibration");
+                                if (cal)
+                                {
+                                    data->Calibration = Matrix4f::FromString(cal->Value.ToCStr());
+                                    data->Version = (UByte)major;
+                                }
+                            }
+                        } 
+                    }
+                    item = device->GetNextItem(item);
+                }
+
+                return true;
+            }
+        }
+
+        device = root->GetNextItem(device);
+    }
+    
+    return true;
+}
+
+
+bool SensorDeviceImpl::SetSerialReport(const SerialReport& data)
+{ 
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::setSerialReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool SensorDeviceImpl::setSerialReport(const SerialReport& data)
+{
+    SerialImpl di(data);
+    return GetInternalDevice()->SetFeatureReport(di.Buffer, SerialImpl::PacketSize);
+}
+
+bool SensorDeviceImpl::GetSerialReport(SerialReport* data)
+{
+	bool result;
+	if (!GetManagerImpl()->GetThreadQueue()->
+            PushCallAndWaitResult(this, &Sensor2DeviceImpl::getSerialReport, &result, data))
+	{
+		return false;
+	}
+
+	return result;
+}
+
+bool SensorDeviceImpl::getSerialReport(SerialReport* data)
+{
+    SerialImpl di;
+    if (GetInternalDevice()->GetFeatureReport(di.Buffer, SerialImpl::PacketSize))
+    {
+        di.Unpack();
+        *data = di.Settings;
+        return true;
+    }
+
+    return false;
+}
+
+} // namespace OVR
diff --git a/LibOVR/Src/OVR_SensorImpl.h b/LibOVR/Src/OVR_SensorImpl.h
new file mode 100644
index 0000000..f53b831
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorImpl.h
@@ -0,0 +1,316 @@
+/************************************************************************************
+
+Filename    :   OVR_SensorImpl.h
+Content     :   Sensor device specific implementation.
+Created     :   March 7, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_SensorImpl_h
+#define OVR_SensorImpl_h
+
+#include "OVR_HIDDeviceImpl.h"
+#include "OVR_SensorTimeFilter.h"
+#include "OVR_Device.h"
+
+#ifdef OVR_OS_ANDROID
+#include "OVR_PhoneSensors.h"
+#endif
+
+namespace OVR {
+
+struct TrackerMessage;
+class ExternalVisitor;
+
+//-------------------------------------------------------------------------------------
+// SensorDeviceFactory enumerates Oculus Sensor devices.
+class SensorDeviceFactory : public DeviceFactory
+{
+public:
+	static SensorDeviceFactory &GetInstance();
+
+    // Enumerates devices, creating and destroying relevant objects in manager.
+    virtual void EnumerateDevices(EnumerateVisitor& visitor);
+
+    virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const;
+    virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc);
+protected:
+    DeviceManager* getManager() const { return (DeviceManager*) pManager; }   
+};
+
+
+// Describes a single a Oculus Sensor device and supports creating its instance.
+class SensorDeviceCreateDesc : public HIDDeviceCreateDesc
+{
+public:
+    SensorDeviceCreateDesc(DeviceFactory* factory, const HIDDeviceDesc& hidDesc)
+        : HIDDeviceCreateDesc(factory, Device_Sensor, hidDesc) { }
+    
+    virtual DeviceCreateDesc* Clone() const
+    {
+        return new SensorDeviceCreateDesc(*this);
+    }
+
+    virtual DeviceBase* NewDeviceInstance();
+
+    virtual MatchResult MatchDevice(const DeviceCreateDesc& other,
+                                    DeviceCreateDesc**) const
+    {
+        if ((other.Type == Device_Sensor) && (pFactory == other.pFactory))
+        {
+            const SensorDeviceCreateDesc& s2 = (const SensorDeviceCreateDesc&) other;
+            if (MatchHIDDevice(s2.HIDDesc))
+                return Match_Found;
+        }
+        return Match_None;
+    }
+
+    virtual bool MatchHIDDevice(const HIDDeviceDesc& hidDesc) const
+    {
+        // should paths comparison be case insensitive?
+        return ((HIDDesc.Path.CompareNoCase(hidDesc.Path) == 0) &&
+                (HIDDesc.SerialNumber == hidDesc.SerialNumber) &&
+                (HIDDesc.VersionNumber == hidDesc.VersionNumber));
+    }
+
+    virtual bool        GetDeviceInfo(DeviceInfo* info) const;
+};
+
+// A simple stub for notification of a sensor in Boot Loader mode
+// This descriptor does not support the creation of a device, only the detection
+// of its existence to warn apps that the sensor device needs firmware.
+// The Boot Loader descriptor reuses and is created by the Sensor device factory
+// but in the future may use a dedicated factory
+class BootLoaderDeviceCreateDesc : public HIDDeviceCreateDesc
+{
+public:
+    BootLoaderDeviceCreateDesc(DeviceFactory* factory, const HIDDeviceDesc& hidDesc)
+        : HIDDeviceCreateDesc(factory, Device_BootLoader, hidDesc) { }
+    
+    virtual DeviceCreateDesc* Clone() const
+    {
+        return new BootLoaderDeviceCreateDesc(*this);
+    }
+
+    // Boot Loader device creation is not allowed
+    virtual DeviceBase* NewDeviceInstance() { return NULL; };
+
+    virtual MatchResult MatchDevice(const DeviceCreateDesc& other,
+                                    DeviceCreateDesc**) const
+    {
+        if ((other.Type == Device_BootLoader) && (pFactory == other.pFactory))
+        {
+            const BootLoaderDeviceCreateDesc& s2 = (const BootLoaderDeviceCreateDesc&) other;
+            if (MatchHIDDevice(s2.HIDDesc))
+                return Match_Found;
+        }
+        return Match_None;
+    }
+
+    virtual bool MatchHIDDevice(const HIDDeviceDesc& hidDesc) const
+    {
+        // should paths comparison be case insensitive?
+        return ((HIDDesc.Path.CompareNoCase(hidDesc.Path) == 0) &&
+                (HIDDesc.SerialNumber == hidDesc.SerialNumber));
+    }
+
+    virtual bool        GetDeviceInfo(DeviceInfo* info) const 
+    {
+        OVR_UNUSED(info);
+        return false; 
+    }
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** OVR::SensorDisplayInfoImpl
+
+// DisplayInfo obtained from sensor; these values are used to report distortion
+// settings and other coefficients.
+// Older SensorDisplayInfo will have all zeros, causing the library to apply hard-coded defaults.
+// Currently, only resolutions and sizes are used.
+struct SensorDisplayInfoImpl
+{
+    enum  { PacketSize = 56 };
+    UByte   Buffer[PacketSize];
+
+    enum
+    {
+        Mask_BaseFmt    = 0x0f,
+        Mask_OptionFmts = 0xf0,
+        Base_None       = 0,
+        Base_ScreenOnly = 1,
+        Base_Distortion = 2,
+    };
+
+    UInt16  CommandId;
+
+    UByte   DistortionType;    
+    UInt16  HResolution, VResolution;
+    float   HScreenSize, VScreenSize;
+    float   VCenter;
+    float   LensSeparation;
+    // Currently these values are not well-measured.
+    float   OutsideLensSurfaceToScreen[2];
+    // TODO: add DistortionEqn
+    // TODO: currently these values are all zeros and the
+    //       distortion is hard-coded in HMDDeviceCreateDesc::GetDeviceInfo()
+    float   DistortionK[6];
+
+    SensorDisplayInfoImpl();
+
+    void Unpack();
+};
+
+//-------------------------------------------------------------------------------------
+// ***** OVR::SensorDeviceImpl
+
+// Oculus Sensor interface.
+
+class SensorDeviceImpl : public HIDDeviceImpl<OVR::SensorDevice>
+{
+public:
+     SensorDeviceImpl(SensorDeviceCreateDesc* createDesc);
+    ~SensorDeviceImpl();
+
+
+    // DeviceCommaon interface
+    virtual bool Initialize(DeviceBase* parent);
+    virtual void Shutdown();
+    
+    virtual void AddMessageHandler(MessageHandler* handler);
+
+    // HIDDevice::Notifier interface.
+    virtual void OnInputReport(UByte* pData, UInt32 length);
+    virtual double OnTicks(double tickSeconds);
+
+    // HMD-Mounted sensor has a different coordinate frame.
+    virtual void SetCoordinateFrame(CoordinateFrame coordframe);    
+    virtual CoordinateFrame GetCoordinateFrame() const;    
+
+    // SensorDevice interface
+    virtual bool SetRange(const SensorRange& range, bool waitFlag);
+    virtual void GetRange(SensorRange* range) const;
+
+    virtual void GetFactoryCalibration(Vector3f* AccelOffset, Vector3f* GyroOffset,
+                                       Matrix4f* AccelMatrix, Matrix4f* GyroMatrix, 
+                                       float* Temperature);
+    virtual void SetOnboardCalibrationEnabled(bool enabled);
+    virtual bool IsMagCalibrated();
+
+    // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call). 
+    // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be 
+    // called twice or thrice at the same 'tick'. 
+    // If the rate is  < 333 then the OnMessage / MessageBodyFrame will be called three
+    // times for each 'tick': the first call will contain averaged values, the second
+    // and third calls will provide with most recent two recorded samples.
+    virtual void        SetReportRate(unsigned rateHz);
+    // Returns currently set report rate, in Hz. If 0 - error occurred.
+    // Note, this value may be different from the one provided for SetReportRate. The return
+    // value will contain the actual rate.
+    virtual unsigned    GetReportRate() const;
+
+	bool				SetSerialReport(const SerialReport& data);
+    bool				GetSerialReport(SerialReport* data);
+
+    // Hack to create HMD device from sensor display info.
+    static void         EnumerateHMDFromSensorDisplayInfo(const SensorDisplayInfoImpl& displayInfo, 
+                                                                DeviceFactory::EnumerateVisitor& visitor);
+
+    // These methods actually store data in a JSON file
+    virtual bool		SetMagCalibrationReport(const MagCalibrationReport& data);
+	virtual bool		GetMagCalibrationReport(MagCalibrationReport* data);
+
+protected:
+
+    virtual void    openDevice();
+    void            closeDeviceOnError();
+
+    Void            setCoordinateFrame(CoordinateFrame coordframe);
+    bool            setRange(const SensorRange& range);
+
+    Void            setReportRate(unsigned rateHz);
+
+    Void            setOnboardCalibrationEnabled(bool enabled);
+
+	bool	        setSerialReport(const SerialReport& data);
+    bool            getSerialReport(SerialReport* data);
+
+    // Called for decoded messages
+    void			onTrackerMessage(TrackerMessage* message);
+	bool			decodeTrackerMessage(TrackerMessage* message, UByte* buffer, int size);
+
+    // Helpers to reduce casting.
+/*
+    SensorDeviceCreateDesc* getCreateDesc() const
+    { return (SensorDeviceCreateDesc*)pCreateDesc.GetPtr(); }
+
+    HIDDeviceDesc* getHIDDesc() const
+    { return &getCreateDesc()->HIDDesc; }    
+*/
+
+    // Set if the sensor is located on the HMD.
+    // Older prototype firmware doesn't support changing HW coordinates,
+    // so we track its state.
+    CoordinateFrame Coordinates;
+    CoordinateFrame HWCoordinates;
+    double      NextKeepAliveTickSeconds;
+
+    bool        SequenceValid;
+    UInt16      LastTimestamp;
+    UByte       LastSampleCount;
+    float       LastTemperature;
+    Vector3f    LastAcceleration;
+    Vector3f    LastRotationRate;
+    Vector3f    LastMagneticField;
+
+    // This tracks wrap around, and should be monotonically increasing.
+    UInt32		FullTimestamp;
+
+    // Current sensor range obtained from device. 
+    SensorRange MaxValidRange;
+    SensorRange CurrentRange;
+
+    // IMU calibration obtained from device.
+    Vector3f    AccelCalibrationOffset;
+    Vector3f    GyroCalibrationOffset;
+    Matrix4f    AccelCalibrationMatrix;
+    Matrix4f    GyroCalibrationMatrix;
+    float       CalibrationTemperature;
+    
+    UInt16      OldCommandId;
+
+    SensorTimeFilter TimeFilter;
+    double           PrevAbsoluteTime;
+
+#ifdef OVR_OS_ANDROID
+    void 	        replaceWithPhoneMag(Vector3f* val);
+    PhoneSensors* 	pPhoneSensors;
+#endif
+
+private:
+    Matrix4f    magCalibration;
+    bool        magCalibrated;
+};
+
+} // namespace OVR
+
+#endif // OVR_SensorImpl_h
diff --git a/LibOVR/Src/OVR_SensorImpl_Common.cpp b/LibOVR/Src/OVR_SensorImpl_Common.cpp
new file mode 100644
index 0000000..99febe8
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorImpl_Common.cpp
@@ -0,0 +1,245 @@
+/************************************************************************************
+
+Filename    :   OVR_SensorImpl_Common.cpp
+Content     :   Source common to SensorImpl and Sensor2Impl.
+Created     :   January 21, 2014
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_SensorImpl_Common.h"
+#include "Kernel/OVR_Alg.h"
+
+namespace OVR 
+{
+
+void UnpackSensor(const UByte* buffer, SInt32* x, SInt32* y, SInt32* z)
+{
+    // Sign extending trick
+    // from http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
+    struct {SInt32 x:21;} s;
+
+    *x = s.x = (buffer[0] << 13) | (buffer[1] << 5) | ((buffer[2] & 0xF8) >> 3);
+    *y = s.x = ((buffer[2] & 0x07) << 18) | (buffer[3] << 10) | (buffer[4] << 2) |
+               ((buffer[5] & 0xC0) >> 6);
+    *z = s.x = ((buffer[5] & 0x3F) << 15) | (buffer[6] << 7) | (buffer[7] >> 1);
+}
+
+void PackSensor(UByte* buffer, SInt32 x, SInt32 y, SInt32 z)
+{
+    // Pack 3 32 bit integers into 8 bytes
+    buffer[0] = UByte(x >> 13);
+    buffer[1] = UByte(x >> 5);
+    buffer[2] = UByte((x << 3) | ((y >> 18) & 0x07));
+    buffer[3] = UByte(y >> 10);
+    buffer[4] = UByte(y >> 2);
+    buffer[5] = UByte((y << 6) | ((z >> 15) & 0x3F));
+    buffer[6] = UByte(z >> 7);
+    buffer[7] = UByte(z << 1);
+}
+
+UInt16 SelectSensorRampValue(const UInt16* ramp, unsigned count,
+                                    float val, float factor, const char* label)
+{    
+    UInt16 threshold = (UInt16)(val * factor);
+
+    for (unsigned i = 0; i<count; i++)
+    {
+        if (ramp[i] >= threshold)
+            return ramp[i];
+    }
+    OVR_DEBUG_LOG(("SensorDevice::SetRange - %s clamped to %0.4f",
+                   label, float(ramp[count-1]) / factor));
+    OVR_UNUSED2(factor, label);
+    return ramp[count-1];
+}
+
+SensorRangeImpl::SensorRangeImpl(const SensorRange& r, UInt16 commandId)
+{
+    SetSensorRange(r, commandId);
+}
+
+void SensorRangeImpl::SetSensorRange(const SensorRange& r, UInt16 commandId)
+{
+    CommandId  = commandId;
+    AccelScale = SelectSensorRampValue(AccelRangeRamp, sizeof(AccelRangeRamp)/sizeof(AccelRangeRamp[0]),
+                                        r.MaxAcceleration, (1.0f / 9.81f), "MaxAcceleration");
+    GyroScale  = SelectSensorRampValue(GyroRangeRamp, sizeof(GyroRangeRamp)/sizeof(GyroRangeRamp[0]),
+                                        r.MaxRotationRate, Math<float>::RadToDegreeFactor, "MaxRotationRate");
+    MagScale   = SelectSensorRampValue(MagRangeRamp, sizeof(MagRangeRamp)/sizeof(MagRangeRamp[0]),
+                                        r.MaxMagneticField, 1000.0f, "MaxMagneticField");
+    Pack();
+}
+
+void SensorRangeImpl::GetSensorRange(SensorRange* r)
+{
+    r->MaxAcceleration = AccelScale * 9.81f;
+    r->MaxRotationRate = DegreeToRad((float)GyroScale);
+    r->MaxMagneticField= MagScale * 0.001f;
+}
+
+SensorRange SensorRangeImpl::GetMaxSensorRange()
+{
+    return SensorRange(AccelRangeRamp[sizeof(AccelRangeRamp)/sizeof(AccelRangeRamp[0]) - 1] * 9.81f,
+                        GyroRangeRamp[sizeof(GyroRangeRamp)/sizeof(GyroRangeRamp[0]) - 1] *
+                            Math<float>::DegreeToRadFactor,
+                        MagRangeRamp[sizeof(MagRangeRamp)/sizeof(MagRangeRamp[0]) - 1] * 0.001f);
+}
+
+void SensorRangeImpl::Pack()
+{
+    Buffer[0] = 4;
+    Buffer[1] = UByte(CommandId & 0xFF);
+    Buffer[2] = UByte(CommandId >> 8);
+    Buffer[3] = UByte(AccelScale);
+    Buffer[4] = UByte(GyroScale & 0xFF);
+    Buffer[5] = UByte(GyroScale >> 8);
+    Buffer[6] = UByte(MagScale & 0xFF);
+    Buffer[7] = UByte(MagScale >> 8);
+}
+
+void SensorRangeImpl::Unpack()
+{
+    CommandId = Buffer[1] | (UInt16(Buffer[2]) << 8);
+    AccelScale= Buffer[3];
+    GyroScale = Buffer[4] | (UInt16(Buffer[5]) << 8);
+    MagScale  = Buffer[6] | (UInt16(Buffer[7]) << 8);
+}
+
+SensorConfigImpl::SensorConfigImpl() 
+    :   CommandId(0), Flags(0), PacketInterval(0), SampleRate(0)
+{
+    memset(Buffer, 0, PacketSize);
+    Buffer[0] = 2;
+}
+
+void SensorConfigImpl::SetSensorCoordinates(bool sensorCoordinates)
+{ 
+    Flags = (Flags & ~Flag_SensorCoordinates) | (sensorCoordinates ? Flag_SensorCoordinates : 0); 
+}
+
+bool SensorConfigImpl::IsUsingSensorCoordinates() const
+{ 
+    return (Flags & Flag_SensorCoordinates) != 0; 
+}
+
+void SensorConfigImpl::Pack()
+{
+    Buffer[0] = 2;
+    Buffer[1] = UByte(CommandId & 0xFF);
+    Buffer[2] = UByte(CommandId >> 8);
+    Buffer[3] = Flags;
+    Buffer[4] = UByte(PacketInterval);
+    Buffer[5] = UByte(SampleRate & 0xFF);
+    Buffer[6] = UByte(SampleRate >> 8);
+}
+
+void SensorConfigImpl::Unpack()
+{
+    CommandId		= Buffer[1] | (UInt16(Buffer[2]) << 8);
+    Flags			= Buffer[3];
+    PacketInterval	= Buffer[4];
+    SampleRate		= Buffer[5] | (UInt16(Buffer[6]) << 8);
+}
+
+SensorFactoryCalibrationImpl::SensorFactoryCalibrationImpl() 
+    : AccelOffset(), GyroOffset(), AccelMatrix(), GyroMatrix(), Temperature(0)
+{
+    memset(Buffer, 0, PacketSize);
+    Buffer[0] = 3;
+}
+
+void SensorFactoryCalibrationImpl::Pack()
+{
+    SInt32 x, y, z;
+
+    Buffer[0] = 3;
+
+    x = SInt32(AccelOffset.x * 1e4f);
+    y = SInt32(AccelOffset.y * 1e4f);
+    z = SInt32(AccelOffset.z * 1e4f);
+    PackSensor(Buffer + 3, x, y, z);
+
+    x = SInt32(GyroOffset.x * 1e4f);
+    y = SInt32(GyroOffset.y * 1e4f);
+    z = SInt32(GyroOffset.z * 1e4f);
+    PackSensor(Buffer + 11, x, y, z);
+
+    // ignore the scale matrices for now
+}
+
+void SensorFactoryCalibrationImpl::Unpack()
+{
+    static const float sensorMax = (1 << 20) - 1;
+    SInt32 x, y, z;
+
+    UnpackSensor(Buffer + 3, &x, &y, &z);
+    AccelOffset.y = (float) y * 1e-4f;
+    AccelOffset.z = (float) z * 1e-4f;
+    AccelOffset.x = (float) x * 1e-4f;
+
+    UnpackSensor(Buffer + 11, &x, &y, &z);
+    GyroOffset.x = (float) x * 1e-4f;
+    GyroOffset.y = (float) y * 1e-4f;
+    GyroOffset.z = (float) z * 1e-4f;
+
+    for (int i = 0; i < 3; i++)
+    {
+        UnpackSensor(Buffer + 19 + 8 * i, &x, &y, &z);
+        AccelMatrix.M[i][0] = (float) x / sensorMax;
+        AccelMatrix.M[i][1] = (float) y / sensorMax;
+        AccelMatrix.M[i][2] = (float) z / sensorMax;
+        AccelMatrix.M[i][i] += 1.0f;
+    }
+
+    for (int i = 0; i < 3; i++)
+    {
+        UnpackSensor(Buffer + 43 + 8 * i, &x, &y, &z);
+        GyroMatrix.M[i][0] = (float) x / sensorMax;
+        GyroMatrix.M[i][1] = (float) y / sensorMax;
+        GyroMatrix.M[i][2] = (float) z / sensorMax;
+        GyroMatrix.M[i][i] += 1.0f;
+    }
+
+    Temperature = (float) Alg::DecodeSInt16(Buffer + 67) / 100.0f;
+}
+
+SensorKeepAliveImpl::SensorKeepAliveImpl(UInt16 interval, UInt16 commandId)
+    : CommandId(commandId), KeepAliveIntervalMs(interval)
+{
+    Pack();
+}
+
+void SensorKeepAliveImpl::Pack()
+{
+    Buffer[0] = 8;
+    Buffer[1] = UByte(CommandId & 0xFF);
+    Buffer[2] = UByte(CommandId >> 8);
+    Buffer[3] = UByte(KeepAliveIntervalMs & 0xFF);
+    Buffer[4] = UByte(KeepAliveIntervalMs >> 8);
+}
+
+void SensorKeepAliveImpl::Unpack()
+{
+    CommandId          = Buffer[1] | (UInt16(Buffer[2]) << 8);
+    KeepAliveIntervalMs= Buffer[3] | (UInt16(Buffer[4]) << 8);
+}
+
+} // namespace OVR
diff --git a/LibOVR/Src/OVR_SensorImpl_Common.h b/LibOVR/Src/OVR_SensorImpl_Common.h
new file mode 100644
index 0000000..a7091ba
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorImpl_Common.h
@@ -0,0 +1,150 @@
+/************************************************************************************
+
+Filename    :   OVR_SensorImpl_Common.h
+Content     :   Source common to SensorImpl and Sensor2Impl.
+Created     :   January 21, 2014
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_SensorImpl_Common_h
+#define OVR_SensorImpl_Common_h
+
+#include "Kernel/OVR_System.h"
+#include "OVR_Device.h"
+
+namespace OVR 
+{
+
+void UnpackSensor(const UByte* buffer, SInt32* x, SInt32* y, SInt32* z);
+void PackSensor(UByte* buffer, SInt32 x, SInt32 y, SInt32 z);
+
+// Sensor HW only accepts specific maximum range values, used to maximize
+// the 16-bit sensor outputs. Use these ramps to specify and report appropriate values.
+const UInt16 AccelRangeRamp[] = { 2, 4, 8, 16 };
+const UInt16 GyroRangeRamp[]  = { 250, 500, 1000, 2000 };
+const UInt16 MagRangeRamp[]   = { 880, 1300, 1900, 2500 };
+
+UInt16 SelectSensorRampValue(const UInt16* ramp, unsigned count,
+                                    float val, float factor, const char* label);
+
+// SensorScaleImpl provides buffer packing logic for the Sensor Range
+// record that can be applied to DK1 sensor through Get/SetFeature. We expose this
+// through SensorRange class, which has different units.
+struct SensorRangeImpl
+{
+    enum  { PacketSize = 8 };
+    UByte   Buffer[PacketSize];
+    
+    UInt16  CommandId;
+    UInt16  AccelScale;
+    UInt16  GyroScale;
+    UInt16  MagScale;
+
+    SensorRangeImpl(const SensorRange& r, UInt16 commandId = 0);
+
+    void SetSensorRange(const SensorRange& r, UInt16 commandId = 0);
+    void GetSensorRange(SensorRange* r);
+
+    static SensorRange GetMaxSensorRange();
+
+    void  Pack();
+    void Unpack();
+};
+
+struct SensorConfigImpl
+{
+    enum  { PacketSize = 7 };
+    UByte   Buffer[PacketSize];
+
+    // Flag values for Flags.
+    enum {
+        Flag_RawMode            = 0x01,
+        Flag_CalibrationTest	= 0x02, // Internal test mode
+        Flag_UseCalibration		= 0x04,
+        Flag_AutoCalibration	= 0x08,
+        Flag_MotionKeepAlive    = 0x10,
+        Flag_CommandKeepAlive   = 0x20,
+        Flag_SensorCoordinates  = 0x40
+    };
+
+    UInt16  CommandId;
+    UByte   Flags;
+    UInt16  PacketInterval;		// LDC - This should be a UByte. Fix when you have time to test it.
+    UInt16  SampleRate;
+
+    SensorConfigImpl();
+
+    void    SetSensorCoordinates(bool sensorCoordinates);
+    bool    IsUsingSensorCoordinates() const;
+
+    void Pack();
+    void Unpack();
+};
+
+struct SensorFactoryCalibrationImpl
+{
+    enum  { PacketSize = 69 };
+    UByte   Buffer[PacketSize];
+    
+    Vector3f AccelOffset;
+    Vector3f GyroOffset;
+    Matrix4f AccelMatrix;
+    Matrix4f GyroMatrix;
+    float    Temperature;
+
+    SensorFactoryCalibrationImpl();
+
+    void     Pack();    // Not yet implemented.
+    void     Unpack();
+};
+
+
+// SensorKeepAlive - feature report that needs to be sent at regular intervals for sensor
+// to receive commands.
+struct SensorKeepAliveImpl
+{
+    enum  { PacketSize = 5 };
+    UByte   Buffer[PacketSize];
+
+    UInt16  CommandId;
+    UInt16  KeepAliveIntervalMs;
+
+    SensorKeepAliveImpl(UInt16 interval = 0, UInt16 commandId = 0);
+
+    void Pack();
+    void Unpack();
+};
+
+struct TrackerSample
+{
+    SInt32 AccelX, AccelY, AccelZ;
+    SInt32 GyroX, GyroY, GyroZ;
+};
+
+enum LastCommandIdFlags
+{
+    LastCommandId_Shutter = 1,
+    LastCommandId_LEDs    = 2
+};
+
+} // namespace OVR
+
+#endif // OVR_SensorImpl_Common_h
diff --git a/LibOVR/Src/OVR_SensorTimeFilter.cpp b/LibOVR/Src/OVR_SensorTimeFilter.cpp
new file mode 100644
index 0000000..ee0c385
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorTimeFilter.cpp
@@ -0,0 +1,385 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_SensorTimeFilter.cpp
+Content     :   Class to filter HMD time and convert it to system time
+Created     :   December 20, 2013
+Author      :   Michael Antonov
+Notes       :
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_SensorTimeFilter.h"
+#include "Kernel/OVR_Log.h"
+
+
+#include <stdio.h>
+#include <math.h>
+
+namespace OVR {  
+
+// Comment out for debug logging to file
+//#define OVR_TIMEFILTER_LOG_CODE( code )  code
+#define OVR_TIMEFILTER_LOG_CODE( code )
+
+#if defined(OVR_OS_ANDROID)
+    #define OVR_TIMEFILTER_LOG_FILENAME "/sdcard/TimeFilterLog.txt"
+#elif defined(OVR_OS_WIN32)
+    #define OVR_TIMEFILTER_LOG_FILENAME "C:\\TimeFilterLog.txt"
+#else
+    #define OVR_TIMEFILTER_LOG_FILENAME "TimeFilterLog.txt"
+#endif
+
+OVR_TIMEFILTER_LOG_CODE( FILE* pTFLogFile = 0; )
+
+
+// Ideally, the following would always be true:
+//  - NewSampleTime > PrevSample
+//  - NewSampleTime < now systemTime
+//  - (NewSampleTime - PrevSampleTime) == integration delta, matching
+//    HW sample time difference + drift
+//
+// In practice, these issues affect us:
+//  - System thread can be suspended for a while
+//  - System de-buffering of recorded samples cause deviceTime to advance up
+//    much faster then system time for ~100+ samples
+//  - Device (DK1) and system clock granularities are high; this can
+//    lead to potentially having estimations in the future
+//
+
+
+// ***** TimerFilter
+
+SensorTimeFilter::SensorTimeFilter(const Settings& settings)
+{
+    FilterSettings = settings;
+
+    ClockInitialized             = false;
+    ClockDelta                   = 0;       
+    ClockDeltaDriftPerSecond     = 0;
+    ClockDeltaCorrectPerSecond   = 0;
+    ClockDeltaCorrectSecondsLeft = 0;
+    OldClockDeltaDriftExpire     = 0;
+
+    LastLargestDeviceTime = 0;
+    PrevSystemTime        = 0;    
+    PastSampleResetTime   = 0;
+
+    MinWindowsCollected  = 0;
+    MinWindowDuration    = 0; // assigned later
+    MinWindowLastTime    = 0;
+    MinWindowSamples     = settings.MinSamples; // Force initialization
+
+    OVR_TIMEFILTER_LOG_CODE( pTFLogFile = fopen(OVR_TIMEFILTER_LOG_FILENAME, "w+"); )
+}
+
+
+double SensorTimeFilter::SampleToSystemTime(double sampleDeviceTime, double systemTime,
+                                            double prevResult, const char* debugTag)
+{
+    double clockDelta      = systemTime - sampleDeviceTime + FilterSettings.ClockDeltaAdjust;
+    double deviceTimeDelta = sampleDeviceTime - LastLargestDeviceTime;       
+    double result;
+
+    // Collect a sample ClockDelta for a "MinimumWindow" or process
+    // the window by adjusting drift rates if it's full of samples.
+    //   - (deviceTimeDelta < 1.0f) is a corner cases, as it would imply timestamp skip/wrap.
+
+    if (ClockInitialized)
+    {
+        // Samples in the past commonly occur if they come from separately incrementing
+        // data channels. Just adjust them with ClockDelta.
+
+        if (deviceTimeDelta < 0.0)
+        {
+            result = sampleDeviceTime + ClockDelta;
+
+            if (result > (prevResult - 0.00001))
+                goto clamp_and_log_result;
+
+            // Consistent samples less then prevResult for indicate a back-jump or bad input.
+            // In this case we return prevResult for a while, then reset filter if it keeps going.
+            if (PastSampleResetTime < 0.0001)
+            {
+                PastSampleResetTime = systemTime + FilterSettings.PastSampleResetSeconds;
+                goto clamp_and_log_result;
+            }
+            else if (systemTime > PastSampleResetTime) 
+            {
+                OVR_DEBUG_LOG(("SensorTimeFilter - Filtering reset due to samples in the past!\n"));
+                initClockSampling(sampleDeviceTime, clockDelta);
+                // Fall through to below, to ' PastSampleResetTime = 0.0; '
+            }
+            else
+            {
+                goto clamp_and_log_result;
+            }
+        }
+
+        // Most common case: Record window sample.
+        else if ( (deviceTimeDelta < 1.0f) &&
+                  ( (sampleDeviceTime < MinWindowLastTime) ||
+                  (MinWindowSamples < FilterSettings.MinSamples) ) )
+        {
+            // Pick minimum ClockDelta sample.
+            if (clockDelta < MinWindowClockDelta)
+                MinWindowClockDelta = clockDelta;
+            MinWindowSamples++;        
+        }
+        else
+        {
+            processFinishedMinWindow(sampleDeviceTime, clockDelta);
+        }
+
+        PastSampleResetTime = 0.0;
+    }
+    else
+    {
+        initClockSampling(sampleDeviceTime, clockDelta);
+    }
+        
+
+    // Clock adjustment for drift.
+    ClockDelta += ClockDeltaDriftPerSecond  * deviceTimeDelta;
+
+    // ClockDelta "nudging" towards last known MinWindowClockDelta.
+    if (ClockDeltaCorrectSecondsLeft > 0.000001)
+    {
+        double correctTimeDelta = deviceTimeDelta;
+        if (deviceTimeDelta > ClockDeltaCorrectSecondsLeft)        
+            correctTimeDelta = ClockDeltaCorrectSecondsLeft;
+        ClockDeltaCorrectSecondsLeft -= correctTimeDelta;
+        
+        ClockDelta += ClockDeltaCorrectPerSecond  * correctTimeDelta;
+    }
+
+    // Record largest device time, so we know what samples to use in accumulation
+    // of min-window in the future.
+    LastLargestDeviceTime = sampleDeviceTime;
+
+    // Compute our resulting sample time after ClockDelta adjustment.
+    result = sampleDeviceTime + ClockDelta;
+
+    
+clamp_and_log_result:
+
+    OVR_TIMEFILTER_LOG_CODE( double savedResult = result; )
+
+    // Clamp to ensure that result >= PrevResult, or not to far in the future.
+    // Future clamp primarily happens in the very beginning if we are de-queuing
+    // system buffer full of samples.
+    if (result < prevResult)
+    {
+        result = prevResult;
+    }    
+    if (result > (systemTime + FilterSettings.FutureClamp))
+    {
+        result = (systemTime + FilterSettings.FutureClamp);
+    }
+
+    OVR_TIMEFILTER_LOG_CODE(
+
+        // Tag lines that were outside desired range, with '<' or '>'.
+        char rangeClamp         = ' '; 
+        char resultDeltaFar     = ' ';
+
+        if (savedResult > (systemTime + 0.0000001))
+            rangeClamp = '>';
+        if (savedResult < prevResult)
+            rangeClamp = '<';
+
+        // Tag any result delta outside desired threshold with a '*'.
+        if (fabs(deviceTimeDelta - (result - prevResult)) >= 0.00002)
+            resultDeltaFar = '*';
+    
+        fprintf(pTFLogFile, "Res%s = %13.7f, dt = % 8.7f,  ClkD = %13.6f  "
+                            "sysT = %13.6f, sysDt = %f,  "
+                            "sysDiff = % f, devT = %11.6f,  ddevT = %9.6f %c%c\n",
+                            debugTag, result, result - prevResult, ClockDelta,
+                            systemTime, systemTime - PrevSystemTime,
+                            -(systemTime - result),  // Negatives in the past, positive > now.
+                            sampleDeviceTime,  deviceTimeDelta, rangeClamp, resultDeltaFar);
+
+        ) // OVR_TIMEFILTER_LOG_CODE()
+    OVR_UNUSED(debugTag);
+
+    // Record prior values. Useful or logging and clamping.
+    PrevSystemTime = systemTime;    
+
+    return result;    
+}
+
+
+void SensorTimeFilter::initClockSampling(double sampleDeviceTime, double clockDelta)
+{
+    ClockInitialized             = true;
+    ClockDelta                   = clockDelta;
+    ClockDeltaDriftPerSecond     = 0;
+    OldClockDeltaDriftExpire     = 0;
+    ClockDeltaCorrectSecondsLeft = 0;
+    ClockDeltaCorrectPerSecond   = 0;
+
+    MinWindowsCollected          = 0;
+    MinWindowDuration            = 0.25;
+    MinWindowClockDelta          = clockDelta;
+    MinWindowLastTime            = sampleDeviceTime + MinWindowDuration;
+    MinWindowSamples             = 0;
+}
+
+
+void SensorTimeFilter::processFinishedMinWindow(double sampleDeviceTime, double clockDelta)
+{
+    MinRecord newRec = { MinWindowClockDelta, sampleDeviceTime };
+    
+    double    clockDeltaDiff    = MinWindowClockDelta - ClockDelta;
+    double    absClockDeltaDiff = fabs(clockDeltaDiff);
+
+
+    // Abrupt change causes Reset of minClockDelta collection.
+    //  > 8 ms would a Large jump in a minimum sample, as those are usually stable.
+    //  > 1 second intantaneous jump would land us here as well, as that would imply
+    //    device being suspended, clock wrap or some other unexpected issue.
+    if ((absClockDeltaDiff > 0.008) ||
+        ((sampleDeviceTime - LastLargestDeviceTime) >= 1.0))
+    {            
+        OVR_TIMEFILTER_LOG_CODE(
+            fprintf(pTFLogFile,
+                    "\nMinWindow Finished:  %d Samples, MinWindowClockDelta=%f, MW-CD=%f,"
+                    "  ** ClockDelta Reset **\n\n",
+                    MinWindowSamples, MinWindowClockDelta, MinWindowClockDelta-ClockDelta);
+            )
+
+        // Use old collected ClockDeltaDriftPerSecond drift value 
+        // up to 1 minute until we collect better samples.
+        if (!MinRecords.IsEmpty())
+        {
+            OldClockDeltaDriftExpire = MinRecords.GetNewest().LastSampleDeviceTime -
+                                       MinRecords.GetOldest().LastSampleDeviceTime;
+            if (OldClockDeltaDriftExpire > 60.0)
+                OldClockDeltaDriftExpire = 60.0;
+            OldClockDeltaDriftExpire += sampleDeviceTime;           
+        }
+
+        // Jump to new ClockDelta value.
+        if ((sampleDeviceTime - LastLargestDeviceTime) > 1.0)
+            ClockDelta = clockDelta;
+        else
+            ClockDelta = MinWindowClockDelta;
+
+        ClockDeltaCorrectSecondsLeft = 0;
+        ClockDeltaCorrectPerSecond   = 0;
+
+        // Reset buffers, we'll be collecting a new MinWindow.
+        MinRecords.Reset();
+        MinWindowsCollected = 0;
+        MinWindowDuration   = 0.25;
+        MinWindowSamples    = 0;
+    }
+    else
+    {        
+        OVR_ASSERT(MinWindowSamples >= FilterSettings.MinSamples);
+
+        double timeElapsed = 0;
+
+        // If we have older values, use them to update clock drift in 
+        // ClockDeltaDriftPerSecond
+        if (!MinRecords.IsEmpty() && (sampleDeviceTime > OldClockDeltaDriftExpire))
+        {
+            MinRecord rec = MinRecords.GetOldest();
+
+            // Compute clock rate of drift.            
+            timeElapsed = sampleDeviceTime - rec.LastSampleDeviceTime;
+
+            // Check for divide by zero shouldn't be necessary here, but just be be safe...
+            if (timeElapsed > 0.000001)
+            {
+                ClockDeltaDriftPerSecond = (MinWindowClockDelta - rec.MinClockDelta) / timeElapsed;
+                ClockDeltaDriftPerSecond = clampRate(ClockDeltaDriftPerSecond,
+                                                      FilterSettings.MaxChangeRate);
+            }
+            else
+            {
+                ClockDeltaDriftPerSecond = 0.0;
+            }
+        }
+
+        MinRecords.AddRecord(newRec);
+
+
+        // Catchup correction nudges ClockDelta towards MinWindowClockDelta.
+        // These are needed because clock drift correction alone is not enough
+        // for past accumulated error/high-granularity clock delta changes.
+        // The further away we are, the stronger correction we apply.
+        // Correction has timeout, as we don't want it to overshoot in case
+        // of a large delay between samples.
+       
+        if (absClockDeltaDiff >= 0.00125)
+        {
+            // Correct large discrepancy immediately.
+            if (absClockDeltaDiff > 0.00175)
+            {
+                if (clockDeltaDiff > 0)
+                    ClockDelta += (clockDeltaDiff - 0.00175);
+                else
+                    ClockDelta += (clockDeltaDiff + 0.00175);
+
+                clockDeltaDiff = MinWindowClockDelta - ClockDelta;
+            }
+
+            ClockDeltaCorrectPerSecond   = clockDeltaDiff;
+            ClockDeltaCorrectSecondsLeft = 1.0;
+        }            
+        else if (absClockDeltaDiff > 0.0005)
+        {                
+            ClockDeltaCorrectPerSecond   = clockDeltaDiff / 8.0;
+            ClockDeltaCorrectSecondsLeft = 8.0;
+        }
+        else
+        {                
+            ClockDeltaCorrectPerSecond   = clockDeltaDiff / 15.0;
+            ClockDeltaCorrectSecondsLeft = 15.0;
+        }
+
+        ClockDeltaCorrectPerSecond = clampRate(ClockDeltaCorrectPerSecond,
+                                               FilterSettings.MaxCorrectRate);
+
+        OVR_TIMEFILTER_LOG_CODE(
+            fprintf(pTFLogFile,
+                    "\nMinWindow Finished:  %d Samples, MinWindowClockDelta=%f, MW-CD=%f,"
+                    " tileElapsed=%f, ClockChange=%f, ClockCorrect=%f\n\n",
+                    MinWindowSamples, MinWindowClockDelta, MinWindowClockDelta-ClockDelta,
+                    timeElapsed, ClockDeltaDriftPerSecond, ClockDeltaCorrectPerSecond);
+            )                           
+    }
+
+    // New MinClockDelta collection window.
+    // Switch to longer duration after first few windows.
+    MinWindowsCollected ++;
+    if (MinWindowsCollected > 5)
+        MinWindowDuration = 0.5; 
+
+    MinWindowClockDelta = clockDelta;
+    MinWindowLastTime   = sampleDeviceTime + MinWindowDuration;
+    MinWindowSamples    = 0;
+}
+
+
+} // namespace OVR
+
diff --git a/LibOVR/Src/OVR_SensorTimeFilter.h b/LibOVR/Src/OVR_SensorTimeFilter.h
new file mode 100644
index 0000000..409fe66
--- /dev/null
+++ b/LibOVR/Src/OVR_SensorTimeFilter.h
@@ -0,0 +1,226 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_SensorTimeFilter.h
+Content     :   Class to filter HMD time and convert it to system time
+Created     :   December 20, 2013
+Author      :   Michael Antonov
+Notes       :
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_SensorTimeFilter_h
+#define OVR_SensorTimeFilter_h
+
+#include "Kernel/OVR_Types.h"
+
+namespace OVR {  
+    
+
+//-----------------------------------------------------------------------------------
+// ***** SensorTimeFilter
+    
+// SensorTimeFilter converts sample device time, in seconds, to absolute system
+// time. It filter maintains internal state to estimate the following:
+//
+//  - Difference between system and device time values (ClockDelta).
+//      ~= (systemTime - deviceTime)
+//  - Drift rate between system and device clocks (ClockDeltaDriftPerSecond).
+//
+//  Additionally, the following criteria are enforced:
+//   - Resulting samples must be increasing, compared to prevSample.
+//   - Returned sample time should not exceed 'now' system time by more then a fixed
+//     value.
+//       * Ideally this should be 0, however, enforcing this is hard when clocks
+//         have high discrete values.
+//   - Returned sample AbsoluteTime values deltas are very close to HW samples,
+//     adjusted by drift rate. Note that this is not always possible due to clamping,
+//     in which case it is better to use ScaleTimeUnit(deviceTimeDelta) 
+//     for integration.
+//
+// Algorithm: We collect minimum ClockDelta  on windows of 
+// consecutive samples (500 ms each set). Long term difference between sample
+// set minimums is drift. ClockDelta is also continually nudged towards most recent
+// minimum. 
+
+class SensorTimeFilter
+{
+public:
+
+    // It may be desirable to configure these per device/platform.
+    // For example, rates can be tighter for DK2 because of microsecond clock.    
+    struct Settings
+    {
+        Settings(int minSamples = 50,
+                 double clockDeltaAdjust = -0.0002, // 200 mks in the past.
+                 double futureClamp      = 0.0008)
+            : MinSamples(minSamples),
+              ClockDeltaAdjust(clockDeltaAdjust), 
+          //    PastClamp(-0.032),
+              FutureClamp(futureClamp),
+              PastSampleResetSeconds(0.2),
+              MaxChangeRate(0.004),
+              MaxCorrectRate(0.004)
+        { }
+
+        // Minimum number of samples in a window. Different number may be desirable
+        // based on how often samples come in.
+        int    MinSamples;
+
+        // Factor always added to ClockDelta, used to skew all values into the past by fixed
+        // value and reduce the chances we report a sample "in the future".        
+        double ClockDeltaAdjust;  
+        // How much away in a past can a sample be before being shifted closer to system time.
+        //double PastClamp;
+        // How much larger then systemTime can a value be? Set to 0 to clamp to null,
+        // put small positive value is better.
+        double FutureClamp;
+
+        // How long (in system time) do we take to reset the system if a device sample.
+        // comes in the past. Generally, this should never happened, but exists as a way to
+        // address bad timing coming form firmware (temp CCove issue, presumably fixed)
+        // or buggy input.
+        double PastSampleResetSeconds;
+
+        // Maximum drift change and near-term correction rates, in seconds.
+        double MaxChangeRate;
+        double MaxCorrectRate;
+    };
+
+
+    SensorTimeFilter(const Settings& settings = Settings());
+
+
+    // Convert device sample time to system time, driving clock drift estimation.    
+    // Input:  SampleTime, System Time
+    // Return: Absolute system time for sample
+    double SampleToSystemTime(double sampleDeviceTime, double systemTime,
+                              double prevResult, const char* debugTag = "");
+
+
+    // Scales device time to account for drift.
+    double ScaleTimeUnit(double deviceClockDelta)
+    {
+        return deviceClockDelta * (1.0 + ClockDeltaDriftPerSecond);
+    }
+
+    // Return currently estimated difference between the clocks.
+    double GetClockDelta() const { return ClockDelta; }
+    
+
+private:
+
+    void   initClockSampling(double sampleDeviceTime, double clockDelta);
+    void   processFinishedMinWindow(double sampleDeviceTime, double systemTime);
+
+    static double clampRate(double rate, double limit)
+    {
+        if (rate > limit)
+            rate = limit;
+        else if (rate < -limit)
+            rate = -limit;
+        return rate;
+    }
+
+
+    // Describes minimum observed ClockDelta for sample set seen in the past.
+    struct MinRecord
+    {
+        double  MinClockDelta;
+        double  LastSampleDeviceTime;
+    };
+
+    // Circular buffer storing MinRecord(s) several minutes into the past.
+    // Oldest value here is used to help estimate drift.
+    class MinRecordBuffer
+    {
+        enum { BufferSize = 60*6 }; // 3 min
+    public:
+
+        MinRecordBuffer() : Head(0), Tail(0) { }
+
+        void      Reset()         { Head = Tail = 0; }
+        bool      IsEmpty() const { return Head == Tail; }
+
+        const MinRecord& GetOldest() const
+        {
+            OVR_ASSERT(!IsEmpty());
+            return Records[Tail];
+        }
+        const MinRecord& GetNewest() const
+        {
+            OVR_ASSERT(!IsEmpty());
+            return Records[(BufferSize + Head - 1) % BufferSize];
+        }
+
+        void     AddRecord(const MinRecord& rec)
+        {
+            Records[Head] = rec;
+            Head = advanceIndex(Head);
+            if (Head == Tail)
+                Tail = advanceIndex(Tail);
+        }
+
+    private:
+
+        static int advanceIndex(int index)
+        {
+            index++;
+            if (index >= BufferSize)
+                index = 0;
+            return index;
+        }
+
+        MinRecord Records[BufferSize];
+        int       Head;  // Location we will most recent entry, unused.
+        int       Tail;  // Oldest entry.
+    };
+
+
+    Settings    FilterSettings;
+
+    // Clock correction state.
+    bool        ClockInitialized;
+    double      ClockDelta;    
+    double      ClockDeltaDriftPerSecond;
+    double      ClockDeltaCorrectPerSecond;
+    double      ClockDeltaCorrectSecondsLeft;
+    double      OldClockDeltaDriftExpire;
+    
+    double      LastLargestDeviceTime;
+    double      PrevSystemTime;    
+    // Used to reset timing if we get multiple "samples in the past"
+    double      PastSampleResetTime;
+
+    // "MinWindow" is a block of time during which minimum ClockDelta values
+    // are collected into MinWindowClockDelta.
+    int         MinWindowsCollected;
+    double      MinWindowDuration; // Device sample seconds
+    double      MinWindowLastTime;
+    double      MinWindowClockDelta;
+    int         MinWindowSamples;
+
+    // Historic buffer used to determine rate of clock change over time.
+    MinRecordBuffer MinRecords;
+};
+
+} // namespace OVR
+
+#endif // OVR_SensorTimeFilter_h
diff --git a/LibOVR/Src/OVR_Stereo.cpp b/LibOVR/Src/OVR_Stereo.cpp
new file mode 100644
index 0000000..936a02a
--- /dev/null
+++ b/LibOVR/Src/OVR_Stereo.cpp
@@ -0,0 +1,1805 @@
+/************************************************************************************
+
+Filename    :   OVR_Stereo.cpp
+Content     :   Stereo rendering functions
+Created     :   November 30, 2013
+Authors     :   Tom Fosyth
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "OVR_Stereo.h"
+#include "OVR_Profile.h"
+#include "Kernel/OVR_Log.h"
+#include "Kernel/OVR_Alg.h"
+
+//To allow custom distortion to be introduced to CatMulSpline.
+float (*CustomDistortion)(float) = NULL;
+float (*CustomDistortionInv)(float) = NULL;
+
+
+namespace OVR {
+
+
+using namespace Alg;
+
+//-----------------------------------------------------------------------------------
+
+// Inputs are 4 points (pFitX[0],pFitY[0]) through (pFitX[3],pFitY[3])
+// Result is four coefficients in pResults[0] through pResults[3] such that
+//      y = pResult[0] + x * ( pResult[1] + x * ( pResult[2] + x * ( pResult[3] ) ) );
+// passes through all four input points.
+// Return is true if it succeeded, false if it failed (because two control points
+// have the same pFitX value).
+bool FitCubicPolynomial ( float *pResult, const float *pFitX, const float *pFitY )
+{
+    float d0 = ( ( pFitX[0]-pFitX[1] ) * ( pFitX[0]-pFitX[2] ) * ( pFitX[0]-pFitX[3] ) );
+    float d1 = ( ( pFitX[1]-pFitX[2] ) * ( pFitX[1]-pFitX[3] ) * ( pFitX[1]-pFitX[0] ) );
+    float d2 = ( ( pFitX[2]-pFitX[3] ) * ( pFitX[2]-pFitX[0] ) * ( pFitX[2]-pFitX[1] ) );
+    float d3 = ( ( pFitX[3]-pFitX[0] ) * ( pFitX[3]-pFitX[1] ) * ( pFitX[3]-pFitX[2] ) );
+
+    if ( ( d0 == 0.0f ) || ( d1 == 0.0f ) || ( d2 == 0.0f ) || ( d3 == 0.0f ) )
+    {
+        return false;
+    }
+
+    float f0 = pFitY[0] / d0;
+    float f1 = pFitY[1] / d1;
+    float f2 = pFitY[2] / d2;
+    float f3 = pFitY[3] / d3;
+
+    pResult[0] = -( f0*pFitX[1]*pFitX[2]*pFitX[3]
+                  + f1*pFitX[0]*pFitX[2]*pFitX[3]
+                  + f2*pFitX[0]*pFitX[1]*pFitX[3]
+                  + f3*pFitX[0]*pFitX[1]*pFitX[2] );
+    pResult[1] = f0*(pFitX[1]*pFitX[2] + pFitX[2]*pFitX[3] + pFitX[3]*pFitX[1])
+               + f1*(pFitX[0]*pFitX[2] + pFitX[2]*pFitX[3] + pFitX[3]*pFitX[0])
+               + f2*(pFitX[0]*pFitX[1] + pFitX[1]*pFitX[3] + pFitX[3]*pFitX[0])
+               + f3*(pFitX[0]*pFitX[1] + pFitX[1]*pFitX[2] + pFitX[2]*pFitX[0]);
+    pResult[2] = -( f0*(pFitX[1]+pFitX[2]+pFitX[3])
+                  + f1*(pFitX[0]+pFitX[2]+pFitX[3])
+                  + f2*(pFitX[0]+pFitX[1]+pFitX[3])
+                  + f3*(pFitX[0]+pFitX[1]+pFitX[2]) );
+    pResult[3] = f0 + f1 + f2 + f3;
+
+    return true;
+}
+
+
+
+float EvalCatmullRom10Spline ( float const *K, float scaledVal )
+{
+    int const NumSegments = LensConfig::NumCoefficients;
+
+    float scaledValFloor = floorf ( scaledVal );
+    scaledValFloor = Alg::Max ( 0.0f, Alg::Min ( (float)(NumSegments-1), scaledValFloor ) );
+    float t = scaledVal - scaledValFloor;
+    int k = (int)scaledValFloor;
+
+    float p0, p1;
+    float m0, m1;
+    switch ( k )
+    {
+    case 0:
+        // Curve starts at 1.0 with gradient K[1]-K[0]
+        p0 = 1.0f;
+        m0 =        ( K[1] - K[0] );    // general case would have been (K[1]-K[-1])/2
+        p1 = K[1];
+        m1 = 0.5f * ( K[2] - K[0] );
+        break;
+    default:
+        // General case
+        p0 = K[k  ];
+        m0 = 0.5f * ( K[k+1] - K[k-1] );
+        p1 = K[k+1];
+        m1 = 0.5f * ( K[k+2] - K[k  ] );
+        break;
+    case NumSegments-2:
+        // Last tangent is just the slope of the last two points.
+        p0 = K[NumSegments-2];
+        m0 = 0.5f * ( K[NumSegments-1] - K[NumSegments-2] );
+        p1 = K[NumSegments-1];
+        m1 = K[NumSegments-1] - K[NumSegments-2];
+        break;
+    case NumSegments-1:
+        // Beyond the last segment it's just a straight line
+        p0 = K[NumSegments-1];
+        m0 = K[NumSegments-1] - K[NumSegments-2];
+        p1 = p0 + m0;
+        m1 = m0;
+        break;
+    }
+
+    float omt = 1.0f - t;
+    float res  = ( p0 * ( 1.0f + 2.0f *   t ) + m0 *   t ) * omt * omt
+               + ( p1 * ( 1.0f + 2.0f * omt ) - m1 * omt ) *   t *   t;
+
+    return res;
+}
+
+
+
+
+// Converts a Profile eyecup string into an eyecup enumeration
+void SetEyeCup(HmdRenderInfo* renderInfo, const char* cup)
+{
+    if (OVR_strcmp(cup, "A") == 0)
+        renderInfo->EyeCups = EyeCup_DK1A;
+    else if (OVR_strcmp(cup, "B") == 0)
+        renderInfo->EyeCups = EyeCup_DK1B;
+    else if (OVR_strcmp(cup, "C") == 0)
+        renderInfo->EyeCups = EyeCup_DK1C;
+    else if (OVR_strcmp(cup, "Orange A") == 0)
+        renderInfo->EyeCups =  EyeCup_OrangeA;
+    else if (OVR_strcmp(cup, "Red A") == 0)
+        renderInfo->EyeCups = EyeCup_RedA;
+    else if (OVR_strcmp(cup, "Pink A") == 0)
+        renderInfo->EyeCups = EyeCup_PinkA;
+    else if (OVR_strcmp(cup, "Blue A") == 0)
+        renderInfo->EyeCups = EyeCup_BlueA;
+    else
+        renderInfo->EyeCups = EyeCup_DK1A;
+}
+
+
+
+//-----------------------------------------------------------------------------------
+
+
+// The result is a scaling applied to the distance.
+float LensConfig::DistortionFnScaleRadiusSquared (float rsq) const
+{
+    float scale = 1.0f;
+    switch ( Eqn )
+    {
+    case Distortion_Poly4:
+        // This version is deprecated! Prefer one of the other two.
+        scale = ( K[0] + rsq * ( K[1] + rsq * ( K[2] + rsq * K[3] ) ) );
+        break;
+    case Distortion_RecipPoly4:
+        scale = 1.0f / ( K[0] + rsq * ( K[1] + rsq * ( K[2] + rsq * K[3] ) ) );
+        break;
+    case Distortion_CatmullRom10:{
+        // A Catmull-Rom spline through the values 1.0, K[1], K[2] ... K[10]
+        // evenly spaced in R^2 from 0.0 to MaxR^2
+        // K[0] controls the slope at radius=0.0, rather than the actual value.
+        const int NumSegments = LensConfig::NumCoefficients;
+        OVR_ASSERT ( NumSegments <= NumCoefficients );
+        float scaledRsq = (float)(NumSegments-1) * rsq / ( MaxR * MaxR );
+        scale = EvalCatmullRom10Spline ( K, scaledRsq );
+
+
+		//Intercept, and overrule if needed
+		if (CustomDistortion)
+		{
+			scale = CustomDistortion(rsq);
+		}
+
+        }break;
+    default:
+        OVR_ASSERT ( false );
+        break;
+    }
+    return scale;
+}
+
+// x,y,z components map to r,g,b
+Vector3f LensConfig::DistortionFnScaleRadiusSquaredChroma (float rsq) const
+{
+    float scale = DistortionFnScaleRadiusSquared ( rsq );
+    Vector3f scaleRGB;
+    scaleRGB.x = scale * ( 1.0f + ChromaticAberration[0] + rsq * ChromaticAberration[1] );     // Red
+    scaleRGB.y = scale;                                                                        // Green
+    scaleRGB.z = scale * ( 1.0f + ChromaticAberration[2] + rsq * ChromaticAberration[3] );     // Blue
+    return scaleRGB;
+}
+
+// DistortionFnInverse computes the inverse of the distortion function on an argument.
+float LensConfig::DistortionFnInverse(float r) const
+{    
+    OVR_ASSERT((r <= 20.0f));
+
+    float s, d;
+    float delta = r * 0.25f;
+
+    // Better to start guessing too low & take longer to converge than too high
+    // and hit singularities. Empirically, r * 0.5f is too high in some cases.
+    s = r * 0.25f;
+    d = fabs(r - DistortionFn(s));
+
+    for (int i = 0; i < 20; i++)
+    {
+        float sUp   = s + delta;
+        float sDown = s - delta;
+        float dUp   = fabs(r - DistortionFn(sUp));
+        float dDown = fabs(r - DistortionFn(sDown));
+
+        if (dUp < d)
+        {
+            s = sUp;
+            d = dUp;
+        }
+        else if (dDown < d)
+        {
+            s = sDown;
+            d = dDown;
+        }
+        else
+        {
+            delta *= 0.5f;
+        }
+    }
+
+    return s;
+}
+
+
+
+float LensConfig::DistortionFnInverseApprox(float r) const
+{
+    float rsq = r * r;
+    float scale = 1.0f;
+    switch ( Eqn )
+    {
+    case Distortion_Poly4:
+        // Deprecated
+        OVR_ASSERT ( false );
+        break;
+    case Distortion_RecipPoly4:
+        scale = 1.0f / ( InvK[0] + rsq * ( InvK[1] + rsq * ( InvK[2] + rsq * InvK[3] ) ) );
+        break;
+    case Distortion_CatmullRom10:{
+        // A Catmull-Rom spline through the values 1.0, K[1], K[2] ... K[9]
+        // evenly spaced in R^2 from 0.0 to MaxR^2
+        // K[0] controls the slope at radius=0.0, rather than the actual value.
+        const int NumSegments = LensConfig::NumCoefficients;
+        OVR_ASSERT ( NumSegments <= NumCoefficients );
+        float scaledRsq = (float)(NumSegments-1) * rsq / ( MaxInvR * MaxInvR );
+        scale = EvalCatmullRom10Spline ( InvK, scaledRsq );
+
+		//Intercept, and overrule if needed
+		if (CustomDistortionInv)
+		{
+			scale = CustomDistortionInv(rsq);
+		}
+
+        }break;
+    default:
+        OVR_ASSERT ( false );
+        break;
+    }
+    return r * scale;
+}
+
+void LensConfig::SetUpInverseApprox()
+{
+    float maxR = MaxInvR;
+
+    switch ( Eqn )
+    {
+    case Distortion_Poly4:
+        // Deprecated
+        OVR_ASSERT ( false );
+        break;
+    case Distortion_RecipPoly4:{
+
+        float sampleR[4];
+        float sampleRSq[4];
+        float sampleInv[4];
+        float sampleFit[4];
+
+        // Found heuristically...
+        sampleR[0] = 0.0f;
+        sampleR[1] = maxR * 0.4f;
+        sampleR[2] = maxR * 0.8f;
+        sampleR[3] = maxR * 1.5f;
+        for ( int i = 0; i < 4; i++ )
+        {
+            sampleRSq[i] = sampleR[i] * sampleR[i];
+            sampleInv[i] = DistortionFnInverse ( sampleR[i] );
+            sampleFit[i] = sampleR[i] / sampleInv[i];
+        }
+        sampleFit[0] = 1.0f;
+        FitCubicPolynomial ( InvK, sampleRSq, sampleFit );
+
+    #if 0
+        // Should be a nearly exact match on the chosen points.
+        OVR_ASSERT ( fabs ( DistortionFnInverse ( sampleR[0] ) - DistortionFnInverseApprox ( sampleR[0] ) ) / maxR < 0.0001f );
+        OVR_ASSERT ( fabs ( DistortionFnInverse ( sampleR[1] ) - DistortionFnInverseApprox ( sampleR[1] ) ) / maxR < 0.0001f );
+        OVR_ASSERT ( fabs ( DistortionFnInverse ( sampleR[2] ) - DistortionFnInverseApprox ( sampleR[2] ) ) / maxR < 0.0001f );
+        OVR_ASSERT ( fabs ( DistortionFnInverse ( sampleR[3] ) - DistortionFnInverseApprox ( sampleR[3] ) ) / maxR < 0.0001f );
+        // Should be a decent match on the rest of the range.
+        const int maxCheck = 20;
+        for ( int i = 0; i < maxCheck; i++ )
+        {
+            float checkR = (float)i * maxR / (float)maxCheck;
+            float realInv = DistortionFnInverse       ( checkR );
+            float testInv = DistortionFnInverseApprox ( checkR );
+            float error = fabsf ( realInv - testInv ) / maxR;
+            OVR_ASSERT ( error < 0.1f );
+        }
+    #endif
+
+        }break;
+    case Distortion_CatmullRom10:{
+
+        const int NumSegments = LensConfig::NumCoefficients;
+        OVR_ASSERT ( NumSegments <= NumCoefficients );
+        for ( int i = 1; i < NumSegments; i++ )
+        {
+            float scaledRsq = (float)i;
+            float rsq = scaledRsq * MaxInvR * MaxInvR / (float)( NumSegments - 1);
+            float r = sqrtf ( rsq );
+            float inv = DistortionFnInverse ( r );
+            InvK[i] = inv / r;
+            InvK[0] = 1.0f;     // TODO: fix this.
+        }
+
+#if 0
+        const int maxCheck = 20;
+        for ( int i = 0; i <= maxCheck; i++ )
+        {
+            float checkR = (float)i * MaxInvR / (float)maxCheck;
+            float realInv = DistortionFnInverse       ( checkR );
+            float testInv = DistortionFnInverseApprox ( checkR );
+            float error = fabsf ( realInv - testInv ) / MaxR;
+            OVR_ASSERT ( error < 0.01f );
+        }
+#endif
+
+        }break;
+
+    default:
+        break;
+    }
+}
+
+
+void LensConfig::SetToIdentity()
+{
+    for ( int i = 0; i < NumCoefficients; i++ )
+    {
+        K[i] = 0.0f;
+        InvK[i] = 0.0f;
+    }
+    Eqn = Distortion_RecipPoly4;
+    K[0] = 1.0f;
+    InvK[0] = 1.0f;
+    MaxR = 1.0f;
+    MaxInvR = 1.0f;
+    ChromaticAberration[0] = 0.0f;
+    ChromaticAberration[1] = 0.0f;
+    ChromaticAberration[2] = 0.0f;
+    ChromaticAberration[3] = 0.0f;
+    MetersPerTanAngleAtCenter = 0.05f;
+}
+
+
+enum LensConfigStoredVersion
+{
+    LCSV_CatmullRom10Version1 = 1
+};
+
+// DO NOT CHANGE THESE ONCE THEY HAVE BEEN BAKED INTO FIRMWARE.
+// If something needs to change, add a new one!
+struct LensConfigStored_CatmullRom10Version1
+{
+    // All these items must be fixed-length integers - no "float", no "int", etc.
+    UInt16      VersionNumber;      // Must be LCSV_CatmullRom10Version1
+
+    UInt16      K[11];
+    UInt16      MaxR;
+    UInt16      MetersPerTanAngleAtCenter;
+    UInt16      ChromaticAberration[4];
+    // InvK and MaxInvR are calculated on load.
+};
+
+UInt16 EncodeFixedPointUInt16 ( float val, UInt16 zeroVal, int fractionalBits )
+{
+    OVR_ASSERT ( ( fractionalBits >= 0 ) && ( fractionalBits < 31 ) );
+    float valWhole = val * (float)( 1 << fractionalBits );
+    valWhole += (float)zeroVal + 0.5f;
+    valWhole = floorf ( valWhole );
+    OVR_ASSERT ( ( valWhole >= 0.0f ) && ( valWhole < (float)( 1 << 16 ) ) );
+    return (UInt16)valWhole;
+}
+
+float DecodeFixedPointUInt16 ( UInt16 val, UInt16 zeroVal, int fractionalBits )
+{
+    OVR_ASSERT ( ( fractionalBits >= 0 ) && ( fractionalBits < 31 ) );
+    float valFloat = (float)val;
+    valFloat -= (float)zeroVal;
+    valFloat *= 1.0f / (float)( 1 << fractionalBits );
+    return valFloat;
+}
+
+
+// Returns true on success.
+bool LoadLensConfig ( LensConfig *presult, UByte const *pbuffer, int bufferSizeInBytes )
+{
+    if ( bufferSizeInBytes < 2 )
+    {
+        // Can't even tell the version number!
+        return false;
+    }
+    UInt16 version = DecodeUInt16 ( pbuffer + 0 );
+    switch ( version )
+    {
+    case LCSV_CatmullRom10Version1:
+        {
+            if ( bufferSizeInBytes < (int)sizeof(LensConfigStored_CatmullRom10Version1) )
+            {
+                return false;
+            }
+            LensConfigStored_CatmullRom10Version1 lcs;
+            lcs.VersionNumber               = DecodeUInt16 ( pbuffer + 0 );
+            for ( int i = 0; i < 11; i++ )
+            {
+                lcs.K[i]                    = DecodeUInt16 ( pbuffer + 2 + 2*i );
+            }
+            lcs.MaxR                        = DecodeUInt16 ( pbuffer + 24 );
+            lcs.MetersPerTanAngleAtCenter   = DecodeUInt16 ( pbuffer + 26 );
+            for ( int i = 0; i < 4; i++ )
+            {
+                lcs.ChromaticAberration[i]  = DecodeUInt16 ( pbuffer + 28 + 2*i );
+            }
+            OVR_COMPILER_ASSERT ( sizeof(lcs) ==                       36 );
+
+            // Convert to the real thing.
+            LensConfig result;
+            result.Eqn = Distortion_CatmullRom10;
+            for ( int i = 0; i < 11; i++ )
+            {
+                // K[] are mostly 1.something. They may get significantly bigger, but they never hit 0.0.
+                result.K[i] = DecodeFixedPointUInt16 ( lcs.K[i], 0, 14 );
+            }
+            // MaxR is tan(angle), so always >0, typically just over 1.0 (45 degrees half-fov),
+            // but may get arbitrarily high. tan(76)=4 is a very reasonable limit!
+            result.MaxR = DecodeFixedPointUInt16 ( lcs.MaxR, 0, 14 );
+            // MetersPerTanAngleAtCenter is also known as focal length!
+            // Typically around 0.04 for our current screens, minimum of 0, sensible maximum of 0.125 (i.e. 3 "extra" bits of fraction)
+            result.MetersPerTanAngleAtCenter = DecodeFixedPointUInt16 ( lcs.MetersPerTanAngleAtCenter, 0, 16+3 );
+            for ( int i = 0; i < 4; i++ )
+            {
+                // ChromaticAberration[] are mostly 0.0something, centered on 0.0. Largest seen is 0.04, so set max to 0.125 (i.e. 3 "extra" bits of fraction)
+                result.ChromaticAberration[i] = DecodeFixedPointUInt16 ( lcs.ChromaticAberration[i], 0x8000, 16+3 );
+            }
+            result.MaxInvR = result.DistortionFn ( result.MaxR );
+            result.SetUpInverseApprox();
+
+            OVR_ASSERT ( version == lcs.VersionNumber );
+
+            *presult = result;
+        }
+        break;
+    default:
+        // Unknown format.
+        return false;
+        break;
+    }
+    return true;
+}
+
+// Returns number of bytes needed.
+int SaveLensConfigSizeInBytes ( LensConfig const &config )
+{
+    OVR_UNUSED ( config );
+    return sizeof ( LensConfigStored_CatmullRom10Version1 );
+}
+
+// Returns true on success.
+bool SaveLensConfig ( UByte *pbuffer, int bufferSizeInBytes, LensConfig const &config )
+{
+    if ( bufferSizeInBytes < (int)sizeof ( LensConfigStored_CatmullRom10Version1 ) )
+    {
+        return false;
+    }
+
+    // Construct the values.
+    LensConfigStored_CatmullRom10Version1 lcs;
+    lcs.VersionNumber = LCSV_CatmullRom10Version1;
+    for ( int i = 0; i < 11; i++ )
+    {
+        // K[] are mostly 1.something. They may get significantly bigger, but they never hit 0.0.
+        lcs.K[i] = EncodeFixedPointUInt16 ( config.K[i], 0, 14 );
+    }
+    // MaxR is tan(angle), so always >0, typically just over 1.0 (45 degrees half-fov),
+    // but may get arbitrarily high. tan(76)=4 is a very reasonable limit!
+    lcs.MaxR = EncodeFixedPointUInt16 ( config.MaxR, 0, 14 );
+    // MetersPerTanAngleAtCenter is also known as focal length!
+    // Typically around 0.04 for our current screens, minimum of 0, sensible maximum of 0.125 (i.e. 3 "extra" bits of fraction)
+    lcs.MetersPerTanAngleAtCenter = EncodeFixedPointUInt16 ( config.MetersPerTanAngleAtCenter, 0, 16+3 );
+    for ( int i = 0; i < 4; i++ )
+    {
+        // ChromaticAberration[] are mostly 0.0something, centered on 0.0. Largest seen is 0.04, so set max to 0.125 (i.e. 3 "extra" bits of fraction)
+        lcs.ChromaticAberration[i] = EncodeFixedPointUInt16 ( config.ChromaticAberration[i], 0x8000, 16+3 );
+    }
+
+
+    // Now store them out, sensitive to endinness.
+    EncodeUInt16 (      pbuffer + 0,        lcs.VersionNumber );
+    for ( int i = 0; i < 11; i++ )
+    {
+        EncodeUInt16 (  pbuffer + 2 + 2*i,  lcs.K[i] );
+    }
+    EncodeUInt16 (      pbuffer + 24,       lcs.MaxR );
+    EncodeUInt16 (      pbuffer + 26,       lcs.MetersPerTanAngleAtCenter );
+    for ( int i = 0; i < 4; i++ )
+    {
+        EncodeUInt16 (  pbuffer + 28 + 2*i, lcs.ChromaticAberration[i] );
+    }
+    OVR_COMPILER_ASSERT (         36        == sizeof(lcs) );
+
+    return true;
+}
+
+#ifdef OVR_BUILD_DEBUG
+void TestSaveLoadLensConfig ( LensConfig const &config )
+{
+    OVR_ASSERT ( config.Eqn == Distortion_CatmullRom10 );
+    // As a test, make sure this can be encoded and decoded correctly.
+    const int bufferSize = 256;
+    UByte buffer[bufferSize];
+    OVR_ASSERT ( SaveLensConfigSizeInBytes ( config ) < bufferSize );
+    bool success;
+    success = SaveLensConfig ( buffer, bufferSize, config );
+    OVR_ASSERT ( success );
+    LensConfig testConfig;
+    success = LoadLensConfig ( &testConfig, buffer, bufferSize );
+    OVR_ASSERT ( success );
+    OVR_ASSERT ( testConfig.Eqn == config.Eqn );
+    for ( int i = 0; i < 11; i++ )
+    {
+        OVR_ASSERT ( fabs ( testConfig.K[i] - config.K[i] ) < 0.0001f );
+    }
+    OVR_ASSERT ( fabsf ( testConfig.MaxR - config.MaxR ) < 0.0001f );
+    OVR_ASSERT ( fabsf ( testConfig.MetersPerTanAngleAtCenter - config.MetersPerTanAngleAtCenter ) < 0.00001f );
+    for ( int i = 0; i < 4; i++ )
+    {
+        OVR_ASSERT ( fabsf ( testConfig.ChromaticAberration[i] - config.ChromaticAberration[i] ) < 0.00001f );
+    }
+}
+#endif
+
+
+
+//-----------------------------------------------------------------------------------
+
+// TBD: There is a question of whether this is the best file for CreateDebugHMDInfo. As long as there are many
+// constants for HmdRenderInfo here as well it is ok. The alternative would be OVR_Common_HMDDevice.cpp, but
+// that's specialized per platform... should probably move it there onces the code is in the common base class.
+
+HMDInfo CreateDebugHMDInfo(HmdTypeEnum hmdType)
+{
+    HMDInfo info;    
+
+    if ((hmdType != HmdType_DK1) &&
+        (hmdType != HmdType_CrystalCoveProto))
+    {
+        LogText("Debug HMDInfo - HmdType not supported. Defaulting to DK1.\n");
+        hmdType = HmdType_DK1;
+    }
+
+    // The alternative would be to initialize info.HmdType to HmdType_None instead. If we did that,
+    // code wouldn't be "maximally compatible" and devs wouldn't know what device we are
+    // simulating... so if differentiation becomes necessary we better add Debug flag in the future.
+    info.HmdType      = hmdType;
+    info.Manufacturer = "Oculus VR";    
+
+    switch(hmdType)
+    {
+    case HmdType_DK1:
+        info.ProductName                            = "Oculus Rift DK1";
+        info.ResolutionInPixels                     = Sizei ( 1280, 800 );
+        info.ScreenSizeInMeters                     = Sizef ( 0.1498f, 0.0936f );
+        info.ScreenGapSizeInMeters                  = 0.0f;
+        info.CenterFromTopInMeters                  = 0.0468f;
+        info.LensSeparationInMeters                 = 0.0635f;
+        info.Shutter.Type                           = HmdShutter_RollingTopToBottom;
+        info.Shutter.VsyncToNextVsync               = ( 1.0f / 60.0f );
+        info.Shutter.VsyncToFirstScanline           = 0.000052f;
+        info.Shutter.FirstScanlineToLastScanline    = 0.016580f;
+        info.Shutter.PixelSettleTime                = 0.015f;
+        info.Shutter.PixelPersistence               = ( 1.0f / 60.0f );
+        break;
+
+    case HmdType_CrystalCoveProto:
+        info.ProductName                            = "Oculus Rift Crystal Cove";        
+        info.ResolutionInPixels                     = Sizei ( 1920, 1080 );
+        info.ScreenSizeInMeters                     = Sizef ( 0.12576f, 0.07074f );
+        info.ScreenGapSizeInMeters                  = 0.0f;
+        info.CenterFromTopInMeters                  = info.ScreenSizeInMeters.h * 0.5f;
+        info.LensSeparationInMeters                 = 0.0635f;
+        info.Shutter.Type                           = HmdShutter_RollingRightToLeft;
+        info.Shutter.VsyncToNextVsync               = ( 1.0f / 76.0f );
+        info.Shutter.VsyncToFirstScanline           = 0.0000273f;
+        info.Shutter.FirstScanlineToLastScanline    = 0.0131033f;
+        info.Shutter.PixelSettleTime                = 0.0f;
+        info.Shutter.PixelPersistence               = 0.18f * info.Shutter.VsyncToNextVsync;
+        break;
+
+    case HmdType_DK2:
+        info.ProductName                            = "Oculus Rift DK2";        
+        info.ResolutionInPixels                     = Sizei ( 1920, 1080 );
+        info.ScreenSizeInMeters                     = Sizef ( 0.12576f, 0.07074f );
+        info.ScreenGapSizeInMeters                  = 0.0f;
+        info.CenterFromTopInMeters                  = info.ScreenSizeInMeters.h * 0.5f;
+        info.LensSeparationInMeters                 = 0.0635f;
+        info.Shutter.Type                           = HmdShutter_RollingRightToLeft;
+        info.Shutter.VsyncToNextVsync               = ( 1.0f / 76.0f );
+        info.Shutter.VsyncToFirstScanline           = 0.0000273f;
+        info.Shutter.FirstScanlineToLastScanline    = 0.0131033f;
+        info.Shutter.PixelSettleTime                = 0.0f;
+        info.Shutter.PixelPersistence               = 0.18f * info.Shutter.VsyncToNextVsync;
+        break;
+
+    default:
+        break;
+    }
+
+    return info;
+}
+
+
+
+// profile may be NULL, in which case it uses the hard-coded defaults.
+HmdRenderInfo GenerateHmdRenderInfoFromHmdInfo ( HMDInfo const &hmdInfo, 
+                                                 Profile const *profile /*=NULL*/,
+                                                 DistortionEqnType distortionType /*= Distortion_CatmullRom10*/,
+                                                 EyeCupType eyeCupOverride /*= EyeCup_LAST*/ )
+{
+    HmdRenderInfo renderInfo;
+
+    renderInfo.HmdType                              = hmdInfo.HmdType;
+    renderInfo.ResolutionInPixels                   = hmdInfo.ResolutionInPixels;
+    renderInfo.ScreenSizeInMeters                   = hmdInfo.ScreenSizeInMeters;
+    renderInfo.CenterFromTopInMeters                = hmdInfo.CenterFromTopInMeters;
+    renderInfo.ScreenGapSizeInMeters                = hmdInfo.ScreenGapSizeInMeters;
+    renderInfo.LensSeparationInMeters               = hmdInfo.LensSeparationInMeters;
+
+    OVR_ASSERT ( sizeof(renderInfo.Shutter) == sizeof(hmdInfo.Shutter) );   // Try to keep the files in sync!
+    renderInfo.Shutter.Type                         = hmdInfo.Shutter.Type;
+    renderInfo.Shutter.VsyncToNextVsync             = hmdInfo.Shutter.VsyncToNextVsync;
+    renderInfo.Shutter.VsyncToFirstScanline         = hmdInfo.Shutter.VsyncToFirstScanline;
+    renderInfo.Shutter.FirstScanlineToLastScanline  = hmdInfo.Shutter.FirstScanlineToLastScanline;
+    renderInfo.Shutter.PixelSettleTime              = hmdInfo.Shutter.PixelSettleTime;
+    renderInfo.Shutter.PixelPersistence             = hmdInfo.Shutter.PixelPersistence;
+
+    renderInfo.LensDiameterInMeters                 = 0.035f;
+    renderInfo.LensSurfaceToMidplateInMeters        = 0.025f;
+    renderInfo.EyeCups                              = EyeCup_DK1A;
+
+#if 0       // Device settings are out of date - don't use them.
+    if (Contents & Contents_Distortion)
+    {
+        memcpy(renderInfo.DistortionK, DistortionK, sizeof(float)*4);
+        renderInfo.DistortionEqn = Distortion_RecipPoly4;
+    }
+#endif
+
+    // Defaults in case of no user profile.
+    renderInfo.EyeLeft.NoseToPupilInMeters   = 0.032f;
+    renderInfo.EyeLeft.ReliefInMeters        = 0.012f;
+
+    // 10mm eye-relief laser numbers for DK1 lenses.
+    // These are a decent seed for finding eye-relief and IPD.
+    // These are NOT used for rendering!
+    // Rendering distortions are now in GenerateLensConfigFromEyeRelief()
+    // So, if you're hacking in new distortions, don't do it here!
+    renderInfo.EyeLeft.Distortion.SetToIdentity();
+    renderInfo.EyeLeft.Distortion.MetersPerTanAngleAtCenter = 0.0449f;
+    renderInfo.EyeLeft.Distortion.Eqn       = Distortion_RecipPoly4;
+    renderInfo.EyeLeft.Distortion.K[0]      =  1.0f;
+    renderInfo.EyeLeft.Distortion.K[1]      = -0.494165344f;
+    renderInfo.EyeLeft.Distortion.K[2]      = 0.587046423f;
+    renderInfo.EyeLeft.Distortion.K[3]      = -0.841887126f;
+    renderInfo.EyeLeft.Distortion.MaxR      = 1.0f;
+
+    renderInfo.EyeLeft.Distortion.ChromaticAberration[0] = -0.006f;
+    renderInfo.EyeLeft.Distortion.ChromaticAberration[1] =  0.0f;
+    renderInfo.EyeLeft.Distortion.ChromaticAberration[2] =  0.014f;
+    renderInfo.EyeLeft.Distortion.ChromaticAberration[3] =  0.0f;
+
+    renderInfo.EyeRight = renderInfo.EyeLeft;
+
+
+    // Obtain data from profile.
+    if ( profile != NULL )
+    {
+        char eyecup[16];
+        if (profile->GetValue(OVR_KEY_EYE_CUP, eyecup, 16))
+            SetEyeCup(&renderInfo, eyecup);
+    }
+
+    switch ( hmdInfo.HmdType )
+    {
+    case HmdType_None:
+    case HmdType_DKProto:
+    case HmdType_DK1:
+        // Slight hack to improve usability.
+        // If you have a DKHD-style lens profile enabled,
+        // but you plug in DK1 and forget to change the profile,
+        // obviously you don't want those lens numbers.
+        if ( ( renderInfo.EyeCups != EyeCup_DK1A ) &&
+             ( renderInfo.EyeCups != EyeCup_DK1B ) &&
+             ( renderInfo.EyeCups != EyeCup_DK1C ) )
+        {
+            renderInfo.EyeCups = EyeCup_DK1A;
+        }
+        break;
+
+    case HmdType_DKHD2Proto:
+        renderInfo.EyeCups = EyeCup_DKHD2A;
+        break;
+    case HmdType_CrystalCoveProto:
+        renderInfo.EyeCups = EyeCup_PinkA;
+        break;
+    case HmdType_DK2:
+        renderInfo.EyeCups = EyeCup_DK2A;
+        break;
+    default:
+        break;
+    }
+
+    if ( eyeCupOverride != EyeCup_LAST )
+    {
+        renderInfo.EyeCups = eyeCupOverride;
+    }
+
+    switch ( renderInfo.EyeCups )
+    {
+    case EyeCup_DK1A:
+    case EyeCup_DK1B:
+    case EyeCup_DK1C:
+        renderInfo.LensDiameterInMeters                   = 0.035f;
+        renderInfo.LensSurfaceToMidplateInMeters          = 0.02357f;
+        // Not strictly lens-specific, but still wise to set a reasonable default for relief.
+        renderInfo.EyeLeft.ReliefInMeters                 = 0.010f; 
+        renderInfo.EyeRight.ReliefInMeters                = 0.010f; 
+        break;
+    case EyeCup_DKHD2A:
+        renderInfo.LensDiameterInMeters                   = 0.035f;
+        renderInfo.LensSurfaceToMidplateInMeters          = 0.02357f;
+        // Not strictly lens-specific, but still wise to set a reasonable default for relief.
+        renderInfo.EyeLeft.ReliefInMeters                 = 0.010f; 
+        renderInfo.EyeRight.ReliefInMeters                = 0.010f; 
+        break;
+    case EyeCup_PinkA:
+    case EyeCup_DK2A:
+        renderInfo.LensDiameterInMeters                   = 0.04f;      // approximate
+        renderInfo.LensSurfaceToMidplateInMeters          = 0.01965f;
+        // Not strictly lens-specific, but still wise to set a reasonable default for relief.
+        renderInfo.EyeLeft.ReliefInMeters                 = 0.012f;
+        renderInfo.EyeRight.ReliefInMeters                = 0.012f;
+        break;
+    default: OVR_ASSERT ( false ); break;
+    }
+
+    if ( profile != NULL )
+    {
+        // Set the customized user eye position
+        // TBD: Maybe we should separate custom camera positioning from custom distortion rendering ??
+        if (profile->GetBoolValue(OVR_KEY_CUSTOM_EYE_RENDER, true))
+        {
+            float eye2nose[2];
+            if (profile->GetFloatValues(OVR_KEY_EYE_TO_NOSE_DISTANCE, eye2nose, 2) == 2)
+            {   // Load per-eye half-IPD
+                renderInfo.EyeLeft.NoseToPupilInMeters = eye2nose[0];
+                renderInfo.EyeRight.NoseToPupilInMeters = eye2nose[1];
+            }
+            else
+            {   // Use a centered IPD instead
+                float ipd = profile->GetFloatValue(OVR_KEY_IPD, OVR_DEFAULT_IPD);
+                renderInfo.EyeLeft.NoseToPupilInMeters = 0.5f * ipd;
+                renderInfo.EyeRight.NoseToPupilInMeters = 0.5f * ipd;
+            }
+        
+            float eye2plate[2];
+            if (profile->GetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, eye2plate, 2) == 2)
+            {   // Subtract the eye-cup height from the plate distance to get the eye-to-lens distance
+                // This measurement should be the the distance at maximum dial setting
+                // We still need to adjust with the dial offset
+                renderInfo.EyeLeft.ReliefInMeters = eye2plate[0] - renderInfo.LensSurfaceToMidplateInMeters;
+                renderInfo.EyeRight.ReliefInMeters = eye2plate[1] - renderInfo.LensSurfaceToMidplateInMeters;
+
+                // Adjust the eye relief with the dial setting (from the assumed max eye relief)
+                int dial = profile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, -1);
+                if (dial >= 0)
+                {
+                    renderInfo.EyeLeft.ReliefInMeters -= ((10 - dial) * 0.001f);
+                    renderInfo.EyeRight.ReliefInMeters -= ((10 - dial) * 0.001f);
+                }
+            }
+            else
+            {
+                // Set the eye relief with the user configured dial setting
+                int dial = profile->GetIntValue(OVR_KEY_EYE_RELIEF_DIAL, -1);
+                if (dial >= 0)
+                {   // Assume a default of 7 to 17 mm eye relief based on the dial.  This corresponds
+                    // to the sampled and tuned distortion range on the DK1.
+                    renderInfo.EyeLeft.ReliefInMeters = 0.007f + (dial * 0.001f);
+                    renderInfo.EyeRight.ReliefInMeters = 0.007f + (dial * 0.001f);
+                }
+            }
+        }
+    }
+
+    // Now we know where the eyes are relative to the lenses, we can compute a distortion for each.
+    // TODO: incorporate lateral offset in distortion generation.
+    // TODO: we used a distortion to calculate eye-relief, and now we're making a distortion from that eye-relief. Close the loop!
+
+    for ( int eyeNum = 0; eyeNum < 2; eyeNum++ )
+    {
+        HmdRenderInfo::EyeConfig *pHmdEyeConfig = ( eyeNum == 0 ) ? &(renderInfo.EyeLeft) : &(renderInfo.EyeRight);
+
+        float eye_relief = pHmdEyeConfig->ReliefInMeters;
+        LensConfig distortionConfig = GenerateLensConfigFromEyeRelief ( eye_relief, renderInfo, distortionType );
+        pHmdEyeConfig->Distortion = distortionConfig;
+    }
+
+    return renderInfo;
+}
+
+
+LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderInfo const &hmd, DistortionEqnType distortionType /*= Distortion_CatmullRom10*/ )
+{
+    struct DistortionDescriptor
+    {
+        float EyeRelief;
+        // The three places we're going to sample & lerp the curve at.
+        // One sample is always at 0.0, and the distortion scale should be 1.0 or else!
+        // Only use for poly4 numbers - CR has an implicit scale.
+        float SampleRadius[3];
+        // Where the distortion has actually been measured/calibrated out to.
+        // Don't try to hallucinate data out beyond here.
+        float MaxRadius;
+        // The config itself.
+        LensConfig Config;
+    };
+
+    DistortionDescriptor distortions[10];
+    for ( unsigned int i = 0; i < sizeof(distortions)/sizeof(distortions[0]); i++ )
+    {
+        distortions[i].Config.SetToIdentity();
+        distortions[i].EyeRelief = 0.0f;
+        distortions[i].MaxRadius = 1.0f;
+    }
+    int numDistortions = 0;
+    int defaultDistortion = 0;     // index of the default distortion curve to use if zero eye relief supplied
+
+    if ( ( hmd.EyeCups == EyeCup_DK1A ) ||
+         ( hmd.EyeCups == EyeCup_DK1B ) ||
+         ( hmd.EyeCups == EyeCup_DK1C ) )
+    {
+
+        numDistortions = 0;
+       
+        // Tuned at minimum dial setting - extended to r^2 == 1.8
+        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
+        distortions[numDistortions].EyeRelief                            = 0.012760465f - 0.005f;
+        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.0425f;
+        distortions[numDistortions].Config.K[0]                          = 1.0000f;
+        distortions[numDistortions].Config.K[1]                          = 1.06505f;
+        distortions[numDistortions].Config.K[2]                          = 1.14725f;
+        distortions[numDistortions].Config.K[3]                          = 1.2705f;
+        distortions[numDistortions].Config.K[4]                          = 1.48f;
+        distortions[numDistortions].Config.K[5]                          = 1.87f;
+        distortions[numDistortions].Config.K[6]                          = 2.534f;
+        distortions[numDistortions].Config.K[7]                          = 3.6f;
+        distortions[numDistortions].Config.K[8]                          = 5.1f;
+        distortions[numDistortions].Config.K[9]                          = 7.4f;
+        distortions[numDistortions].Config.K[10]                         = 11.0f;
+        distortions[numDistortions].SampleRadius[0]                      = 0.222717149f;
+        distortions[numDistortions].SampleRadius[1]                      = 0.512249443f;
+        distortions[numDistortions].SampleRadius[2]                      = 0.712694878f;
+        distortions[numDistortions].MaxRadius                            = sqrt(1.8f);
+        defaultDistortion = numDistortions;                      // this is the default
+        numDistortions++;
+        
+        // Tuned at middle dial setting
+        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
+        distortions[numDistortions].EyeRelief                            = 0.012760465f;  // my average eye-relief
+        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.0425f;
+        distortions[numDistortions].Config.K[0]                          = 1.0f;
+        distortions[numDistortions].Config.K[1]                          = 1.032407264f;
+        distortions[numDistortions].Config.K[2]                          = 1.07160462f;
+        distortions[numDistortions].Config.K[3]                          = 1.11998388f;
+        distortions[numDistortions].Config.K[4]                          = 1.1808606f;
+        distortions[numDistortions].Config.K[5]                          = 1.2590494f;
+        distortions[numDistortions].Config.K[6]                          = 1.361915f;
+        distortions[numDistortions].Config.K[7]                          = 1.5014339f;
+        distortions[numDistortions].Config.K[8]                          = 1.6986004f;
+        distortions[numDistortions].Config.K[9]                          = 1.9940577f;
+        distortions[numDistortions].Config.K[10]                         = 2.4783147f;
+        distortions[numDistortions].SampleRadius[0]                      = 0.222717149f;
+        distortions[numDistortions].SampleRadius[1]                      = 0.512249443f;
+        distortions[numDistortions].SampleRadius[2]                      = 0.712694878f;
+        distortions[numDistortions].MaxRadius                            = 1.0f;
+        numDistortions++;
+
+        // Tuned at maximum dial setting
+        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
+        distortions[numDistortions].EyeRelief                            = 0.012760465f + 0.005f;
+        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.0425f;
+        distortions[numDistortions].Config.K[0]                          = 1.0102f;
+        distortions[numDistortions].Config.K[1]                          = 1.0371f;
+        distortions[numDistortions].Config.K[2]                          = 1.0831f;
+        distortions[numDistortions].Config.K[3]                          = 1.1353f;
+        distortions[numDistortions].Config.K[4]                          = 1.2f;
+        distortions[numDistortions].Config.K[5]                          = 1.2851f;
+        distortions[numDistortions].Config.K[6]                          = 1.3979f;
+        distortions[numDistortions].Config.K[7]                          = 1.56f;
+        distortions[numDistortions].Config.K[8]                          = 1.8f;
+        distortions[numDistortions].Config.K[9]                          = 2.25f;
+        distortions[numDistortions].Config.K[10]                         = 3.0f;
+        distortions[numDistortions].SampleRadius[0]                      = 0.222717149f;
+        distortions[numDistortions].SampleRadius[1]                      = 0.512249443f;
+        distortions[numDistortions].SampleRadius[2]                      = 0.712694878f;
+        distortions[numDistortions].MaxRadius                            = 1.0f;
+        numDistortions++;
+        
+        // Chromatic aberration doesn't seem to change with eye relief.
+        for ( int i = 0; i < numDistortions; i++ )
+        {
+            distortions[i].Config.ChromaticAberration[0]        = -0.006f;
+            distortions[i].Config.ChromaticAberration[1]        =  0.0f;
+            distortions[i].Config.ChromaticAberration[2]        =  0.014f;
+            distortions[i].Config.ChromaticAberration[3]        =  0.0f;
+        }
+    }
+    else if ( hmd.EyeCups == EyeCup_DKHD2A )
+    {
+        // Tuned DKHD2 lens
+        numDistortions = 0;
+       
+        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
+        distortions[numDistortions].EyeRelief                            = 0.010f;
+        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.0425f;
+        distortions[numDistortions].Config.K[0]                          = 1.0f;
+        distortions[numDistortions].Config.K[1]                          = 1.0425f;
+        distortions[numDistortions].Config.K[2]                          = 1.0826f;
+        distortions[numDistortions].Config.K[3]                          = 1.130f;
+        distortions[numDistortions].Config.K[4]                          = 1.185f;
+        distortions[numDistortions].Config.K[5]                          = 1.250f;
+        distortions[numDistortions].Config.K[6]                          = 1.338f;
+        distortions[numDistortions].Config.K[7]                          = 1.455f;
+        distortions[numDistortions].Config.K[8]                          = 1.620f;
+        distortions[numDistortions].Config.K[9]                          = 1.840f;
+        distortions[numDistortions].Config.K[10]                         = 2.200f;
+        distortions[numDistortions].SampleRadius[0]                      = 0.222717149f;
+        distortions[numDistortions].SampleRadius[1]                      = 0.512249443f;
+        distortions[numDistortions].SampleRadius[2]                      = 0.712694878f;
+        distortions[numDistortions].MaxRadius                            = 1.0f;
+        
+        distortions[numDistortions].SampleRadius[0]                      = 0.405405405f;
+        distortions[numDistortions].SampleRadius[1]                      = 0.675675676f;
+        distortions[numDistortions].SampleRadius[2]                      = 0.945945946f;
+        defaultDistortion = numDistortions;   // this is the default
+        numDistortions++;
+
+        distortions[numDistortions] = distortions[0];
+        distortions[numDistortions].EyeRelief = 0.020f;
+        numDistortions++;
+
+        // Chromatic aberration doesn't seem to change with eye relief.
+        for ( int i = 0; i < numDistortions; i++ )
+        {
+            distortions[i].Config.ChromaticAberration[0]        = -0.006f;
+            distortions[i].Config.ChromaticAberration[1]        =  0.0f;
+            distortions[i].Config.ChromaticAberration[2]        =  0.014f;
+            distortions[i].Config.ChromaticAberration[3]        =  0.0f;
+        }
+    }
+    else if ( hmd.EyeCups == EyeCup_PinkA || hmd.EyeCups == EyeCup_DK2A )
+    {
+        // Tuned Crystal Cove & DK2 Lens (CES & GDC)
+        numDistortions = 0;
+       
+        distortions[numDistortions].EyeRelief                            = 0.010f;
+        distortions[numDistortions].Config.MetersPerTanAngleAtCenter     = 0.036f;
+
+        distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10;
+        distortions[numDistortions].Config.K[0]                          = 1.003f;
+        distortions[numDistortions].Config.K[1]                          = 1.02f;
+        distortions[numDistortions].Config.K[2]                          = 1.042f;
+        distortions[numDistortions].Config.K[3]                          = 1.066f;
+        distortions[numDistortions].Config.K[4]                          = 1.094f;  //1.0945f;
+        distortions[numDistortions].Config.K[5]                          = 1.126f;  //1.127f;
+        distortions[numDistortions].Config.K[6]                          = 1.162f;  //1.167f;
+        distortions[numDistortions].Config.K[7]                          = 1.203f;  //1.218f;
+        distortions[numDistortions].Config.K[8]                          = 1.25f;   //1.283f;
+        distortions[numDistortions].Config.K[9]                          = 1.31f;   //1.37f;
+        distortions[numDistortions].Config.K[10]                         = 1.38f;   //1.48f;
+        distortions[numDistortions].MaxRadius                            = 1.0f;
+        
+        
+        distortions[numDistortions].SampleRadius[0]                      = 0.405405405f;
+        distortions[numDistortions].SampleRadius[1]                      = 0.675675676f;
+        distortions[numDistortions].SampleRadius[2]                      = 0.945945946f;
+        defaultDistortion = numDistortions;   // this is the default
+        numDistortions++;
+
+        distortions[numDistortions] = distortions[0];
+        distortions[numDistortions].EyeRelief = 0.020f;
+        numDistortions++;
+
+        // Chromatic aberration doesn't seem to change with eye relief.
+        for ( int i = 0; i < numDistortions; i++ )
+        {
+            distortions[i].Config.ChromaticAberration[0]        = -0.015f;
+            distortions[i].Config.ChromaticAberration[1]        = -0.02f;
+            distortions[i].Config.ChromaticAberration[2]        =  0.025f;
+            distortions[i].Config.ChromaticAberration[3]        =  0.02f;
+        }
+    }
+    else
+    {
+        // Unknown lens.
+        // Use DK1 black lens settings, just so we can continue to run with something.
+        distortions[0].EyeRelief = 0.005f;
+        distortions[0].Config.MetersPerTanAngleAtCenter = 0.043875f;
+        distortions[0].Config.Eqn = Distortion_RecipPoly4;
+        distortions[0].Config.K[0] = 1.0f;
+        distortions[0].Config.K[1] = -0.3999f;
+        distortions[0].Config.K[2] =  0.2408f;
+        distortions[0].Config.K[3] = -0.4589f;
+        distortions[0].SampleRadius[0] = 0.2f;
+        distortions[0].SampleRadius[1] = 0.4f;
+        distortions[0].SampleRadius[2] = 0.6f;
+
+        distortions[1] = distortions[0];
+        distortions[1].EyeRelief = 0.010f;
+        numDistortions = 2;
+
+        // Chromatic aberration doesn't seem to change with eye relief.
+        for ( int i = 0; i < numDistortions; i++ )
+        {
+            // These are placeholder, they have not been tuned!
+            distortions[i].Config.ChromaticAberration[0]        =  0.0f;
+            distortions[i].Config.ChromaticAberration[1]        =  0.0f;
+            distortions[i].Config.ChromaticAberration[2]        =  0.0f;
+            distortions[i].Config.ChromaticAberration[3]        =  0.0f;
+        }
+    }
+
+    OVR_ASSERT ( numDistortions < (sizeof(distortions)/sizeof(distortions[0])) );
+
+
+    DistortionDescriptor *pUpper = NULL;
+    DistortionDescriptor *pLower = NULL;
+    float lerpVal = 0.0f;
+    if (eyeReliefInMeters == 0)
+    {   // Use a constant default distortion if an invalid eye-relief is supplied
+        pLower = &(distortions[defaultDistortion]);
+        pUpper = &(distortions[defaultDistortion]);
+        lerpVal = 0.0f;
+    }
+    else
+    {
+        for ( int i = 0; i < numDistortions-1; i++ )
+        {
+            OVR_ASSERT ( distortions[i].EyeRelief < distortions[i+1].EyeRelief );
+            if ( ( distortions[i].EyeRelief <= eyeReliefInMeters ) && ( distortions[i+1].EyeRelief > eyeReliefInMeters ) )
+            {
+                pLower = &(distortions[i]);
+                pUpper = &(distortions[i+1]);
+                lerpVal = ( eyeReliefInMeters - pLower->EyeRelief ) / ( pUpper->EyeRelief - pLower->EyeRelief );
+                // No break here - I want the ASSERT to check everything every time!
+            }
+        }
+    }
+
+    if ( pUpper == NULL )
+    {
+#if 0
+        // Outside the range, so extrapolate rather than interpolate.
+        if ( distortions[0].EyeRelief > eyeReliefInMeters )
+        { 
+            pLower = &(distortions[0]);
+            pUpper = &(distortions[1]);
+        }
+        else
+        {
+            OVR_ASSERT ( distortions[numDistortions-1].EyeRelief <= eyeReliefInMeters );
+            pLower = &(distortions[numDistortions-2]);
+            pUpper = &(distortions[numDistortions-1]);
+        }
+        lerpVal = ( eyeReliefInMeters - pLower->EyeRelief ) / ( pUpper->EyeRelief - pLower->EyeRelief );
+#else
+        // Do not extrapolate, just clamp - slightly worried about people putting in bogus settings.
+        if ( distortions[0].EyeRelief > eyeReliefInMeters )
+        {
+            pLower = &(distortions[0]);
+            pUpper = &(distortions[0]);
+        }
+        else
+        {
+            OVR_ASSERT ( distortions[numDistortions-1].EyeRelief <= eyeReliefInMeters );
+            pLower = &(distortions[numDistortions-1]);
+            pUpper = &(distortions[numDistortions-1]);
+        }
+        lerpVal = 0.0f;
+#endif
+    }
+    float invLerpVal = 1.0f - lerpVal;
+
+    pLower->Config.MaxR = pLower->MaxRadius;
+    pUpper->Config.MaxR = pUpper->MaxRadius;
+
+    LensConfig result;
+    // Where is the edge of the lens - no point modelling further than this.
+    float maxValidRadius = invLerpVal * pLower->MaxRadius + lerpVal * pUpper->MaxRadius;
+    result.MaxR = maxValidRadius;
+
+    switch ( distortionType )
+    {
+    case Distortion_Poly4:
+        // Deprecated
+        OVR_ASSERT ( false );
+        break;
+    case Distortion_RecipPoly4:{
+        // Lerp control points and fit an equation to them.
+        float fitX[4];
+        float fitY[4];
+        fitX[0] = 0.0f;
+        fitY[0] = 1.0f;
+        for ( int ctrlPt = 1; ctrlPt < 4; ctrlPt ++ )
+        {
+            float radiusLerp = invLerpVal * pLower->SampleRadius[ctrlPt-1] + lerpVal * pUpper->SampleRadius[ctrlPt-1];
+            float radiusLerpSq = radiusLerp * radiusLerp;
+            float fitYLower = pLower->Config.DistortionFnScaleRadiusSquared ( radiusLerpSq );
+            float fitYUpper = pUpper->Config.DistortionFnScaleRadiusSquared ( radiusLerpSq );
+            fitX[ctrlPt] = radiusLerpSq;
+            fitY[ctrlPt] = 1.0f / ( invLerpVal * fitYLower + lerpVal * fitYUpper );
+        }
+
+        result.Eqn = Distortion_RecipPoly4;
+        bool bSuccess = FitCubicPolynomial ( result.K, fitX, fitY );
+        OVR_ASSERT ( bSuccess );
+        OVR_UNUSED ( bSuccess );
+
+        // Set up the fast inverse.
+        float maxRDist = result.DistortionFn ( maxValidRadius );
+        result.MaxInvR = maxRDist;
+        result.SetUpInverseApprox();
+
+        }break;
+
+    case Distortion_CatmullRom10:{
+
+        // Evenly sample & lerp points on the curve.
+        const int NumSegments = LensConfig::NumCoefficients;
+        result.MaxR = maxValidRadius;
+        // Directly interpolate the K0 values
+        result.K[0] = invLerpVal * pLower->Config.K[0] + lerpVal * pUpper->Config.K[0];
+
+        // Sample and interpolate the distortion curves to derive K[1] ... K[n]
+        for ( int ctrlPt = 1; ctrlPt < NumSegments; ctrlPt++ )
+        {
+            float radiusSq = ( (float)ctrlPt / (float)(NumSegments-1) ) * maxValidRadius * maxValidRadius;
+            float fitYLower = pLower->Config.DistortionFnScaleRadiusSquared ( radiusSq );
+            float fitYUpper = pUpper->Config.DistortionFnScaleRadiusSquared ( radiusSq );
+            float fitLerp = invLerpVal * fitYLower + lerpVal * fitYUpper;
+            result.K[ctrlPt] = fitLerp;
+        }
+
+        result.Eqn = Distortion_CatmullRom10;
+
+        for ( int ctrlPt = 1; ctrlPt < NumSegments; ctrlPt++ )
+        {
+            float radiusSq = ( (float)ctrlPt / (float)(NumSegments-1) ) * maxValidRadius * maxValidRadius;
+            float val = result.DistortionFnScaleRadiusSquared ( radiusSq );            
+            OVR_ASSERT ( Alg::Abs ( val - result.K[ctrlPt] ) < 0.0001f );
+            OVR_UNUSED1(val); // For release build.
+        }
+
+        // Set up the fast inverse.
+        float maxRDist = result.DistortionFn ( maxValidRadius );
+        result.MaxInvR = maxRDist;
+        result.SetUpInverseApprox();
+
+        }break;
+
+    default: OVR_ASSERT ( false ); break;
+    }
+
+
+    // Chromatic aberration.
+    result.ChromaticAberration[0] = invLerpVal * pLower->Config.ChromaticAberration[0] + lerpVal * pUpper->Config.ChromaticAberration[0];
+    result.ChromaticAberration[1] = invLerpVal * pLower->Config.ChromaticAberration[1] + lerpVal * pUpper->Config.ChromaticAberration[1];
+    result.ChromaticAberration[2] = invLerpVal * pLower->Config.ChromaticAberration[2] + lerpVal * pUpper->Config.ChromaticAberration[2];
+    result.ChromaticAberration[3] = invLerpVal * pLower->Config.ChromaticAberration[3] + lerpVal * pUpper->Config.ChromaticAberration[3];
+
+    // Scale.
+    result.MetersPerTanAngleAtCenter =  pLower->Config.MetersPerTanAngleAtCenter * invLerpVal +
+                                        pUpper->Config.MetersPerTanAngleAtCenter * lerpVal;
+    /*
+    // Commented out - Causes ASSERT with no HMD plugged in
+#ifdef OVR_BUILD_DEBUG
+    if ( distortionType == Distortion_CatmullRom10 )
+    {
+        TestSaveLoadLensConfig ( result );
+    }
+#endif
+    */
+    return result;
+}
+
+
+
+
+
+DistortionRenderDesc CalculateDistortionRenderDesc ( StereoEye eyeType, HmdRenderInfo const &hmd,
+                                                     const LensConfig *pLensOverride /*= NULL */ )
+{
+    // From eye relief, IPD and device characteristics, we get the distortion mapping.
+    // This distortion does the following things:
+    // 1. It undoes the distortion that happens at the edges of the lens.
+    // 2. It maps the undistorted field into "retina" space.
+    // So the input is a pixel coordinate - the physical pixel on the display itself.
+    // The output is the real-world direction of the ray from this pixel as it comes out of the lens and hits the eye.
+    // However we typically think of rays "coming from" the eye, so the direction (TanAngleX,TanAngleY,1) is the direction
+    //      that the pixel appears to be in real-world space, where AngleX and AngleY are relative to the straight-ahead vector.
+    // If your renderer is a raytracer, you can use this vector directly (normalize as appropriate).
+    // However in standard rasterisers, we have rendered a 2D image and are putting it in front of the eye,
+    //      so we then need a mapping from this space to the [-1,1] UV coordinate space, which depends on exactly
+    //      where "in space" the app wants to put that rendertarget.
+    //      Where in space, and how large this rendertarget is, is completely up to the app and/or user,
+    //      though of course we can provide some useful hints.
+
+    // TODO: Use IPD and eye relief to modify distortion (i.e. non-radial component)
+    // TODO: cope with lenses that don't produce collimated light.
+    //       This means that IPD relative to the lens separation changes the light vergence,
+    //       and so we actually need to change where the image is displayed.
+
+    const HmdRenderInfo::EyeConfig &hmdEyeConfig = ( eyeType == StereoEye_Left ) ? hmd.EyeLeft : hmd.EyeRight;
+
+    DistortionRenderDesc localDistortion;
+    localDistortion.Lens = hmdEyeConfig.Distortion;
+
+    if ( pLensOverride != NULL )
+    {
+        localDistortion.Lens = *pLensOverride;
+    }
+
+    Sizef pixelsPerMeter(hmd.ResolutionInPixels.w / ( hmd.ScreenSizeInMeters.w - hmd.ScreenGapSizeInMeters ),
+                         hmd.ResolutionInPixels.h / hmd.ScreenSizeInMeters.h);
+
+    localDistortion.PixelsPerTanAngleAtCenter = (pixelsPerMeter * localDistortion.Lens.MetersPerTanAngleAtCenter).ToVector();
+    // Same thing, scaled to [-1,1] for each eye, rather than pixels.
+
+    localDistortion.TanEyeAngleScale = Vector2f(0.25f, 0.5f).EntrywiseMultiply(
+                                       (hmd.ScreenSizeInMeters / localDistortion.Lens.MetersPerTanAngleAtCenter).ToVector());
+    
+    // <--------------left eye------------------><-ScreenGapSizeInMeters-><--------------right eye----------------->
+    // <------------------------------------------ScreenSizeInMeters.Width----------------------------------------->
+    //                            <----------------LensSeparationInMeters--------------->
+    // <--centerFromLeftInMeters->
+    //                            ^
+    //                      Center of lens
+
+    // Find the lens centers in scale of [-1,+1] (NDC) in left eye.
+    float visibleWidthOfOneEye = 0.5f * ( hmd.ScreenSizeInMeters.w - hmd.ScreenGapSizeInMeters );
+    float centerFromLeftInMeters = ( hmd.ScreenSizeInMeters.w - hmd.LensSeparationInMeters ) * 0.5f;
+    localDistortion.LensCenter.x = (     centerFromLeftInMeters / visibleWidthOfOneEye          ) * 2.0f - 1.0f;
+    localDistortion.LensCenter.y = ( hmd.CenterFromTopInMeters  / hmd.ScreenSizeInMeters.h ) * 2.0f - 1.0f;
+    if ( eyeType == StereoEye_Right )
+    {
+        localDistortion.LensCenter.x = -localDistortion.LensCenter.x;
+    }
+
+    return localDistortion;
+}
+
+FovPort CalculateFovFromEyePosition ( float eyeReliefInMeters,
+                                      float offsetToRightInMeters,
+                                      float offsetDownwardsInMeters,
+                                      float lensDiameterInMeters,
+                                      float extraEyeRotationInRadians /*= 0.0f*/ )
+{
+    // 2D view of things:
+    //       |-|            <--- offsetToRightInMeters (in this case, it is negative)
+    // |=======C=======|    <--- lens surface (C=center)
+    //  \    |       _/
+    //   \   R     _/
+    //    \  |   _/
+    //     \ | _/
+    //      \|/
+    //       O  <--- center of pupil
+
+    // (technically the lens is round rather than square, so it's not correct to
+    // separate vertical and horizontal like this, but it's close enough)
+    float halfLensDiameter = lensDiameterInMeters * 0.5f;
+    FovPort fovPort;
+    fovPort.UpTan    = ( halfLensDiameter + offsetDownwardsInMeters ) / eyeReliefInMeters;
+    fovPort.DownTan  = ( halfLensDiameter - offsetDownwardsInMeters ) / eyeReliefInMeters;
+    fovPort.LeftTan  = ( halfLensDiameter + offsetToRightInMeters   ) / eyeReliefInMeters;
+    fovPort.RightTan = ( halfLensDiameter - offsetToRightInMeters   ) / eyeReliefInMeters;
+
+    if ( extraEyeRotationInRadians > 0.0f )
+    {
+        // That's the basic looking-straight-ahead eye position relative to the lens.
+        // But if you look left, the pupil moves left as the eyeball rotates, which
+        // means you can see more to the right than this geometry suggests.
+        // So add in the bounds for the extra movement of the pupil.
+
+        // Beyond 30 degrees does not increase FOV because the pupil starts moving backwards more than sideways.
+        extraEyeRotationInRadians = Alg::Min ( DegreeToRad ( 30.0f ), Alg::Max ( 0.0f, extraEyeRotationInRadians ) );
+        
+        // The rotation of the eye is a bit more complex than a simple circle.  The center of rotation
+        // at 13.5mm from cornea is slightly further back than the actual center of the eye.
+        // Additionally the rotation contains a small lateral component as the muscles pull the eye
+        const float eyeballCenterToPupil = 0.0135f;  // center of eye rotation
+        const float eyeballLateralPull = 0.001f * (extraEyeRotationInRadians / DegreeToRad ( 30.0f));  // lateral motion as linear function 
+        float extraTranslation = eyeballCenterToPupil * sinf ( extraEyeRotationInRadians ) + eyeballLateralPull;
+        float extraRelief = eyeballCenterToPupil * ( 1.0f - cosf ( extraEyeRotationInRadians ) );
+
+        fovPort.UpTan    = Alg::Max ( fovPort.UpTan   , ( halfLensDiameter + offsetDownwardsInMeters + extraTranslation ) / ( eyeReliefInMeters + extraRelief ) );
+        fovPort.DownTan  = Alg::Max ( fovPort.DownTan , ( halfLensDiameter - offsetDownwardsInMeters + extraTranslation ) / ( eyeReliefInMeters + extraRelief ) );
+        fovPort.LeftTan  = Alg::Max ( fovPort.LeftTan , ( halfLensDiameter + offsetToRightInMeters   + extraTranslation ) / ( eyeReliefInMeters + extraRelief ) );
+        fovPort.RightTan = Alg::Max ( fovPort.RightTan, ( halfLensDiameter - offsetToRightInMeters   + extraTranslation ) / ( eyeReliefInMeters + extraRelief ) );
+    }
+
+    return fovPort;
+}
+
+
+
+FovPort CalculateFovFromHmdInfo ( StereoEye eyeType,
+                                  DistortionRenderDesc const &distortion,
+                                  HmdRenderInfo const &hmd,
+                                  float extraEyeRotationInRadians /*= 0.0f*/ )
+{
+    FovPort fovPort;
+    float eyeReliefInMeters;
+    float offsetToRightInMeters;
+    if ( eyeType == StereoEye_Right )
+    {
+        eyeReliefInMeters     = hmd.EyeRight.ReliefInMeters;
+        offsetToRightInMeters = hmd.EyeRight.NoseToPupilInMeters - 0.5f * hmd.LensSeparationInMeters;
+    }
+    else
+    {
+        eyeReliefInMeters     = hmd.EyeLeft.ReliefInMeters;
+        offsetToRightInMeters = -(hmd.EyeLeft.NoseToPupilInMeters - 0.5f * hmd.LensSeparationInMeters);
+    }
+
+    // Limit the eye-relief to 6 mm for FOV calculations since this just tends to spread off-screen
+    // and get clamped anyways on DK1 (but in Unity it continues to spreads and causes 
+    // unnecessarily large render targets)
+    eyeReliefInMeters = Alg::Max(eyeReliefInMeters, 0.006f);
+
+    // Central view.
+    fovPort = CalculateFovFromEyePosition ( eyeReliefInMeters,
+                                            offsetToRightInMeters,
+                                            0.0f,
+                                            hmd.LensDiameterInMeters,
+                                            extraEyeRotationInRadians );
+
+    // clamp to the screen
+    fovPort = ClampToPhysicalScreenFov ( eyeType, distortion, fovPort );
+       
+    return fovPort;
+}
+
+
+
+FovPort GetPhysicalScreenFov ( StereoEye eyeType, DistortionRenderDesc const &distortion )
+{
+    OVR_UNUSED1 ( eyeType );
+
+    FovPort resultFovPort;
+
+    // Figure out the boundaries of the screen. We take the middle pixel of the screen,
+    // move to each of the four screen edges, and transform those back into TanAngle space.
+    Vector2f dmiddle = distortion.LensCenter;
+
+    // The gotcha is that for some distortion functions, the map will "wrap around"
+    // for screen pixels that are not actually visible to the user (especially on DK1,
+    // which has a lot of invisible pixels), and map to pixels that are close to the middle.
+    // This means the edges of the screen will actually be
+    // "closer" than the visible bounds, so we'll clip too aggressively.
+
+    // Solution - step gradually towards the boundary, noting the maximum distance.
+    struct FunctionHider
+    {
+        static FovPort FindRange ( Vector2f from, Vector2f to, int numSteps,
+                                          DistortionRenderDesc const &distortion )
+        {
+            FovPort result;
+            result.UpTan    = 0.0f;
+            result.DownTan  = 0.0f;
+            result.LeftTan  = 0.0f;
+            result.RightTan = 0.0f;
+
+            float stepScale = 1.0f / ( numSteps - 1 );
+            for ( int step = 0; step < numSteps; step++ )
+            {
+                float    lerpFactor  = stepScale * (float)step;
+                Vector2f sample      = from + (to - from) * lerpFactor;
+                Vector2f tanEyeAngle = TransformScreenNDCToTanFovSpace ( distortion, sample );
+
+                result.LeftTan  = Alg::Max ( result.LeftTan,  -tanEyeAngle.x );
+                result.RightTan = Alg::Max ( result.RightTan,  tanEyeAngle.x );
+                result.UpTan    = Alg::Max ( result.UpTan,    -tanEyeAngle.y );
+                result.DownTan  = Alg::Max ( result.DownTan,   tanEyeAngle.y );
+            }
+            return result;
+        }
+    };
+
+    FovPort leftFovPort  = FunctionHider::FindRange( dmiddle, Vector2f( -1.0f, dmiddle.y ), 10, distortion );
+    FovPort rightFovPort = FunctionHider::FindRange( dmiddle, Vector2f( 1.0f, dmiddle.y ),  10, distortion );
+    FovPort upFovPort    = FunctionHider::FindRange( dmiddle, Vector2f( dmiddle.x, -1.0f ), 10, distortion );
+    FovPort downFovPort  = FunctionHider::FindRange( dmiddle, Vector2f( dmiddle.x, 1.0f ),  10, distortion );
+    
+    resultFovPort.LeftTan  = leftFovPort.LeftTan;
+    resultFovPort.RightTan = rightFovPort.RightTan;
+    resultFovPort.UpTan    = upFovPort.UpTan;
+    resultFovPort.DownTan  = downFovPort.DownTan;
+
+    return resultFovPort;
+}
+
+FovPort ClampToPhysicalScreenFov( StereoEye eyeType, DistortionRenderDesc const &distortion,
+                                         FovPort inputFovPort )
+{
+    FovPort resultFovPort;
+    FovPort phsyicalFovPort = GetPhysicalScreenFov ( eyeType, distortion );
+    resultFovPort.LeftTan  = Alg::Min ( inputFovPort.LeftTan,  phsyicalFovPort.LeftTan );
+    resultFovPort.RightTan = Alg::Min ( inputFovPort.RightTan, phsyicalFovPort.RightTan );
+    resultFovPort.UpTan    = Alg::Min ( inputFovPort.UpTan,    phsyicalFovPort.UpTan );
+    resultFovPort.DownTan  = Alg::Min ( inputFovPort.DownTan,  phsyicalFovPort.DownTan );
+
+    return resultFovPort;
+}
+
+Sizei CalculateIdealPixelSize ( StereoEye eyeType, DistortionRenderDesc const &distortion,
+                                FovPort tanHalfFov, float pixelsPerDisplayPixel )
+{
+    OVR_UNUSED(eyeType);   // might be useful in the future if we do overlapping fovs
+
+    Sizei result;    
+    // TODO: if the app passes in a FOV that doesn't cover the centre, use the distortion values for the nearest edge/corner to match pixel size.
+    result.w  = (int)(0.5f + pixelsPerDisplayPixel * distortion.PixelsPerTanAngleAtCenter.x * ( tanHalfFov.LeftTan + tanHalfFov.RightTan ) );
+    result.h = (int)(0.5f + pixelsPerDisplayPixel * distortion.PixelsPerTanAngleAtCenter.y * ( tanHalfFov.UpTan   + tanHalfFov.DownTan  ) );
+    return result;
+}
+
+Recti GetFramebufferViewport ( StereoEye eyeType, HmdRenderInfo const &hmd )
+{
+    Recti result;
+    result.w = hmd.ResolutionInPixels.w/2;
+    result.h = hmd.ResolutionInPixels.h;
+    result.x = 0;
+    result.y = 0;
+    if ( eyeType == StereoEye_Right )
+    {
+        result.x = (hmd.ResolutionInPixels.w+1)/2;      // Round up, not down.
+    }
+    return result;
+}
+
+
+ScaleAndOffset2D CreateNDCScaleAndOffsetFromFov ( FovPort tanHalfFov )
+{
+    float projXScale = 2.0f / ( tanHalfFov.LeftTan + tanHalfFov.RightTan );
+    float projXOffset = ( tanHalfFov.LeftTan - tanHalfFov.RightTan ) * projXScale * 0.5f;
+    float projYScale = 2.0f / ( tanHalfFov.UpTan + tanHalfFov.DownTan );
+    float projYOffset = ( tanHalfFov.UpTan - tanHalfFov.DownTan ) * projYScale * 0.5f;
+
+    ScaleAndOffset2D result;
+    result.Scale    = Vector2f(projXScale, projYScale);
+    result.Offset   = Vector2f(projXOffset, projYOffset);
+    // Hey - why is that Y.Offset negated?
+    // It's because a projection matrix transforms from world coords with Y=up,
+    // whereas this is from NDC which is Y=down.
+
+    return result;
+}
+
+
+ScaleAndOffset2D CreateUVScaleAndOffsetfromNDCScaleandOffset ( ScaleAndOffset2D scaleAndOffsetNDC,
+                                                               Recti renderedViewport,
+                                                               Sizei renderTargetSize )
+{
+    // scaleAndOffsetNDC takes you to NDC space [-1,+1] within the given viewport on the rendertarget.
+    // We want a scale to instead go to actual UV coordinates you can sample with,
+    // which need [0,1] and ignore the viewport.
+    ScaleAndOffset2D result;
+    // Scale [-1,1] to [0,1]
+    result.Scale  = scaleAndOffsetNDC.Scale * 0.5f;
+    result.Offset = scaleAndOffsetNDC.Offset * 0.5f + Vector2f(0.5f);
+    
+    // ...but we will have rendered to a subsection of the RT, so scale for that.
+    Vector2f scale(  (float)renderedViewport.w / (float)renderTargetSize.w,
+                     (float)renderedViewport.h / (float)renderTargetSize.h );
+    Vector2f offset( (float)renderedViewport.x / (float)renderTargetSize.w,
+                     (float)renderedViewport.y / (float)renderTargetSize.h );
+
+	result.Scale  = result.Scale.EntrywiseMultiply(scale);
+    result.Offset  = result.Offset.EntrywiseMultiply(scale) + offset;
+    return result;
+}
+
+
+
+Matrix4f CreateProjection( bool rightHanded, FovPort tanHalfFov,
+                           float zNear /*= 0.01f*/, float zFar /*= 10000.0f*/ )
+{
+    // A projection matrix is very like a scaling from NDC, so we can start with that.
+    ScaleAndOffset2D scaleAndOffset = CreateNDCScaleAndOffsetFromFov ( tanHalfFov );
+
+    float handednessScale = 1.0f;
+    if ( rightHanded )
+    {
+        handednessScale = -1.0f;
+    }
+
+    Matrix4f projection;
+    // Produces X result, mapping clip edges to [-w,+w]
+    projection.M[0][0] = scaleAndOffset.Scale.x;
+    projection.M[0][1] = 0.0f;
+    projection.M[0][2] = handednessScale * scaleAndOffset.Offset.x;
+    projection.M[0][3] = 0.0f;
+
+    // Produces Y result, mapping clip edges to [-w,+w]
+    // Hey - why is that YOffset negated?
+    // It's because a projection matrix transforms from world coords with Y=up,
+    // whereas this is derived from an NDC scaling, which is Y=down.
+    projection.M[1][0] = 0.0f;
+    projection.M[1][1] = scaleAndOffset.Scale.y;
+    projection.M[1][2] = handednessScale * -scaleAndOffset.Offset.y;
+    projection.M[1][3] = 0.0f;
+
+    // Produces Z-buffer result - app needs to fill this in with whatever Z range it wants.
+    // We'll just use some defaults for now.
+    projection.M[2][0] = 0.0f;
+    projection.M[2][1] = 0.0f;
+    projection.M[2][2] = -handednessScale * zFar / (zNear - zFar);
+    projection.M[2][3] = (zFar * zNear) / (zNear - zFar);
+
+    // Produces W result (= Z in)
+    projection.M[3][0] = 0.0f;
+    projection.M[3][1] = 0.0f;
+    projection.M[3][2] = handednessScale;
+    projection.M[3][3] = 0.0f;
+
+    return projection;
+}
+
+
+Matrix4f CreateOrthoSubProjection ( bool rightHanded, StereoEye eyeType,
+                                    float tanHalfFovX, float tanHalfFovY,
+                                    float unitsX, float unitsY,
+                                    float distanceFromCamera, float interpupillaryDistance,
+                                    Matrix4f const &projection,
+                                    float zNear /*= 0.0f*/, float zFar /*= 0.0f*/ )
+{
+    OVR_UNUSED1 ( rightHanded );
+
+    float orthoHorizontalOffset = interpupillaryDistance * 0.5f / distanceFromCamera;
+    switch ( eyeType )
+    {
+    case StereoEye_Center:
+        orthoHorizontalOffset = 0.0f;
+        break;
+    case StereoEye_Left:
+        break;
+    case StereoEye_Right:
+        orthoHorizontalOffset = -orthoHorizontalOffset;
+        break;
+    default: OVR_ASSERT ( false ); break;
+    }
+
+    // Current projection maps real-world vector (x,y,1) to the RT.
+    // We want to find the projection that maps the range [-FovPixels/2,FovPixels/2] to
+    // the physical [-orthoHalfFov,orthoHalfFov]
+    // Note moving the offset from M[0][2]+M[1][2] to M[0][3]+M[1][3] - this means
+    // we don't have to feed in Z=1 all the time.
+    // The horizontal offset math is a little hinky because the destination is
+    // actually [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]
+    // So we need to first map [-FovPixels/2,FovPixels/2] to
+    //                         [-orthoHalfFov+orthoHorizontalOffset,orthoHalfFov+orthoHorizontalOffset]:
+    // x1 = x0 * orthoHalfFov/(FovPixels/2) + orthoHorizontalOffset;
+    //    = x0 * 2*orthoHalfFov/FovPixels + orthoHorizontalOffset;
+    // But then we need the sam mapping as the existing projection matrix, i.e.
+    // x2 = x1 * Projection.M[0][0] + Projection.M[0][2];
+    //    = x0 * (2*orthoHalfFov/FovPixels + orthoHorizontalOffset) * Projection.M[0][0] + Projection.M[0][2];
+    //    = x0 * Projection.M[0][0]*2*orthoHalfFov/FovPixels +
+    //      orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2];
+    // So in the new projection matrix we need to scale by Projection.M[0][0]*2*orthoHalfFov/FovPixels and
+    // offset by orthoHorizontalOffset*Projection.M[0][0] + Projection.M[0][2].
+
+    float orthoScaleX = 2.0f * tanHalfFovX / unitsX;
+    float orthoScaleY = 2.0f * tanHalfFovY / unitsY;
+    Matrix4f ortho;
+    ortho.M[0][0] = projection.M[0][0] * orthoScaleX;
+    ortho.M[0][1] = 0.0f;
+    ortho.M[0][2] = 0.0f;
+    ortho.M[0][3] = -projection.M[0][2] + ( orthoHorizontalOffset * projection.M[0][0] );
+
+    ortho.M[1][0] = 0.0f;
+    ortho.M[1][1] = -projection.M[1][1] * orthoScaleY;       // Note sign flip (text rendering uses Y=down).
+    ortho.M[1][2] = 0.0f;
+    ortho.M[1][3] = -projection.M[1][2];
+
+    if ( fabsf ( zNear - zFar ) < 0.001f )
+    {
+        ortho.M[2][0] = 0.0f;
+        ortho.M[2][1] = 0.0f;
+        ortho.M[2][2] = 0.0f;
+        ortho.M[2][3] = zFar;
+    }
+    else
+    {
+        ortho.M[2][0] = 0.0f;
+        ortho.M[2][1] = 0.0f;
+        ortho.M[2][2] = zFar / (zNear - zFar);
+        ortho.M[2][3] = (zFar * zNear) / (zNear - zFar);
+    }
+
+    // No perspective correction for ortho.
+    ortho.M[3][0] = 0.0f;
+    ortho.M[3][1] = 0.0f;
+    ortho.M[3][2] = 0.0f;
+    ortho.M[3][3] = 1.0f;
+
+    return ortho;
+}
+
+
+//-----------------------------------------------------------------------------------
+// A set of "forward-mapping" functions, mapping from framebuffer space to real-world and/or texture space.
+
+// This mimics the first half of the distortion shader's function.
+Vector2f TransformScreenNDCToTanFovSpace( DistortionRenderDesc const &distortion,
+                                          const Vector2f &framebufferNDC )
+{
+    // Scale to TanHalfFov space, but still distorted.
+    Vector2f tanEyeAngleDistorted;
+    tanEyeAngleDistorted.x = ( framebufferNDC.x - distortion.LensCenter.x ) * distortion.TanEyeAngleScale.x;
+    tanEyeAngleDistorted.y = ( framebufferNDC.y - distortion.LensCenter.y ) * distortion.TanEyeAngleScale.y;
+    // Distort.
+    float radiusSquared = ( tanEyeAngleDistorted.x * tanEyeAngleDistorted.x )
+                        + ( tanEyeAngleDistorted.y * tanEyeAngleDistorted.y );
+    float distortionScale = distortion.Lens.DistortionFnScaleRadiusSquared ( radiusSquared );
+    Vector2f tanEyeAngle;
+    tanEyeAngle.x = tanEyeAngleDistorted.x * distortionScale;
+    tanEyeAngle.y = tanEyeAngleDistorted.y * distortionScale;
+
+    return tanEyeAngle;
+}
+
+// Same, with chromatic aberration correction.
+void TransformScreenNDCToTanFovSpaceChroma ( Vector2f *resultR, Vector2f *resultG, Vector2f *resultB, 
+                                             DistortionRenderDesc const &distortion,
+                                             const Vector2f &framebufferNDC )
+{
+    // Scale to TanHalfFov space, but still distorted.
+    Vector2f tanEyeAngleDistorted;
+    tanEyeAngleDistorted.x = ( framebufferNDC.x - distortion.LensCenter.x ) * distortion.TanEyeAngleScale.x;
+    tanEyeAngleDistorted.y = ( framebufferNDC.y - distortion.LensCenter.y ) * distortion.TanEyeAngleScale.y;
+    // Distort.
+    float radiusSquared = ( tanEyeAngleDistorted.x * tanEyeAngleDistorted.x )
+                        + ( tanEyeAngleDistorted.y * tanEyeAngleDistorted.y );
+    Vector3f distortionScales = distortion.Lens.DistortionFnScaleRadiusSquaredChroma ( radiusSquared );
+    *resultR = tanEyeAngleDistorted * distortionScales.x;
+    *resultG = tanEyeAngleDistorted * distortionScales.y;
+    *resultB = tanEyeAngleDistorted * distortionScales.z;
+}
+
+// This mimics the second half of the distortion shader's function.
+Vector2f TransformTanFovSpaceToRendertargetTexUV( StereoEyeParams const &eyeParams,
+                                                  Vector2f const &tanEyeAngle )
+{
+    Vector2f textureUV;
+    textureUV.x = tanEyeAngle.x * eyeParams.EyeToSourceUV.Scale.x + eyeParams.EyeToSourceUV.Offset.x;
+    textureUV.y = tanEyeAngle.y * eyeParams.EyeToSourceUV.Scale.y + eyeParams.EyeToSourceUV.Offset.y;
+    return textureUV;
+}
+
+Vector2f TransformTanFovSpaceToRendertargetNDC( StereoEyeParams const &eyeParams,
+                                                Vector2f const &tanEyeAngle )
+{
+    Vector2f textureNDC;
+    textureNDC.x = tanEyeAngle.x * eyeParams.EyeToSourceNDC.Scale.x + eyeParams.EyeToSourceNDC.Offset.x;
+    textureNDC.y = tanEyeAngle.y * eyeParams.EyeToSourceNDC.Scale.y + eyeParams.EyeToSourceNDC.Offset.y;
+    return textureNDC;
+}
+
+Vector2f TransformScreenPixelToScreenNDC( Recti const &distortionViewport,
+                                          Vector2f const &pixel )
+{
+    // Move to [-1,1] NDC coords.
+    Vector2f framebufferNDC;
+    framebufferNDC.x = -1.0f + 2.0f * ( ( pixel.x - (float)distortionViewport.x ) / (float)distortionViewport.w );
+    framebufferNDC.y = -1.0f + 2.0f * ( ( pixel.y - (float)distortionViewport.y ) / (float)distortionViewport.h );
+    return framebufferNDC;
+}
+
+Vector2f TransformScreenPixelToTanFovSpace( Recti const &distortionViewport,
+                                            DistortionRenderDesc const &distortion,
+                                            Vector2f const &pixel )
+{
+    return TransformScreenNDCToTanFovSpace( distortion,
+                TransformScreenPixelToScreenNDC( distortionViewport, pixel ) );
+}
+
+Vector2f TransformScreenNDCToRendertargetTexUV( DistortionRenderDesc const &distortion,
+                                                StereoEyeParams const &eyeParams,
+                                                Vector2f const &pixel )
+{
+    return TransformTanFovSpaceToRendertargetTexUV ( eyeParams,
+                TransformScreenNDCToTanFovSpace ( distortion, pixel ) );
+}
+
+Vector2f TransformScreenPixelToRendertargetTexUV( Recti const &distortionViewport,
+                                                  DistortionRenderDesc const &distortion,
+                                                  StereoEyeParams const &eyeParams,
+                                                  Vector2f const &pixel )
+{
+    return TransformTanFovSpaceToRendertargetTexUV ( eyeParams,
+                TransformScreenPixelToTanFovSpace ( distortionViewport, distortion, pixel ) );
+}
+
+
+//-----------------------------------------------------------------------------------
+// A set of "reverse-mapping" functions, mapping from real-world and/or texture space back to the framebuffer.
+
+Vector2f TransformTanFovSpaceToScreenNDC( DistortionRenderDesc const &distortion,
+                                          const Vector2f &tanEyeAngle, bool usePolyApprox /*= false*/ )
+{
+    float tanEyeAngleRadius = tanEyeAngle.Length();
+    float tanEyeAngleDistortedRadius = distortion.Lens.DistortionFnInverseApprox ( tanEyeAngleRadius );
+    if ( !usePolyApprox )
+    {
+        tanEyeAngleDistortedRadius = distortion.Lens.DistortionFnInverse ( tanEyeAngleRadius );
+    }
+    Vector2f tanEyeAngleDistorted = tanEyeAngle;
+    if ( tanEyeAngleRadius > 0.0f )
+    {   
+        tanEyeAngleDistorted = tanEyeAngle * ( tanEyeAngleDistortedRadius / tanEyeAngleRadius );
+    }
+
+    Vector2f framebufferNDC;
+    framebufferNDC.x = ( tanEyeAngleDistorted.x / distortion.TanEyeAngleScale.x ) + distortion.LensCenter.x;
+    framebufferNDC.y = ( tanEyeAngleDistorted.y / distortion.TanEyeAngleScale.y ) + distortion.LensCenter.y;
+
+    return framebufferNDC;
+}
+
+Vector2f TransformRendertargetNDCToTanFovSpace( const ScaleAndOffset2D &eyeToSourceNDC,
+                                                const Vector2f &textureNDC )
+{
+    Vector2f tanEyeAngle = (textureNDC - eyeToSourceNDC.Offset) / eyeToSourceNDC.Scale;
+    return tanEyeAngle;
+}
+
+
+
+} //namespace OVR
+
+//Just want to make a copy disentangled from all these namespaces!
+float ExtEvalCatmullRom10Spline ( float const *K, float scaledVal )
+{
+	return(OVR::EvalCatmullRom10Spline ( K, scaledVal ));
+}
+
+
diff --git a/LibOVR/Src/OVR_Stereo.h b/LibOVR/Src/OVR_Stereo.h
new file mode 100644
index 0000000..dd5499c
--- /dev/null
+++ b/LibOVR/Src/OVR_Stereo.h
@@ -0,0 +1,460 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   OVR_Stereo.h
+Content     :   Stereo rendering functions
+Created     :   November 30, 2013
+Authors     :   Tom Fosyth
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Stereo_h
+#define OVR_Stereo_h
+
+#include "OVR_Device.h"
+
+// CAPI Forward declaration.
+typedef struct ovrFovPort_ ovrFovPort;
+typedef struct ovrRecti_ ovrRecti;
+
+namespace OVR {
+
+//-----------------------------------------------------------------------------------
+// ***** Stereo Enumerations
+
+// StereoEye specifies which eye we are rendering for; it is used to
+// retrieve StereoEyeParams.
+enum StereoEye
+{
+    StereoEye_Center,
+    StereoEye_Left,
+    StereoEye_Right    
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** FovPort
+
+// FovPort describes Field Of View (FOV) of a viewport.
+// This class has values for up, down, left and right, stored in 
+// tangent of the angle units to simplify calculations.
+//
+// As an example, for a standard 90 degree vertical FOV, we would 
+// have: { UpTan = tan(90 degrees / 2), DownTan = tan(90 degrees / 2) }.
+//
+// CreateFromRadians/Degrees helper functions can be used to
+// access FOV in different units.
+
+struct FovPort
+{
+    float UpTan;
+    float DownTan;
+    float LeftTan;
+    float RightTan;
+
+    FovPort ( float sideTan = 0.0f ) :
+        UpTan(sideTan), DownTan(sideTan), LeftTan(sideTan), RightTan(sideTan) { }
+    FovPort ( float u, float d, float l, float r ) :
+        UpTan(u), DownTan(d), LeftTan(l), RightTan(r) { }
+
+    // C-interop support: FovPort <-> ovrFovPort (implementation in OVR_CAPI.cpp).
+    FovPort(const ovrFovPort& src);
+    operator ovrFovPort () const;
+
+
+    static FovPort CreateFromRadians(float horizontalFov, float verticalFov)
+    {
+        FovPort result;
+        result.UpTan    = tanf (   verticalFov * 0.5f );
+        result.DownTan  = tanf (   verticalFov * 0.5f );
+        result.LeftTan  = tanf ( horizontalFov * 0.5f );
+        result.RightTan = tanf ( horizontalFov * 0.5f );
+        return result;
+    }
+
+    static FovPort CreateFromDegrees(float horizontalFovDegrees,
+                                     float verticalFovDegrees)
+    {
+        return CreateFromRadians(DegreeToRad(horizontalFovDegrees),
+                                 DegreeToRad(verticalFovDegrees));
+    }
+
+    //  Get Horizontal/Vertical components of Fov in radians.
+    float GetVerticalFovRadians() const     { return atanf(UpTan)    + atanf(DownTan); }
+    float GetHorizontalFovRadians() const   { return atanf(LeftTan)  + atanf(RightTan); }
+    //  Get Horizontal/Vertical components of Fov in degrees.
+    float GetVerticalFovDegrees() const     { return RadToDegree(GetVerticalFovRadians()); }
+    float GetHorizontalFovDegrees() const   { return RadToDegree(GetHorizontalFovRadians()); }
+
+    // Compute maximum tangent value among all four sides.
+    float GetMaxSideTan() const
+    {
+        return Alg::Max(Alg::Max(UpTan, DownTan), Alg::Max(LeftTan, RightTan));
+    }
+
+    // Converts Fov Tan angle units to [-1,1] render target NDC space
+    Vector2f TanAngleToRendertargetNDC(Vector2f const &tanEyeAngle);
+
+
+    // Compute per-channel minimum and maximum of Fov.
+    static FovPort Min(const FovPort& a, const FovPort& b)
+    {   
+        FovPort fov( Alg::Min( a.UpTan   , b.UpTan    ),   
+                     Alg::Min( a.DownTan , b.DownTan  ),
+                     Alg::Min( a.LeftTan , b.LeftTan  ),
+                     Alg::Min( a.RightTan, b.RightTan ) );
+        return fov;
+    }
+
+    static FovPort Max(const FovPort& a, const FovPort& b)
+    {   
+        FovPort fov( Alg::Max( a.UpTan   , b.UpTan    ),   
+                     Alg::Max( a.DownTan , b.DownTan  ),
+                     Alg::Max( a.LeftTan , b.LeftTan  ),
+                     Alg::Max( a.RightTan, b.RightTan ) );
+        return fov;
+    }
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** ScaleAndOffset
+
+struct ScaleAndOffset2D
+{
+    Vector2f Scale;
+    Vector2f Offset;
+
+    ScaleAndOffset2D(float sx = 0.0f, float sy = 0.0f, float ox = 0.0f, float oy = 0.0f)
+      : Scale(sx, sy), Offset(ox, oy)        
+    { }
+};
+
+
+//-----------------------------------------------------------------------------------
+// ***** Misc. utility functions.
+
+// Inputs are 4 points (pFitX[0],pFitY[0]) through (pFitX[3],pFitY[3])
+// Result is four coefficients in pResults[0] through pResults[3] such that
+//      y = pResult[0] + x * ( pResult[1] + x * ( pResult[2] + x * ( pResult[3] ) ) );
+// passes through all four input points.
+// Return is true if it succeeded, false if it failed (because two control points
+// have the same pFitX value).
+bool FitCubicPolynomial ( float *pResult, const float *pFitX, const float *pFitY );
+
+//-----------------------------------------------------------------------------------
+// ***** LensConfig
+
+// LensConfig describes the configuration of a single lens in an HMD.
+// - Eqn and K[] describe a distortion function.
+// - MetersPerTanAngleAtCenter is the relationship between distance on a
+//   screen (at the center of the lens), and the angle variance of the light after it
+//   has passed through the lens.
+// - ChromaticAberration is an array of parameters for controlling
+//   additional Red and Blue scaling in order to reduce chromatic aberration
+//   caused by the Rift lenses.
+struct LensConfig
+{
+    // The result is a scaling applied to the distance from the center of the lens.
+    float    DistortionFnScaleRadiusSquared (float rsq) const;
+    // x,y,z components map to r,g,b scales.
+    Vector3f DistortionFnScaleRadiusSquaredChroma (float rsq) const;
+
+    // DistortionFn applies distortion to the argument.
+    // Input: the distance in TanAngle/NIC space from the optical center to the input pixel.
+    // Output: the resulting distance after distortion.
+    float DistortionFn(float r) const
+    {
+        return r * DistortionFnScaleRadiusSquared ( r * r );
+    }
+
+    // DistortionFnInverse computes the inverse of the distortion function on an argument.
+    float DistortionFnInverse(float r) const;
+
+    // Also computes the inverse, but using a polynomial approximation. Warning - it's just an approximation!
+    float DistortionFnInverseApprox(float r) const;
+    // Sets up InvK[].
+    void SetUpInverseApprox();
+
+    // Sets a bunch of sensible defaults.
+    void SetToIdentity();
+
+
+
+    enum { NumCoefficients = 11 };
+
+    DistortionEqnType   Eqn;
+    float               K[NumCoefficients];
+    float               MaxR;       // The highest R you're going to query for - the curve is unpredictable beyond it.
+
+    float               MetersPerTanAngleAtCenter;
+
+    // Additional per-channel scaling is applied after distortion:
+    //  Index [0] - Red channel constant coefficient.
+    //  Index [1] - Red channel r^2 coefficient.
+    //  Index [2] - Blue channel constant coefficient.
+    //  Index [3] - Blue channel r^2 coefficient.
+    float               ChromaticAberration[4];
+
+    float               InvK[NumCoefficients];
+    float               MaxInvR;
+};
+
+
+// For internal use - storing and loading lens config data
+
+// Returns true on success.
+bool LoadLensConfig ( LensConfig *presult, UByte const *pbuffer, int bufferSizeInBytes );
+
+// Returns number of bytes needed.
+int SaveLensConfigSizeInBytes ( LensConfig const &config );
+// Returns true on success.
+bool SaveLensConfig ( UByte *pbuffer, int bufferSizeInBytes, LensConfig const &config );
+
+
+//-----------------------------------------------------------------------------------
+// ***** DistortionRenderDesc
+
+// This describes distortion for a single eye in an HMD with a display, not just the lens by itself.
+struct DistortionRenderDesc
+{
+    // The raw lens values.
+    LensConfig          Lens;
+
+    // These map from [-1,1] across the eye being rendered into TanEyeAngle space (but still distorted)
+    Vector2f            LensCenter;
+    Vector2f            TanEyeAngleScale;
+    // Computed from device characteristics, IPD and eye-relief.
+    // (not directly used for rendering, but very useful)
+    Vector2f            PixelsPerTanAngleAtCenter;
+};
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** HmdRenderInfo
+
+// All the parts of the HMD info that are needed to set up the rendering system.
+
+struct HmdRenderInfo
+{
+    // The start of this sturucture is intentionally very similar to HMDInfo in OVER_Device.h
+    // However to reduce interdependencies, one does not simply #include the other.
+
+    HmdTypeEnum HmdType;
+
+    // Size of the entire screen
+    Size<int>   ResolutionInPixels;
+    Size<float> ScreenSizeInMeters;
+    float       ScreenGapSizeInMeters;
+
+    // Characteristics of the lenses.
+    float       CenterFromTopInMeters;
+    float       LensSeparationInMeters;
+    float       LensDiameterInMeters;
+    float       LensSurfaceToMidplateInMeters;
+    EyeCupType  EyeCups;
+
+    // Timing & shutter data. All values in seconds.
+    struct ShutterInfo
+    {
+        HmdShutterTypeEnum  Type;
+        float               VsyncToNextVsync;                // 1/framerate
+        float               VsyncToFirstScanline;            // for global shutter, vsync->shutter open.
+        float               FirstScanlineToLastScanline;     // for global shutter, will be zero.
+        float               PixelSettleTime;                 // estimated.
+        float               PixelPersistence;                // Full persistence = 1/framerate.
+    }           Shutter;
+
+
+    // These are all set from the user's profile.
+    struct EyeConfig
+    {
+        // Distance from center of eyeball to front plane of lens.
+        float               ReliefInMeters;
+        // Distance from nose (technically, center of Rift) to the middle of the eye.
+        float               NoseToPupilInMeters;
+
+        LensConfig          Distortion;
+    } EyeLeft, EyeRight;
+
+
+    HmdRenderInfo()
+    {
+        HmdType = HmdType_None;
+        ResolutionInPixels.w = 0;
+        ResolutionInPixels.h = 0;
+        ScreenSizeInMeters.w = 0.0f;
+        ScreenSizeInMeters.h = 0.0f;
+        ScreenGapSizeInMeters = 0.0f;
+        CenterFromTopInMeters = 0.0f;
+        LensSeparationInMeters = 0.0f;
+        LensDiameterInMeters = 0.0f;
+        LensSurfaceToMidplateInMeters = 0.0f;
+        Shutter.Type = HmdShutter_LAST;
+        Shutter.VsyncToNextVsync = 0.0f;
+        Shutter.VsyncToFirstScanline = 0.0f;
+        Shutter.FirstScanlineToLastScanline = 0.0f;
+        Shutter.PixelSettleTime = 0.0f;
+        Shutter.PixelPersistence = 0.0f;
+        EyeCups = EyeCup_DK1A;
+        EyeLeft.ReliefInMeters = 0.0f;
+        EyeLeft.NoseToPupilInMeters = 0.0f;
+        EyeLeft.Distortion.SetToIdentity();
+        EyeRight = EyeLeft;
+    }
+
+    // The "center eye" is the position the HMD tracking returns,
+    // and games will also usually use it for audio, aiming reticles, some line-of-sight tests, etc.
+    EyeConfig GetEyeCenter() const
+    {
+        EyeConfig result;
+        result.ReliefInMeters = 0.5f * ( EyeLeft.ReliefInMeters + EyeRight.ReliefInMeters );
+        result.NoseToPupilInMeters = 0.0f;
+        result.Distortion.SetToIdentity();
+        return result;
+    }
+
+};
+
+
+
+
+//-----------------------------------------------------------------------------------
+
+// Stateless computation functions, in somewhat recommended execution order.
+// For examples on how to use many of them, see the StereoConfig::UpdateComputedState function.
+
+const float OVR_DEFAULT_EXTRA_EYE_ROTATION = 30.0f * Math<float>::DegreeToRadFactor;
+
+// Creates a dummy debug HMDInfo matching a particular HMD model.
+// Useful for development without an actual HMD attached.
+HMDInfo             CreateDebugHMDInfo(HmdTypeEnum hmdType);
+
+
+// profile may be NULL, in which case it uses the hard-coded defaults.
+// distortionType should be left at the default unless you require something specific for your distortion shaders.
+// eyeCupOverride can be EyeCup_LAST, in which case it uses the one in the profile.
+HmdRenderInfo       GenerateHmdRenderInfoFromHmdInfo ( HMDInfo const &hmdInfo,
+                                                       Profile const *profile = NULL,
+                                                       DistortionEqnType distortionType = Distortion_CatmullRom10,
+                                                       EyeCupType eyeCupOverride = EyeCup_LAST );
+
+LensConfig          GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderInfo const &hmd,
+                                                      DistortionEqnType distortionType = Distortion_CatmullRom10 );
+
+DistortionRenderDesc CalculateDistortionRenderDesc ( StereoEye eyeType, HmdRenderInfo const &hmd,
+                                                     LensConfig const *pLensOverride = NULL );
+
+FovPort             CalculateFovFromEyePosition ( float eyeReliefInMeters,
+                                                  float offsetToRightInMeters,
+                                                  float offsetDownwardsInMeters,
+                                                  float lensDiameterInMeters,
+                                                  float extraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION);
+
+FovPort             CalculateFovFromHmdInfo ( StereoEye eyeType,
+                                              DistortionRenderDesc const &distortion,
+                                              HmdRenderInfo const &hmd,
+                                              float extraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION );
+
+FovPort             GetPhysicalScreenFov ( StereoEye eyeType, DistortionRenderDesc const &distortion );
+
+FovPort             ClampToPhysicalScreenFov ( StereoEye eyeType, DistortionRenderDesc const &distortion,
+                                               FovPort inputFovPort );
+
+Sizei               CalculateIdealPixelSize ( StereoEye eyeType, DistortionRenderDesc const &distortion,
+                                              FovPort fov, float pixelsPerDisplayPixel );
+
+Recti               GetFramebufferViewport ( StereoEye eyeType, HmdRenderInfo const &hmd );
+
+Matrix4f            CreateProjection ( bool rightHanded, FovPort fov,
+                                       float zNear = 0.01f, float zFar = 10000.0f );
+
+Matrix4f            CreateOrthoSubProjection ( bool rightHanded, StereoEye eyeType,
+                                               float tanHalfFovX, float tanHalfFovY,
+                                               float unitsX, float unitsY, float distanceFromCamera,
+                                               float interpupillaryDistance, Matrix4f const &projection,
+                                               float zNear = 0.0f, float zFar = 0.0f );
+
+ScaleAndOffset2D    CreateNDCScaleAndOffsetFromFov ( FovPort fov );
+
+ScaleAndOffset2D    CreateUVScaleAndOffsetfromNDCScaleandOffset ( ScaleAndOffset2D scaleAndOffsetNDC,
+                                                                  Recti renderedViewport,
+                                                                  Sizei renderTargetSize );
+
+
+//-----------------------------------------------------------------------------------
+// ***** StereoEyeParams
+
+// StereoEyeParams describes RenderDevice configuration needed to render
+// the scene for one eye. 
+struct StereoEyeParams
+{
+    StereoEye               Eye;
+    Matrix4f                ViewAdjust;             // Translation to be applied to view matrix.
+
+    // Distortion and the VP on the physical display - the thing to run the distortion shader on.
+    DistortionRenderDesc    Distortion;
+    Recti                   DistortionViewport;
+
+    // Projection and VP of a particular view (you could have multiple of these).
+    Recti                   RenderedViewport;       // Viewport that we render the standard scene to.
+    FovPort                 Fov;                    // The FOVs of this scene.
+    Matrix4f                RenderedProjection;     // Projection matrix used with this eye.
+    ScaleAndOffset2D        EyeToSourceNDC;         // Mapping from TanEyeAngle space to [-1,+1] on the rendered image.
+    ScaleAndOffset2D        EyeToSourceUV;          // Mapping from TanEyeAngle space to actual texture UV coords.
+};
+
+
+//-----------------------------------------------------------------------------------
+// A set of "forward-mapping" functions, mapping from framebuffer space to real-world and/or texture space.
+Vector2f TransformScreenNDCToTanFovSpace ( DistortionRenderDesc const &distortion,
+                                           const Vector2f &framebufferNDC );
+void TransformScreenNDCToTanFovSpaceChroma ( Vector2f *resultR, Vector2f *resultG, Vector2f *resultB, 
+                                             DistortionRenderDesc const &distortion,
+                                             const Vector2f &framebufferNDC );
+Vector2f TransformTanFovSpaceToRendertargetTexUV ( StereoEyeParams const &eyeParams,
+                                                   Vector2f const &tanEyeAngle );
+Vector2f TransformTanFovSpaceToRendertargetNDC ( StereoEyeParams const &eyeParams,
+                                                 Vector2f const &tanEyeAngle );
+Vector2f TransformScreenPixelToScreenNDC( Recti const &distortionViewport,
+                                          Vector2f const &pixel );
+Vector2f TransformScreenPixelToTanFovSpace ( Recti const &distortionViewport,
+                                             DistortionRenderDesc const &distortion,
+                                             Vector2f const &pixel );
+Vector2f TransformScreenNDCToRendertargetTexUV( DistortionRenderDesc const &distortion,
+                                                StereoEyeParams const &eyeParams,
+                                                Vector2f const &pixel );
+Vector2f TransformScreenPixelToRendertargetTexUV( Recti const &distortionViewport,
+                                                  DistortionRenderDesc const &distortion,
+                                                  StereoEyeParams const &eyeParams,
+                                                  Vector2f const &pixel );
+
+// A set of "reverse-mapping" functions, mapping from real-world and/or texture space back to the framebuffer.
+// Be aware that many of these are significantly slower than their forward-mapping counterparts.
+Vector2f TransformTanFovSpaceToScreenNDC( DistortionRenderDesc const &distortion,
+                                          const Vector2f &tanEyeAngle, bool usePolyApprox = false );
+Vector2f TransformRendertargetNDCToTanFovSpace( const ScaleAndOffset2D &eyeToSourceNDC,
+                                                const Vector2f &textureNDC );
+
+} //namespace OVR
+
+#endif // OVR_Stereo_h
\ No newline at end of file
diff --git a/LibOVR/Src/OVR_ThreadCommandQueue.cpp b/LibOVR/Src/OVR_ThreadCommandQueue.cpp
new file mode 100644
index 0000000..bc0d7dc
--- /dev/null
+++ b/LibOVR/Src/OVR_ThreadCommandQueue.cpp
@@ -0,0 +1,380 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_ThreadCommandQueue.cpp
+Content     :   Command queue for operations executed on a thread
+Created     :   October 29, 2012
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#include "OVR_ThreadCommandQueue.h"
+
+namespace OVR {
+
+
+//------------------------------------------------------------------------
+// ***** CircularBuffer
+
+// CircularBuffer is a FIFO buffer implemented in a single block of memory,
+// which allows writing and reading variable-size data chucks. Write fails
+// if buffer is full.
+
+class CircularBuffer
+{
+    enum {
+        AlignSize = 16,
+        AlignMask = AlignSize - 1
+    };
+
+    UByte*  pBuffer;
+    UPInt   Size;
+    UPInt   Tail;   // Byte offset of next item to be popped.
+    UPInt   Head;   // Byte offset of where next push will take place.
+    UPInt   End;    // When Head < Tail, this is used instead of Size.    
+
+    inline UPInt roundUpSize(UPInt size)
+    { return (size + AlignMask) & ~(UPInt)AlignMask; }
+
+public:
+
+    CircularBuffer(UPInt size)
+        : Size(size), Tail(0), Head(0), End(0)
+    {
+        pBuffer = (UByte*)OVR_ALLOC_ALIGNED(roundUpSize(size), AlignSize);
+    }
+    ~CircularBuffer()
+    {
+        // For ThreadCommands, we must consume everything before shutdown.
+        OVR_ASSERT(IsEmpty());
+        OVR_FREE_ALIGNED(pBuffer);
+    }
+
+    bool    IsEmpty() const { return (Head == Tail); }
+
+    // Allocates a state block of specified size and advances pointers,
+    // returning 0 if buffer is full.
+    UByte*  Write(UPInt size);
+
+    // Returns a pointer to next available data block; 0 if none available.
+    UByte*  ReadBegin()
+    { return (Head != Tail) ? (pBuffer + Tail) : 0; }
+    // Consumes data of specified size; this must match size passed to Write.
+    void    ReadEnd(UPInt size);
+};
+
+
+// Allocates a state block of specified size and advances pointers,
+// returning 0 if buffer is full.
+UByte* CircularBuffer::Write(UPInt size)
+{
+    UByte* p = 0;
+
+    size = roundUpSize(size);
+    // Since this is circular buffer, always allow at least one item.
+    OVR_ASSERT(size < Size/2);
+
+    if (Head >= Tail)
+    {
+        OVR_ASSERT(End == 0);
+        
+        if (size <= (Size - Head))
+        {
+            p    = pBuffer + Head;
+            Head += size;
+        }
+        else if (size < Tail)
+        {
+            p    = pBuffer;
+            End  = Head;
+            Head = size;
+            OVR_ASSERT(Head != Tail);
+        }
+    }
+    else
+    {
+        OVR_ASSERT(End != 0);
+
+        if ((Tail - Head) > size)
+        {
+            p    = pBuffer + Head;
+            Head += size;
+            OVR_ASSERT(Head != Tail);
+        }
+    }
+
+    return p;
+}
+
+void CircularBuffer::ReadEnd(UPInt size)
+{
+    OVR_ASSERT(Head != Tail);
+    size = roundUpSize(size);
+    
+    Tail += size;        
+    if (Tail == End)
+    {
+        Tail = End = 0;
+    }
+    else if (Tail == Head)
+    {        
+        OVR_ASSERT(End == 0);
+        Tail = Head = 0;
+    }
+}
+
+
+//-------------------------------------------------------------------------------------
+// ***** ThreadCommand
+
+ThreadCommand::PopBuffer::~PopBuffer()
+{
+    if (Size)
+        Destruct<ThreadCommand>(toCommand());
+}
+
+void ThreadCommand::PopBuffer::InitFromBuffer(void* data)
+{
+    ThreadCommand* cmd = (ThreadCommand*)data;
+    OVR_ASSERT(cmd->Size <= MaxSize);
+
+    if (Size)
+        Destruct<ThreadCommand>(toCommand());    
+    Size = cmd->Size;    
+    memcpy(Buffer, (void*)cmd, Size);
+}
+
+void ThreadCommand::PopBuffer::Execute()
+{
+    ThreadCommand* command = toCommand();
+    OVR_ASSERT(command);
+    command->Execute();
+    if (NeedsWait())
+        GetEvent()->PulseEvent();
+}
+
+//-------------------------------------------------------------------------------------
+
+class ThreadCommandQueueImpl : public NewOverrideBase
+{
+    typedef ThreadCommand::NotifyEvent NotifyEvent;
+    friend class ThreadCommandQueue;
+    
+public:
+
+    ThreadCommandQueueImpl(ThreadCommandQueue* queue)
+        : pQueue(queue), ExitEnqueued(false), ExitProcessed(false), CommandBuffer(2048)
+    {
+    }
+    ~ThreadCommandQueueImpl();
+
+
+    bool PushCommand(const ThreadCommand& command);
+    bool PopCommand(ThreadCommand::PopBuffer* popBuffer);
+
+
+    // ExitCommand is used by notify us that Thread is shutting down.
+    struct ExitCommand : public ThreadCommand
+    {
+        ThreadCommandQueueImpl* pImpl;
+        
+        ExitCommand(ThreadCommandQueueImpl* impl, bool wait)
+            : ThreadCommand(sizeof(ExitCommand), wait, true), pImpl(impl) { }
+
+        virtual void Execute() const
+        {
+            Lock::Locker lock(&pImpl->QueueLock);
+            pImpl->ExitProcessed = true;
+        }
+        virtual ThreadCommand* CopyConstruct(void* p) const 
+        { return Construct<ExitCommand>(p, *this); }
+    };
+
+
+    NotifyEvent* AllocNotifyEvent_NTS()
+    {
+        NotifyEvent* p = AvailableEvents.GetFirst();
+
+        if (!AvailableEvents.IsNull(p))
+            p->RemoveNode();        
+        else
+            p = new NotifyEvent;
+        return p;
+    }
+
+    void         FreeNotifyEvent_NTS(NotifyEvent* p)
+    {
+        AvailableEvents.PushBack(p);
+    }
+
+    void        FreeNotifyEvents_NTS()
+    {
+        while(!AvailableEvents.IsEmpty())
+        {
+            NotifyEvent* p = AvailableEvents.GetFirst();
+            p->RemoveNode();
+            delete p;
+        }
+    }
+
+    ThreadCommandQueue* pQueue;
+    Lock                QueueLock;
+    volatile bool       ExitEnqueued;
+    volatile bool       ExitProcessed;
+    List<NotifyEvent>   AvailableEvents;
+    List<NotifyEvent>   BlockedProducers;
+    CircularBuffer      CommandBuffer;
+};
+
+
+
+ThreadCommandQueueImpl::~ThreadCommandQueueImpl()
+{
+    Lock::Locker lock(&QueueLock);
+    OVR_ASSERT(BlockedProducers.IsEmpty());
+    FreeNotifyEvents_NTS();
+}
+
+bool ThreadCommandQueueImpl::PushCommand(const ThreadCommand& command)
+{
+    ThreadCommand::NotifyEvent* completeEvent = 0;
+    ThreadCommand::NotifyEvent* queueAvailableEvent = 0;
+
+    // Repeat  writing command into buffer until it is available.    
+    do {
+
+        { // Lock Scope
+            Lock::Locker lock(&QueueLock);
+
+            if (queueAvailableEvent)
+            {
+                FreeNotifyEvent_NTS(queueAvailableEvent);
+                queueAvailableEvent = 0;
+            }
+
+            // Don't allow any commands after PushExitCommand() is called.
+            if (ExitEnqueued && !command.ExitFlag)
+                return false;
+
+
+            bool   bufferWasEmpty = CommandBuffer.IsEmpty();
+            UByte* buffer = CommandBuffer.Write(command.GetSize());
+            if  (buffer)
+            {
+                ThreadCommand* c = command.CopyConstruct(buffer);
+                if (c->NeedsWait())
+                    completeEvent = c->pEvent = AllocNotifyEvent_NTS();
+                // Signal-waker consumer when we add data to buffer.
+                if (bufferWasEmpty)
+                    pQueue->OnPushNonEmpty_Locked();
+                break;
+            }
+
+            queueAvailableEvent = AllocNotifyEvent_NTS();
+            BlockedProducers.PushBack(queueAvailableEvent);
+        } // Lock Scope
+
+        queueAvailableEvent->Wait();
+
+    } while(1);
+
+    // Command was enqueued, wait if necessary.
+    if (completeEvent)
+    {
+        completeEvent->Wait();
+        Lock::Locker lock(&QueueLock);
+        FreeNotifyEvent_NTS(completeEvent);
+    }
+
+    return true;
+}
+
+
+// Pops the next command from the thread queue, if any is available.
+bool ThreadCommandQueueImpl::PopCommand(ThreadCommand::PopBuffer* popBuffer)
+{    
+    Lock::Locker lock(&QueueLock);
+
+    UByte* buffer = CommandBuffer.ReadBegin();
+    if (!buffer)
+    {
+        // Notify thread while in lock scope, enabling initialization of wait.
+        pQueue->OnPopEmpty_Locked();
+        return false;
+    }
+
+    popBuffer->InitFromBuffer(buffer);
+    CommandBuffer.ReadEnd(popBuffer->GetSize());
+
+    if (!BlockedProducers.IsEmpty())
+    {
+        ThreadCommand::NotifyEvent* queueAvailableEvent = BlockedProducers.GetFirst();
+        queueAvailableEvent->RemoveNode();
+        queueAvailableEvent->PulseEvent();
+        // Event is freed later by waiter.
+    }    
+    return true;
+}
+
+
+//-------------------------------------------------------------------------------------
+
+ThreadCommandQueue::ThreadCommandQueue()
+{
+    pImpl = new ThreadCommandQueueImpl(this);
+}
+ThreadCommandQueue::~ThreadCommandQueue()
+{
+    delete pImpl;
+}
+
+bool ThreadCommandQueue::PushCommand(const ThreadCommand& command)
+{
+    return pImpl->PushCommand(command);
+}
+
+bool ThreadCommandQueue::PopCommand(ThreadCommand::PopBuffer* popBuffer)
+{    
+    return pImpl->PopCommand(popBuffer);
+}
+
+void ThreadCommandQueue::PushExitCommand(bool wait)
+{
+    // Exit is processed in two stages:
+    //  - First, ExitEnqueued flag is set to block further commands from queuing up.
+    //  - Second, the actual exit call is processed on the consumer thread, flushing
+    //    any prior commands.
+    //    IsExiting() only returns true after exit has flushed.
+    {
+        Lock::Locker lock(&pImpl->QueueLock);
+        if (pImpl->ExitEnqueued)
+            return;
+        pImpl->ExitEnqueued = true;
+    }
+
+    PushCommand(ThreadCommandQueueImpl::ExitCommand(pImpl, wait));
+}
+
+bool ThreadCommandQueue::IsExiting() const
+{
+    return pImpl->ExitProcessed;
+}
+
+
+} // namespace OVR
diff --git a/LibOVR/Src/OVR_ThreadCommandQueue.h b/LibOVR/Src/OVR_ThreadCommandQueue.h
new file mode 100644
index 0000000..9774212
--- /dev/null
+++ b/LibOVR/Src/OVR_ThreadCommandQueue.h
@@ -0,0 +1,319 @@
+/************************************************************************************
+
+PublicHeader:   None
+Filename    :   OVR_ThreadCommandQueue.h
+Content     :   Command queue for operations executed on a thread
+Created     :   October 29, 2012
+Author      :   Michael Antonov
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+************************************************************************************/
+
+#ifndef OVR_ThreadCommandQueue_h
+#define OVR_ThreadCommandQueue_h
+
+#include "Kernel/OVR_Types.h"
+#include "Kernel/OVR_List.h"
+#include "Kernel/OVR_Atomic.h"
+#include "Kernel/OVR_Threads.h"
+
+namespace OVR {
+
+class ThreadCommand;
+class ThreadCommandQueue;
+
+
+//-------------------------------------------------------------------------------------
+// ***** ThreadCommand
+
+// ThreadCommand is a base class implementation for commands stored in ThreadCommandQueue.
+class ThreadCommand
+{
+public:    
+
+    // NotifyEvent is used by ThreadCommandQueue::PushCallAndWait to notify the
+    // calling (producer)  thread when command is completed or queue slot is available.
+    class NotifyEvent : public ListNode<NotifyEvent>, public NewOverrideBase
+    {
+        Event E;
+    public:   
+        NotifyEvent() { }
+
+        void Wait()        { E.Wait(); }
+        void PulseEvent()  { E.PulseEvent(); }
+    };
+
+    // ThreadCommand::PopBuffer is temporary storage for a command popped off
+    // by ThreadCommandQueue::PopCommand. 
+    class PopBuffer
+    {
+        enum { MaxSize = 256 };
+
+        UPInt Size;
+        union {            
+            UByte Buffer[MaxSize];
+            UPInt Align;
+        };
+
+        ThreadCommand* toCommand() const { return (ThreadCommand*)Buffer; }
+
+    public:
+        PopBuffer() : Size(0) { }
+        ~PopBuffer();
+
+        void        InitFromBuffer(void* data);
+
+        bool        HasCommand() const  { return Size != 0; }
+        UPInt       GetSize() const     { return Size; }
+        bool        NeedsWait() const   { return toCommand()->NeedsWait(); }
+        NotifyEvent* GetEvent() const   { return toCommand()->pEvent; }
+
+        // Execute the command and also notifies caller to finish waiting,
+        // if necessary.
+        void        Execute();
+    };
+    
+    UInt16       Size;
+    bool         WaitFlag; 
+    bool         ExitFlag; // Marks the last exit command. 
+    NotifyEvent* pEvent;
+
+    ThreadCommand(UPInt size, bool waitFlag, bool exitFlag = false)
+        : Size((UInt16)size), WaitFlag(waitFlag), ExitFlag(exitFlag), pEvent(0) { }
+    virtual ~ThreadCommand() { }
+
+    bool          NeedsWait() const { return WaitFlag; }
+    UPInt         GetSize() const   { return Size; }
+
+    virtual void            Execute() const = 0;
+    // Copy constructor used for serializing this to memory buffer.
+    virtual ThreadCommand*  CopyConstruct(void* p) const = 0;
+};
+
+
+//-------------------------------------------------------------------------------------
+
+// CleanType is a template that strips 'const' and '&' modifiers from the argument type;
+// for example, typename CleanType<A&>::Type is equivalent to A.
+template<class T> struct CleanType           { typedef T Type; };
+template<class T> struct CleanType<T&>       { typedef T Type; };
+template<class T> struct CleanType<const T>  { typedef T Type; };
+template<class T> struct CleanType<const T&> { typedef T Type; };
+
+// SelfType is a template that yields the argument type. This helps avoid conflicts with
+// automatic template argument deduction for function calls when identical argument
+// is already defined.
+template<class T> struct SelfType { typedef T Type; };
+
+
+
+//-------------------------------------------------------------------------------------
+// ThreadCommand specializations for member functions with different number of
+// arguments and argument types.
+
+// Used to return nothing from a ThreadCommand, to avoid problems with 'void'.
+struct Void
+{
+    Void() {}
+    Void(int) {}
+};
+
+// ThreadCommand for member function with 0 arguments.
+template<class C, class R>
+class ThreadCommandMF0 : public ThreadCommand
+{   
+    typedef R (C::*FnPtr)();
+    C*      pClass;
+    FnPtr   pFn;
+    R*      pRet;
+
+    void executeImpl() const
+    {
+        pRet ? (void)(*pRet = (pClass->*pFn)()) :
+	           (void)(pClass->*pFn)();
+    }
+
+public:    
+    ThreadCommandMF0(C* pclass, FnPtr fn, R* ret, bool needsWait)
+        : ThreadCommand(sizeof(ThreadCommandMF0), needsWait),
+          pClass(pclass), pFn(fn), pRet(ret) { }
+
+    virtual void           Execute() const { executeImpl(); }
+    virtual ThreadCommand* CopyConstruct(void* p) const
+    { return Construct<ThreadCommandMF0>(p, *this); }
+};
+
+
+// ThreadCommand for member function with 1 argument.
+template<class C, class R, class A0>
+class ThreadCommandMF1 : public ThreadCommand
+{   
+    typedef R (C::*FnPtr)(A0);
+    C*                           pClass;
+    FnPtr                        pFn;
+    R*                           pRet;
+    typename CleanType<A0>::Type AVal0;
+
+    void executeImpl() const
+    {
+      pRet ? (void)(*pRet = (pClass->*pFn)(AVal0)) :
+	         (void)(pClass->*pFn)(AVal0);
+    }
+
+public:    
+    ThreadCommandMF1(C* pclass, FnPtr fn, R* ret, A0 a0, bool needsWait)
+        : ThreadCommand(sizeof(ThreadCommandMF1), needsWait),
+          pClass(pclass), pFn(fn), pRet(ret), AVal0(a0) { }
+
+    virtual void           Execute() const { executeImpl(); }
+    virtual ThreadCommand* CopyConstruct(void* p) const
+    { return Construct<ThreadCommandMF1>(p, *this); }
+};
+
+// ThreadCommand for member function with 2 arguments.
+template<class C, class R, class A0, class A1>
+class ThreadCommandMF2 : public ThreadCommand
+{   
+    typedef R (C::*FnPtr)(A0, A1);
+    C*                            pClass;
+    FnPtr                         pFn;
+    R*                            pRet;
+    typename CleanType<A0>::Type  AVal0;
+    typename CleanType<A1>::Type  AVal1;
+
+    void executeImpl() const
+    {
+        pRet ? (void)(*pRet = (pClass->*pFn)(AVal0, AVal1)) :
+	           (void)(pClass->*pFn)(AVal0, AVal1);
+    }
+
+public:    
+    ThreadCommandMF2(C* pclass, FnPtr fn, R* ret, A0 a0, A1 a1, bool needsWait)
+        : ThreadCommand(sizeof(ThreadCommandMF2), needsWait),
+          pClass(pclass), pFn(fn), pRet(ret), AVal0(a0), AVal1(a1) { }
+    
+    virtual void           Execute() const { executeImpl(); }
+    virtual ThreadCommand* CopyConstruct(void* p) const 
+    { return Construct<ThreadCommandMF2>(p, *this); }
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** ThreadCommandQueue
+
+// ThreadCommandQueue is a queue of executable function-call commands intended to be
+// serviced by a single consumer thread. Commands are added to the queue with PushCall
+// and removed with PopCall; they are processed in FIFO order. Multiple producer threads
+// are supported and will be blocked if internal data buffer is full.
+
+class ThreadCommandQueue
+{
+public:
+
+    ThreadCommandQueue();
+    virtual ~ThreadCommandQueue();
+
+
+    // Pops the next command from the thread queue, if any is available.
+    // The command should be executed by calling popBuffer->Execute().
+    // Returns 'false' if no command is available at the time of the call.
+    bool PopCommand(ThreadCommand::PopBuffer* popBuffer);
+
+    // Generic implementaion of PushCommand; enqueues a command for execution.
+    // Returns 'false' if push failed, usually indicating thread shutdown.
+    bool PushCommand(const ThreadCommand& command);
+
+    // 
+    void PushExitCommand(bool wait);
+
+    // Returns 'true' once ExitCommand has been processed, so the thread can shut down.
+    bool IsExiting() const;
+
+
+    // These two virtual functions serve as notifications for derived
+    // thread waiting.    
+    virtual void OnPushNonEmpty_Locked() { }
+    virtual void OnPopEmpty_Locked()     { }
+
+
+    // *** PushCall with no result
+    
+    // Enqueue a member function of 'this' class to be called on consumer thread.
+    // By default the function returns immediately; set 'wait' argument to 'true' to
+    // wait for completion.
+    template<class C, class R>
+    bool PushCall(R (C::*fn)(), bool wait = false)
+    { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, 0, wait)); }       
+    template<class C, class R, class A0>
+    bool PushCall(R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
+    { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, 0, a0, wait)); }
+    template<class C, class R, class A0, class A1>
+    bool PushCall(R (C::*fn)(A0, A1),
+                  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
+    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, 0, a0, a1, wait)); }
+    // Enqueue a specified member function call of class C.
+    // By default the function returns immediately; set 'wait' argument to 'true' to
+    // wait for completion.
+    template<class C, class R>
+    bool PushCall(C* p, R (C::*fn)(), bool wait = false)
+    { return PushCommand(ThreadCommandMF0<C,R>(p, fn, 0, wait)); }
+    template<class C, class R, class A0>
+    bool PushCall(C* p, R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
+    { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, 0, a0, wait)); }
+    template<class C, class R, class A0, class A1>
+    bool PushCall(C* p, R (C::*fn)(A0, A1),
+                  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
+    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, 0, a0, a1, wait)); }
+    
+    
+    // *** PushCall with Result
+
+    // Enqueue a member function of 'this' class call and wait for call to complete
+    // on consumer thread before returning.
+    template<class C, class R>
+    bool PushCallAndWaitResult(R (C::*fn)(), R* ret)
+    { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, ret, true)); }       
+    template<class C, class R, class A0>
+    bool PushCallAndWaitResult(R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
+    { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, ret, a0, true)); }
+    template<class C, class R, class A0, class A1>
+    bool PushCallAndWaitResult(R (C::*fn)(A0, A1), R* ret,
+                               typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
+    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, ret, a0, a1, true)); }
+    // Enqueue a member function call for class C and wait for the call to complete
+    // on consumer thread before returning.
+    template<class C, class R>
+    bool PushCallAndWaitResult(C* p, R (C::*fn)(), R* ret)
+    { return PushCommand(ThreadCommandMF0<C,R>(p, fn, ret, true)); }
+    template<class C, class R, class A0>
+    bool PushCallAndWaitResult(C* p, R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
+    { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, ret, a0, true)); }
+    template<class C, class R, class A0, class A1>
+    bool PushCallAndWaitResult(C* p, R (C::*fn)(A0, A1), R* ret,
+                               typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
+    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, ret, a0, a1, true)); }
+
+private:
+    class ThreadCommandQueueImpl* pImpl;
+};
+
+
+}
+
+#endif // OVR_ThreadCommandQueue_h
diff --git a/LibOVR/Src/Util/Util_ImageWindow.cpp b/LibOVR/Src/Util/Util_ImageWindow.cpp
new file mode 100644
index 0000000..cb091c7
--- /dev/null
+++ b/LibOVR/Src/Util/Util_ImageWindow.cpp
@@ -0,0 +1,511 @@
+/************************************************************************************
+
+Filename    :   Util_ImageWindow.cpp
+Content     :   An output object for windows that can display raw images for testing
+Created     :   March 13, 2014
+Authors     :   Dean Beeler
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+#include "../../Include/OVR.h"
+
+#include "Util_ImageWindow.h"
+
+#if defined(OVR_OS_WIN32)
+
+#include <Windows.h>
+
+#include "DWrite.h"
+
+typedef HRESULT (WINAPI *D2D1CreateFactoryFn)(
+	_In_      D2D1_FACTORY_TYPE,
+	_In_      REFIID,
+	_In_opt_  const D2D1_FACTORY_OPTIONS*,
+	_Out_     ID2D1Factory **
+	);
+
+typedef HRESULT (WINAPI *DWriteCreateFactoryFn)(
+	_In_   DWRITE_FACTORY_TYPE factoryType,
+	_In_   REFIID iid,
+	_Out_  IUnknown **factory
+	);
+
+
+namespace OVR { namespace Util {
+	
+ID2D1Factory* ImageWindow::pD2DFactory = NULL;
+IDWriteFactory* ImageWindow::pDWriteFactory = NULL;
+ImageWindow* ImageWindow::globalWindow[4];
+int ImageWindow::windowCount = 0;
+
+LRESULT CALLBACK MainWndProc(
+	HWND hwnd,
+	UINT uMsg,
+	WPARAM wParam,
+	LPARAM lParam)
+{
+	switch (uMsg) 
+	{ 
+	case WM_CREATE: 
+		return 0; 
+
+	case WM_PAINT: 
+		{
+			LONG_PTR ptr = GetWindowLongPtr( hwnd, GWLP_USERDATA );
+			if( ptr )
+			{
+				ImageWindow* iw = (ImageWindow*)ptr;
+				iw->OnPaint();
+			}
+		}
+		
+		return 0; 
+
+	case WM_SIZE: 
+		// Set the size and position of the window. 
+		return 0; 
+
+	case WM_DESTROY: 
+		// Clean up window-specific data objects. 
+		return 0; 
+
+		// 
+		// Process other messages. 
+		// 
+
+	default: 
+		return DefWindowProc(hwnd, uMsg, wParam, lParam); 
+	} 
+	//return 0; 
+}
+
+ImageWindow::ImageWindow( uint32_t width, uint32_t height ) :
+	frontBufferMutex( new Mutex() )
+{
+
+	HINSTANCE hInst = LoadLibrary( L"d2d1.dll" );
+	HINSTANCE hInstWrite = LoadLibrary( L"Dwrite.dll" );
+
+	D2D1CreateFactoryFn createFactory = NULL;
+	DWriteCreateFactoryFn writeFactory = NULL;
+
+	if( hInst )
+	{
+		createFactory = (D2D1CreateFactoryFn)GetProcAddress( hInst, "D2D1CreateFactory" );
+	}
+
+	if( hInstWrite )
+	{
+		writeFactory = (DWriteCreateFactoryFn)GetProcAddress( hInstWrite, "DWriteCreateFactory" );
+	}
+
+	globalWindow[windowCount] = this;
+
+	++windowCount;
+
+	if( pD2DFactory == NULL && createFactory && writeFactory )
+	{
+		createFactory( 
+			D2D1_FACTORY_TYPE_MULTI_THREADED,
+			__uuidof(ID2D1Factory),
+			NULL,
+			&pD2DFactory
+			);
+
+		// Create a DirectWrite factory.
+		writeFactory(
+			DWRITE_FACTORY_TYPE_SHARED,
+			__uuidof(pDWriteFactory),
+			reinterpret_cast<IUnknown **>(&pDWriteFactory)
+			);
+
+	}
+
+	resolution = D2D1::SizeU( width, height );
+
+	SetWindowLongPtr( hWindow, GWLP_USERDATA, (LONG_PTR)this );
+
+	pRT = NULL;
+	greyBitmap = NULL;
+	colorBitmap = NULL;
+}
+
+ImageWindow::~ImageWindow()
+{
+	for( int i = 0; i < MaxWindows; ++i )
+	{
+		if( globalWindow[i] == this )
+		{
+			globalWindow[i] = NULL;
+			break;
+		}
+}
+
+	if( greyBitmap )
+		greyBitmap->Release();
+
+	if( colorBitmap )
+		colorBitmap->Release();
+
+	if( pRT )
+		pRT->Release();
+
+	{
+		Mutex::Locker locker( frontBufferMutex  );
+
+		while( frames.GetSize() )
+		{
+			Ptr<Frame> aFrame = frames.PopBack();
+		}
+	}
+
+	delete frontBufferMutex;
+
+	ShowWindow( hWindow, SW_HIDE );
+	DestroyWindow( hWindow );
+}
+
+void ImageWindow::AssociateSurface( void* surface )
+{
+	// Assume an IUnknown
+	IUnknown* unknown = (IUnknown*)surface;
+
+	IDXGISurface *pDxgiSurface = NULL;
+	HRESULT hr = unknown->QueryInterface(&pDxgiSurface);
+	if( hr == S_OK )
+	{
+		D2D1_RENDER_TARGET_PROPERTIES props =
+			D2D1::RenderTargetProperties(
+			D2D1_RENDER_TARGET_TYPE_DEFAULT,
+			D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED),
+			96,
+			96
+			);
+
+
+		pRT = NULL;			
+		ID2D1RenderTarget* tmpTarget;
+
+		hr = pD2DFactory->CreateDxgiSurfaceRenderTarget( pDxgiSurface, &props, &tmpTarget );
+
+		if( hr == S_OK )
+		{
+			DXGI_SURFACE_DESC desc = {0};
+			pDxgiSurface->GetDesc( &desc );
+			int width = desc.Width;
+			int height = desc.Height;
+
+			D2D1_SIZE_U size = D2D1::SizeU( width, height );
+
+			D2D1_PIXEL_FORMAT pixelFormat = D2D1::PixelFormat(
+				DXGI_FORMAT_A8_UNORM,
+				D2D1_ALPHA_MODE_PREMULTIPLIED
+				);
+
+			D2D1_PIXEL_FORMAT colorPixelFormat = D2D1::PixelFormat(
+				DXGI_FORMAT_B8G8R8A8_UNORM,
+				D2D1_ALPHA_MODE_PREMULTIPLIED
+				);
+
+			D2D1_BITMAP_PROPERTIES bitmapProps;
+			bitmapProps.dpiX = 96;
+			bitmapProps.dpiY = 96;
+			bitmapProps.pixelFormat = pixelFormat;
+
+			D2D1_BITMAP_PROPERTIES colorBitmapProps;
+			colorBitmapProps.dpiX = 96;
+			colorBitmapProps.dpiY = 96;
+			colorBitmapProps.pixelFormat = colorPixelFormat;
+
+			HRESULT result = tmpTarget->CreateBitmap( size, bitmapProps, &greyBitmap );
+			if( result != S_OK )
+			{
+				tmpTarget->Release();
+				tmpTarget = NULL;
+			}
+
+			result = tmpTarget->CreateBitmap( size, colorBitmapProps, &colorBitmap );
+			if( result != S_OK )
+			{
+				greyBitmap->Release();
+				greyBitmap = NULL;
+
+				tmpTarget->Release();
+				tmpTarget = NULL;
+			}
+			pRT = tmpTarget;
+		}
+	}
+}
+
+void ImageWindow::Process()
+{
+	if( pRT && greyBitmap )
+	{
+		OnPaint();
+
+		pRT->Flush();
+	}
+}
+
+void ImageWindow::Complete()
+{
+	Mutex::Locker locker( frontBufferMutex  );
+
+	if( frames.IsEmpty() )
+		return;
+
+	if( frames.PeekBack(0)->ready )
+		return;
+
+	Ptr<Frame> frame = frames.PeekBack(0);
+
+	frame->ready = true;
+}
+
+void ImageWindow::OnPaint()
+{
+	Mutex::Locker locker( frontBufferMutex  );
+
+	// Nothing to do
+	if( frames.IsEmpty() )
+		return;
+
+	if( !frames.PeekFront(0)->ready )
+		return;
+
+	Ptr<Frame> currentFrame = frames.PopFront();
+
+	Ptr<Frame> nextFrame = NULL;
+
+	if( !frames.IsEmpty() )
+		nextFrame = frames.PeekFront(0);
+	
+	while( nextFrame && nextFrame->ready )
+	{
+		// Free up the current frame since it's been removed from the deque
+		currentFrame = frames.PopFront();
+
+		if( frames.IsEmpty() )
+			break;
+
+		nextFrame = frames.PeekFront(0);
+	}
+
+	if( currentFrame->imageData )
+		greyBitmap->CopyFromMemory( NULL, currentFrame->imageData, currentFrame->width );
+
+	if( currentFrame->colorImageData )
+		colorBitmap->CopyFromMemory( NULL, currentFrame->colorImageData, currentFrame->colorPitch );
+
+	pRT->BeginDraw();
+
+	pRT->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); 
+
+	pRT->Clear( D2D1::ColorF(D2D1::ColorF::Black) );
+
+	// This will mirror our image
+	D2D1_MATRIX_3X2_F m;
+	m._11 = -1; m._12 = 0;
+	m._21 = 0; m._22 = 1;
+	m._31 = 0; m._32 = 0;
+	pRT->SetTransform( m );
+
+	ID2D1SolidColorBrush* whiteBrush;
+
+	pRT->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::White, 1.0f), &whiteBrush );
+
+	if( currentFrame->imageData )
+	{
+		pRT->FillOpacityMask( greyBitmap, whiteBrush, 
+			D2D1_OPACITY_MASK_CONTENT_TEXT_NATURAL, 
+			D2D1::RectF( -(FLOAT)resolution.width, 0.0f, (FLOAT)0.0f, (FLOAT)resolution.height ), 
+			//D2D1::RectF( 0.0f, 0.0f, (FLOAT)0.0f, (FLOAT)resolution.height ), 
+			D2D1::RectF( 0.0f, 0.0f, (FLOAT)resolution.width, (FLOAT)resolution.height ) );
+	}
+	else if( currentFrame->colorImageData )
+	{
+		pRT->DrawBitmap( colorBitmap,
+			D2D1::RectF( -(FLOAT)resolution.width, 0.0f, (FLOAT)0.0f, (FLOAT)resolution.height ) );
+
+	}
+
+	pRT->SetTransform(D2D1::Matrix3x2F::Identity());
+
+	whiteBrush->Release();
+
+	Array<CirclePlot>::Iterator it;
+
+	for( it = currentFrame->plots.Begin(); it != currentFrame->plots.End(); ++it )
+	{
+		ID2D1SolidColorBrush* aBrush;
+
+		pRT->CreateSolidColorBrush( D2D1::ColorF( it->r, it->g, it->b), &aBrush );
+
+		D2D1_ELLIPSE ellipse;
+		ellipse.point.x = it->x;
+		ellipse.point.y = it->y;
+		ellipse.radiusX = it->radius;
+		ellipse.radiusY = it->radius;
+
+		if( it->fill )
+			pRT->FillEllipse( &ellipse, aBrush );
+		else
+			pRT->DrawEllipse( &ellipse, aBrush );
+
+		aBrush->Release();
+	}
+
+	static const WCHAR msc_fontName[] = L"Verdana";
+	static const FLOAT msc_fontSize = 20;
+
+	IDWriteTextFormat* textFormat = NULL;
+
+	// Create a DirectWrite text format object.
+	pDWriteFactory->CreateTextFormat(
+		msc_fontName,
+		NULL,
+		DWRITE_FONT_WEIGHT_NORMAL,
+		DWRITE_FONT_STYLE_NORMAL,
+		DWRITE_FONT_STRETCH_NORMAL,
+		msc_fontSize,
+		L"", //locale
+		&textFormat
+		);
+
+	D2D1_SIZE_F renderTargetSize = pRT->GetSize();
+
+	Array<TextPlot>::Iterator textIt;
+	for( textIt = currentFrame->textLines.Begin(); textIt != currentFrame->textLines.End(); ++textIt )
+	{
+		ID2D1SolidColorBrush* aBrush;
+
+		pRT->CreateSolidColorBrush( D2D1::ColorF( textIt->r, textIt->g, textIt->b), &aBrush );
+
+		WCHAR* tmpString = (WCHAR*)calloc( textIt->text.GetLength(),  sizeof( WCHAR ) );
+		for( unsigned i = 0; i < textIt->text.GetLength(); ++i )
+		{
+			tmpString[i] = (WCHAR)textIt->text.GetCharAt( i );
+		}
+					
+		pRT->DrawTextW( tmpString, (UINT32)textIt->text.GetLength(), textFormat,
+			D2D1::RectF(textIt->x, textIt->y, renderTargetSize.width, renderTargetSize.height), aBrush );
+
+		free( tmpString );
+
+		aBrush->Release();
+	}
+
+	if( textFormat )
+		textFormat->Release();
+
+	pRT->EndDraw();
+
+	pRT->Flush();
+}
+
+Ptr<Frame> ImageWindow::lastUnreadyFrame()
+{
+	static int framenumber = 0;
+
+	if( frames.GetSize() && !frames.PeekBack( 0 )->ready )
+		return frames.PeekBack( 0 );
+
+	// Create a new frame if an unready one doesn't already exist
+	Ptr<Frame> tmpFrame = *new Frame( framenumber );
+	frames.PushBack( tmpFrame );
+
+	++framenumber;
+
+	return tmpFrame;
+}
+
+void ImageWindow::UpdateImageBW( const uint8_t* imageData, uint32_t width, uint32_t height )
+{
+	if( pRT && greyBitmap )
+	{
+		Mutex::Locker locker( frontBufferMutex );
+
+		Ptr<Frame> frame = lastUnreadyFrame();
+		frame->imageData = malloc( width * height );
+		frame->width = width;
+		frame->height = height;
+		memcpy( frame->imageData, imageData, width * height );
+	}
+}
+
+void ImageWindow::UpdateImageRGBA( const uint8_t* imageData, uint32_t width, uint32_t height, uint32_t pitch )
+{
+	if( pRT && colorBitmap )
+	{
+		Mutex::Locker locker( frontBufferMutex );
+
+		Ptr<Frame> frame = lastUnreadyFrame();
+		frame->colorImageData = malloc( pitch * height );
+		frame->width = width;
+		frame->height = height;
+		frame->colorPitch = pitch;
+		memcpy( frame->colorImageData, imageData, pitch * height );
+	}
+}
+
+void ImageWindow::addCircle( float x, float y, float radius, float r, float g, float b, bool fill )
+{
+	if( pRT )
+	{
+		CirclePlot cp;
+
+		cp.x = x;
+		cp.y = y;
+		cp.radius = radius;
+		cp.r = r;
+		cp.g = g;
+		cp.b = b;
+		cp.fill = fill;
+
+		Mutex::Locker locker( frontBufferMutex );
+
+		Ptr<Frame> frame = lastUnreadyFrame();
+		frame->plots.PushBack( cp );
+	}
+
+}
+
+void ImageWindow::addText( float x, float y, float r, float g, float b, OVR::String text )
+{
+	if( pRT )
+	{
+		TextPlot tp;
+
+		tp.x = x;
+		tp.y = y;
+		tp.r = r;
+		tp.g = g;
+		tp.b = b;
+		tp.text = text;
+
+		Mutex::Locker locker( frontBufferMutex );
+		Ptr<Frame> frame = lastUnreadyFrame();
+		frame->textLines.PushBack( tp );
+	}
+}
+
+}}
+
+#endif //defined(OVR_OS_WIN32)
\ No newline at end of file
diff --git a/LibOVR/Src/Util/Util_ImageWindow.h b/LibOVR/Src/Util/Util_ImageWindow.h
new file mode 100644
index 0000000..4b88959
--- /dev/null
+++ b/LibOVR/Src/Util/Util_ImageWindow.h
@@ -0,0 +1,200 @@
+/************************************************************************************
+
+Filename    :   Util_ImageWindow.h
+Content     :   An output object for windows that can display raw images for testing
+Created     :   March 13, 2014
+Authors     :   Dean Beeler
+
+Copyright   :   Copyright 2014 Oculus, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef UTIL_IMAGEWINDOW_H
+#define UTIL_IMAGEWINDOW_H
+
+#if defined(OVR_OS_WIN32)
+#define WIN32_LEAN_AND_MEAN 1
+#include <windows.h>
+#include <d2d1.h>
+#include <dwrite.h>
+#endif
+
+#include "../../Include/OVR.h"
+#include "../Kernel/OVR_Hash.h"
+#include "../Kernel/OVR_Array.h"
+#include "../Kernel/OVR_Threads.h"
+#include "../Kernel/OVR_Deque.h"
+
+#include <stdint.h>
+
+namespace OVR { namespace Util {
+
+	typedef struct 
+	{
+		float x;
+		float y;
+		float radius;
+		float r;
+		float g;
+		float b;
+		bool  fill;
+	} CirclePlot;
+
+	typedef struct  
+	{
+		float x;
+		float y;
+		float r;
+		float g;
+		float b;
+	OVR::String text;
+	} TextPlot;
+
+class Frame : virtual public RefCountBaseV<Frame>
+	{
+public:
+
+	Frame( int frame ) :
+		frameNumber( frame ),
+		imageData( NULL ),
+		colorImageData( NULL ),
+		plots(),
+		textLines(),
+		width( 0 ),
+		height( 0 ),
+		colorPitch( 0 ),
+		ready( false )
+	{
+
+	}
+
+	~Frame()
+	{
+		if( imageData )
+			free( imageData );
+		if( colorImageData )
+			free( colorImageData );
+
+		plots.ClearAndRelease();
+		textLines.ClearAndRelease();
+	}
+
+	int						frameNumber;
+
+		Array<CirclePlot> plots;
+	Array<TextPlot>			textLines;
+		void*			  imageData;
+		void*			  colorImageData;
+		int				  width;
+		int				  height;
+		int				  colorPitch;
+		bool			  ready;
+};
+
+#if defined(OVR_OS_WIN32)
+class ImageWindow
+{
+	HWND hWindow;
+	ID2D1RenderTarget* pRT;
+	D2D1_SIZE_U resolution;
+
+	Mutex*						frontBufferMutex;
+
+	InPlaceMutableDeque< Ptr<Frame> >	frames;
+
+	ID2D1Bitmap*				greyBitmap;
+	ID2D1Bitmap*				colorBitmap;
+    
+public:
+	// constructors
+	ImageWindow();
+	ImageWindow( uint32_t width, uint32_t height );
+	virtual ~ImageWindow();
+
+	void GetResolution( size_t& width, size_t& height ) { width = resolution.width; height = resolution.height; }
+
+	void OnPaint(); // Called by Windows when it receives a WM_PAINT message
+
+	void UpdateImage( const uint8_t* imageData, uint32_t width, uint32_t height ) { UpdateImageBW( imageData, width, height ); }
+	void UpdateImageBW( const uint8_t* imageData, uint32_t width, uint32_t height );
+	void UpdateImageRGBA( const uint8_t* imageData, uint32_t width, uint32_t height, uint32_t pitch );
+	void Complete(); // Called by drawing thread to submit a frame
+
+	void Process(); // Called by rendering thread to do window processing
+
+	void AssociateSurface( void* surface );
+
+	void addCircle( float x , float y, float radius, float r, float g, float b, bool fill );
+	void addText( float x, float y, float r, float g, float b, OVR::String text );
+
+	static ImageWindow*			GlobalWindow( int window ) { return globalWindow[window]; }
+	static int					WindowCount() { return windowCount; }
+
+private:
+
+	Ptr<Frame>					lastUnreadyFrame();
+
+	static const int			MaxWindows = 4;
+	static ImageWindow*			globalWindow[MaxWindows];
+	static int					windowCount;
+	static ID2D1Factory*		pD2DFactory;
+	static IDWriteFactory*		pDWriteFactory;
+};
+
+#else
+
+class ImageWindow
+{
+public:
+	// constructors
+	ImageWindow() {}
+	ImageWindow( uint32_t width, uint32_t height ) { OVR_UNUSED( width ); OVR_UNUSED( height ); }
+	virtual ~ImageWindow() { }
+
+	void GetResolution( size_t& width, size_t& height ) { width = 0; height = 0; }
+
+	void OnPaint() { }
+
+	void UpdateImage( const uint8_t* imageData, uint32_t width, uint32_t height ) { UpdateImageBW( imageData, width, height ); }
+	void UpdateImageBW( const uint8_t* imageData, uint32_t width, uint32_t height ) { }
+	void UpdateImageRGBA( const uint8_t* imageData, uint32_t width, uint32_t height, uint32_t pitch ) { }
+	void Complete() { }
+
+	void Process() { }
+
+	void AssociateSurface( void* surface ) { }
+
+	void addCircle( float x , float y, float radius, float r, float g, float b, bool fill ) { }
+	void addText( float x, float y, float r, float g, float b, OVR::String text ) { }
+
+	static ImageWindow*			GlobalWindow( int window ) { return globalWindow[window]; }
+	static int					WindowCount() { return windowCount; }
+
+private:
+
+	static const int			MaxWindows = 4;
+	static ImageWindow*			globalWindow[4];
+	static int					windowCount;
+};
+
+#endif
+
+}} // namespace OVR::Util
+
+
+#endif
\ No newline at end of file
diff --git a/LibOVR/Src/Util/Util_Interface.cpp b/LibOVR/Src/Util/Util_Interface.cpp
new file mode 100644
index 0000000..d96423c
--- /dev/null
+++ b/LibOVR/Src/Util/Util_Interface.cpp
@@ -0,0 +1,34 @@
+/************************************************************************************
+
+Filename    :   Util_Interface.cpp
+Content     :   Simple interface, utilised by internal demos,
+				with access to wider SDK as needed. 
+				Located in the body of the SDK to ensure updated
+				when new SDK features are added.
+Created     :   February 20, 2014
+Authors     :   Tom Heath
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "Util_Interface.h"
+
+
+
+//Files left in to ease its possible return......
\ No newline at end of file
diff --git a/LibOVR/Src/Util/Util_Interface.h b/LibOVR/Src/Util/Util_Interface.h
new file mode 100644
index 0000000..1bbf638
--- /dev/null
+++ b/LibOVR/Src/Util/Util_Interface.h
@@ -0,0 +1,37 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   Util_Interface.h
+Content     :   Simple interface, utilised by internal demos,
+				with access to wider SDK as needed. 
+				Located in the body of the SDK to ensure updated
+				when new SDK features are added.
+Created     :   February 20, 2014
+Authors     :   Tom Heath
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Util_Interface_h
+#define OVR_Util_Interface_h
+#include "../../Src/OVR_CAPI.h"
+
+//Files left in to ease its possible return......
+
+#endif
diff --git a/LibOVR/Src/Util/Util_LatencyTest.cpp b/LibOVR/Src/Util/Util_LatencyTest.cpp
new file mode 100644
index 0000000..3017c72
--- /dev/null
+++ b/LibOVR/Src/Util/Util_LatencyTest.cpp
@@ -0,0 +1,570 @@
+/************************************************************************************
+
+Filename    :   Util_LatencyTest.cpp
+Content     :   Wraps the lower level LatencyTester interface and adds functionality.
+Created     :   February 14, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "Util_LatencyTest.h"
+
+#include "../Kernel/OVR_Log.h"
+#include "../Kernel/OVR_Timer.h"
+
+namespace OVR { namespace Util {
+
+static const UInt32     TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION = 16*10;
+static const UInt32     TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION = 16*10;
+static const UInt32     TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT = 16*5;
+static const UInt32     TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS = 16*5;
+static const UInt32     DEFAULT_NUMBER_OF_SAMPLES = 10;                 // For both color 1->2 and color 2->1 transitions.
+static const UInt32     INITIAL_SAMPLES_TO_IGNORE = 4;
+static const UInt32     TIMEOUT_WAITING_FOR_TEST_STARTED = 1000;
+static const UInt32     TIMEOUT_WAITING_FOR_COLOR_DETECTED = 4000;
+static const Color      CALIBRATE_BLACK(0, 0, 0);
+static const Color      CALIBRATE_WHITE(255, 255, 255);
+static const Color      COLOR1(0, 0, 0);
+static const Color      COLOR2(255, 255, 255);
+static const Color      SENSOR_DETECT_THRESHOLD(128, 255, 255);
+static const float      BIG_FLOAT = 1000000.0f;
+static const float      SMALL_FLOAT = -1000000.0f;
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTest
+
+LatencyTest::LatencyTest(LatencyTestDevice* device)
+ :  Handler(getThis())
+{
+    if (device != NULL)
+    {
+        SetDevice(device);
+    }
+
+    reset();
+
+    srand(Timer::GetTicksMs());
+}
+
+LatencyTest::~LatencyTest()
+{
+     clearMeasurementResults();
+}
+
+bool LatencyTest::SetDevice(LatencyTestDevice* device)
+{
+
+    if (device != Device)
+    {
+        Handler.RemoveHandlerFromDevices();
+
+        Device = device;
+
+        if (Device != NULL)
+        {
+            Device->AddMessageHandler(&Handler);
+
+            // Set trigger threshold.
+            LatencyTestConfiguration configuration(SENSOR_DETECT_THRESHOLD, false);     // No samples streaming.
+            Device->SetConfiguration(configuration, true);
+
+            // Set display to initial (3 dashes).
+            LatencyTestDisplay ltd(2, 0x40400040);
+            Device->SetDisplay(ltd);
+        }
+    }
+
+    return true;
+}
+
+UInt32 LatencyTest::getRandomComponent(UInt32 range)
+{
+    UInt32 val = rand() % range;
+    return val;
+}
+
+void LatencyTest::BeginTest()
+{
+     if (State == State_WaitingForButton)
+    {
+        // Set color to black and wait a while.
+        RenderColor = CALIBRATE_BLACK;
+
+        State = State_WaitingForSettlePreCalibrationColorBlack;
+        OVR_DEBUG_LOG(("State_WaitingForButton -> State_WaitingForSettlePreCalibrationColorBlack."));
+
+        setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION);
+    }
+}
+
+void LatencyTest::handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage)
+{
+    // For debugging.
+/*  if (msg.Type == Message_LatencyTestSamples)
+    {
+        MessageLatencyTestSamples* pSamples = (MessageLatencyTestSamples*) &msg;
+
+        if (pSamples->Samples.GetSize() > 0)
+        {
+            // Just show the first one for now.
+            Color c = pSamples->Samples[0];
+            OVR_DEBUG_LOG(("%d %d %d", c.R, c.G, c.B));
+        }
+        return;
+    }
+*/
+
+    if (latencyTestMessage == LatencyTest_Timer)
+    {
+        if (!Device)
+        {
+            reset();
+            return;
+        }
+        
+        if (State == State_WaitingForSettlePreCalibrationColorBlack)
+        {
+            // Send calibrate message to device and wait a while.
+            Device->SetCalibrate(CALIBRATE_BLACK);
+
+            State = State_WaitingForSettlePostCalibrationColorBlack;
+            OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorBlack -> State_WaitingForSettlePostCalibrationColorBlack."));
+
+            setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION);
+        }
+        else if (State == State_WaitingForSettlePostCalibrationColorBlack)
+        {
+            // Change color to white and wait a while.
+            RenderColor = CALIBRATE_WHITE;
+
+            State = State_WaitingForSettlePreCalibrationColorWhite;
+            OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorBlack -> State_WaitingForSettlePreCalibrationColorWhite."));
+
+            setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION);
+        }
+        else if (State == State_WaitingForSettlePreCalibrationColorWhite)
+        {
+            // Send calibrate message to device and wait a while.
+            Device->SetCalibrate(CALIBRATE_WHITE);
+
+            State = State_WaitingForSettlePostCalibrationColorWhite;
+            OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorWhite -> State_WaitingForSettlePostCalibrationColorWhite."));
+
+            setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION);
+        }
+        else if (State == State_WaitingForSettlePostCalibrationColorWhite)
+        {
+            // Calibration is done. Switch to color 1 and wait for it to settle.
+            RenderColor = COLOR1;
+
+            State = State_WaitingForSettlePostMeasurement;
+            OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorWhite -> State_WaitingForSettlePostMeasurement."));
+
+            UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS);
+            setTimer(waitTime);
+        }
+        else if (State == State_WaitingForSettlePostMeasurement)
+        {
+            // Prepare for next measurement.
+
+            // Create a new result object.
+            MeasurementResult* pResult = new MeasurementResult();
+            Results.PushBack(pResult);
+
+            State = State_WaitingToTakeMeasurement;
+            OVR_DEBUG_LOG(("State_WaitingForSettlePostMeasurement -> State_WaitingToTakeMeasurement."));
+        }
+        else if (State == State_WaitingForTestStarted)
+        {
+            // We timed out waiting for 'TestStarted'. Abandon this measurement and setup for the next.
+            getActiveResult()->TimedOutWaitingForTestStarted = true;
+
+            State = State_WaitingForSettlePostMeasurement;
+            OVR_DEBUG_LOG(("** Timed out waiting for 'TestStarted'."));
+            OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForSettlePostMeasurement."));
+
+            UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS);
+            setTimer(waitTime);
+        }
+        else if (State == State_WaitingForColorDetected)
+        {
+            // We timed out waiting for 'ColorDetected'. Abandon this measurement and setup for the next.
+            getActiveResult()->TimedOutWaitingForColorDetected = true;
+
+            State = State_WaitingForSettlePostMeasurement;
+            OVR_DEBUG_LOG(("** Timed out waiting for 'ColorDetected'."));
+            OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement."));
+
+            UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS);
+            setTimer(waitTime);
+        }
+    }
+    else if (latencyTestMessage == LatencyTest_ProcessInputs)
+    {
+        if (State == State_WaitingToTakeMeasurement)
+        {
+            if (!Device)
+            {
+                reset();
+                return;
+            }
+            
+            // Send 'StartTest' feature report with opposite target color.
+            if (RenderColor == COLOR1)
+            {
+                RenderColor = COLOR2;
+            }
+            else
+            {
+                RenderColor = COLOR1;
+            }
+
+            getActiveResult()->TargetColor = RenderColor;
+            
+            // Record time so we can determine usb roundtrip time.
+            getActiveResult()->StartTestSeconds = Timer::GetSeconds();
+
+            Device->SetStartTest(RenderColor);
+
+            State = State_WaitingForTestStarted;
+            OVR_DEBUG_LOG(("State_WaitingToTakeMeasurement -> State_WaitingForTestStarted."));
+
+            setTimer(TIMEOUT_WAITING_FOR_TEST_STARTED);
+
+            LatencyTestDisplay ltd(2, 0x40090040);
+            Device->SetDisplay(ltd);
+        }
+    }
+    else if (msg.Type == Message_LatencyTestButton)
+    {
+        BeginTest();
+    }
+    else if (msg.Type == Message_LatencyTestStarted)
+    {
+        if (State == State_WaitingForTestStarted)
+        {
+            clearTimer();
+
+            // Record time so we can determine usb roundtrip time.
+            getActiveResult()->TestStartedSeconds = Timer::GetSeconds();
+            
+            State = State_WaitingForColorDetected;
+            OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForColorDetected."));
+
+            setTimer(TIMEOUT_WAITING_FOR_COLOR_DETECTED);
+        }
+    }
+    else if (msg.Type == Message_LatencyTestColorDetected)
+    {
+        if (State == State_WaitingForColorDetected)
+        {
+            // Record time to detect color.
+            MessageLatencyTestColorDetected* pDetected = (MessageLatencyTestColorDetected*) &msg;
+            UInt16 elapsedTime = pDetected->Elapsed;
+            OVR_DEBUG_LOG(("Time to 'ColorDetected' = %d", elapsedTime));
+            
+            getActiveResult()->DeviceMeasuredElapsedMilliS = elapsedTime;
+
+            if (areResultsComplete())
+            {
+                // We're done.
+                processResults();
+                reset();
+            }
+            else
+            {
+                // Run another measurement.
+                State = State_WaitingForSettlePostMeasurement;
+                OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement."));
+
+                UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS);
+                setTimer(waitTime);
+
+                LatencyTestDisplay ltd(2, 0x40400040);
+                Device->SetDisplay(ltd);
+            }
+        }
+    }
+    else if (msg.Type == Message_DeviceRemoved)
+    {
+        reset();
+    }
+}
+
+LatencyTest::MeasurementResult* LatencyTest::getActiveResult()
+{
+    OVR_ASSERT(!Results.IsEmpty());    
+    return Results.GetLast();
+}
+
+void LatencyTest::setTimer(UInt32 timeMilliS)
+{
+    ActiveTimerMilliS = timeMilliS;
+}
+
+void LatencyTest::clearTimer()
+{
+    ActiveTimerMilliS = 0;
+}
+
+void LatencyTest::reset()
+{
+    clearMeasurementResults();
+    State = State_WaitingForButton;
+
+    HaveOldTime = false;
+    ActiveTimerMilliS = 0;
+}
+
+void LatencyTest::clearMeasurementResults()
+{
+    while(!Results.IsEmpty())
+    {
+        MeasurementResult* pElem = Results.GetFirst();
+        pElem->RemoveNode();
+        delete pElem;
+    }
+}
+
+LatencyTest::LatencyTestHandler::~LatencyTestHandler()
+{
+    RemoveHandlerFromDevices();
+}
+
+void LatencyTest::LatencyTestHandler::OnMessage(const Message& msg)
+{
+    pLatencyTestUtil->handleMessage(msg);
+}
+
+void LatencyTest::ProcessInputs()
+{
+    updateForTimeouts();
+    handleMessage(Message(), LatencyTest_ProcessInputs);
+}
+
+bool LatencyTest::DisplayScreenColor(Color& colorToDisplay)
+{
+    updateForTimeouts();
+
+    if (State == State_WaitingForButton)
+    {
+        return false;
+    }
+
+    colorToDisplay = RenderColor;
+    return true;
+}
+
+const char*	LatencyTest::GetResultsString()
+{
+	if (!ResultsString.IsEmpty() && ReturnedResultString != ResultsString.ToCStr())
+	{
+		ReturnedResultString = ResultsString;
+		return ReturnedResultString.ToCStr();
+	}
+    
+	return NULL;
+}
+
+bool LatencyTest::areResultsComplete()
+{
+    UInt32 initialMeasurements = 0;
+
+    UInt32 measurements1to2 = 0;
+    UInt32 measurements2to1 = 0;
+
+    MeasurementResult* pCurr = Results.GetFirst();
+    while(true)
+    {
+        // Process.
+        if (!pCurr->TimedOutWaitingForTestStarted &&
+            !pCurr->TimedOutWaitingForColorDetected)
+        {
+            initialMeasurements++;
+
+            if (initialMeasurements > INITIAL_SAMPLES_TO_IGNORE)
+            {
+                if (pCurr->TargetColor == COLOR2)
+                {
+                    measurements1to2++;
+                }
+                else
+                {
+                    measurements2to1++;
+                }
+            }
+        }
+
+        if (Results.IsLast(pCurr))
+        {
+            break;
+        }
+        pCurr = Results.GetNext(pCurr);
+    }
+
+    if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES &&
+        measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+void LatencyTest::processResults()
+{
+
+    UInt32 minTime1To2 = UINT_MAX;
+    UInt32 maxTime1To2 = 0;
+    float averageTime1To2 = 0.0f;
+    UInt32 minTime2To1 = UINT_MAX;
+    UInt32 maxTime2To1 = 0;
+    float averageTime2To1 = 0.0f;
+
+    float minUSBTripMilliS = BIG_FLOAT;
+    float maxUSBTripMilliS = SMALL_FLOAT;
+    float averageUSBTripMilliS = 0.0f;
+    UInt32 countUSBTripTime = 0;
+
+    UInt32 measurementsCount = 0;
+    UInt32 measurements1to2 = 0;
+    UInt32 measurements2to1 = 0;
+
+    MeasurementResult* pCurr = Results.GetFirst();
+    UInt32 count = 0;
+    while(true)
+    {
+        count++;
+
+        if (!pCurr->TimedOutWaitingForTestStarted &&
+            !pCurr->TimedOutWaitingForColorDetected)
+        {
+            measurementsCount++;
+
+            if (measurementsCount > INITIAL_SAMPLES_TO_IGNORE)
+            {
+                if (pCurr->TargetColor == COLOR2)
+                {
+                    measurements1to2++;
+
+                    if (measurements1to2 <= DEFAULT_NUMBER_OF_SAMPLES)
+                    {
+                        UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS;
+
+                        minTime1To2 = Alg::Min(elapsed, minTime1To2);
+                        maxTime1To2 = Alg::Max(elapsed, maxTime1To2);
+
+                        averageTime1To2 += (float) elapsed;
+                    }
+                }
+                else
+                {
+                    measurements2to1++;
+
+                    if (measurements2to1 <= DEFAULT_NUMBER_OF_SAMPLES)
+                    {
+                        UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS;
+
+                        minTime2To1 = Alg::Min(elapsed, minTime2To1);
+                        maxTime2To1 = Alg::Max(elapsed, maxTime2To1);
+
+                        averageTime2To1 += (float) elapsed;
+                    }
+                }
+
+                float usbRountripElapsedMilliS = Timer::MsPerSecond * (float) (pCurr->TestStartedSeconds - pCurr->StartTestSeconds);
+                minUSBTripMilliS = Alg::Min(usbRountripElapsedMilliS, minUSBTripMilliS);
+                maxUSBTripMilliS = Alg::Max(usbRountripElapsedMilliS, maxUSBTripMilliS);
+                averageUSBTripMilliS += usbRountripElapsedMilliS;
+                countUSBTripTime++;
+            }
+        }
+
+        if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES &&
+            measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES)
+        {
+            break;
+        }
+
+        if (Results.IsLast(pCurr))
+        {
+            break;
+        }
+        pCurr = Results.GetNext(pCurr);
+    }
+
+    averageTime1To2 /= (float) DEFAULT_NUMBER_OF_SAMPLES;      
+    averageTime2To1 /= (float) DEFAULT_NUMBER_OF_SAMPLES;
+
+    averageUSBTripMilliS /= countUSBTripTime;
+    
+    float finalResult = 0.5f * (averageTime1To2 + averageTime2To1);
+    finalResult += averageUSBTripMilliS;
+
+    ResultsString.Clear();
+    ResultsString.AppendFormat("RESULT=%.1f (add half Tracker period) [b->w %d|%.1f|%d] [w->b %d|%.1f|%d] [usb rndtrp %.1f|%.1f|%.1f] [cnt %d] [tmouts %d]",  
+                finalResult, 
+                minTime1To2, averageTime1To2, maxTime1To2, 
+                minTime2To1, averageTime2To1, maxTime2To1,
+                minUSBTripMilliS, averageUSBTripMilliS, maxUSBTripMilliS,
+                DEFAULT_NUMBER_OF_SAMPLES*2, count - measurementsCount);
+    
+    // Display result on latency tester display.
+    LatencyTestDisplay ltd(1, (int)finalResult);
+    Device->SetDisplay(ltd);
+}
+
+void LatencyTest::updateForTimeouts()
+{
+    if (!HaveOldTime)
+    {
+        HaveOldTime = true;
+        OldTime = Timer::GetTicksMs();
+        return;
+    }
+
+    UInt32 newTime = Timer::GetTicksMs();
+    UInt32 elapsedMilliS = newTime - OldTime;
+    if (newTime < OldTime)
+    {
+        elapsedMilliS = OldTime - newTime;
+        elapsedMilliS = UINT_MAX - elapsedMilliS;
+    }
+    OldTime = newTime;
+
+    elapsedMilliS = Alg::Min(elapsedMilliS, (UInt32) 100);   // Clamp at 100mS in case we're not being called very often.
+
+
+    if (ActiveTimerMilliS == 0)
+    {
+        return;
+    }
+
+    if (elapsedMilliS >= ActiveTimerMilliS)
+    {
+        ActiveTimerMilliS = 0;
+        handleMessage(Message(), LatencyTest_Timer);
+        return;
+    }
+
+    ActiveTimerMilliS -= elapsedMilliS;
+}
+
+}} // namespace OVR::Util
diff --git a/LibOVR/Src/Util/Util_LatencyTest.h b/LibOVR/Src/Util/Util_LatencyTest.h
new file mode 100644
index 0000000..0844603
--- /dev/null
+++ b/LibOVR/Src/Util/Util_LatencyTest.h
@@ -0,0 +1,173 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   Util_LatencyTest.h
+Content     :   Wraps the lower level LatencyTesterDevice and adds functionality.
+Created     :   February 14, 2013
+Authors     :   Lee Cooper
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Util_LatencyTest_h
+#define OVR_Util_LatencyTest_h
+
+#include "../OVR_Device.h"
+
+#include "../Kernel/OVR_String.h"
+#include "../Kernel/OVR_List.h"
+
+namespace OVR { namespace Util {
+
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTest
+//
+// LatencyTest utility class wraps the low level LatencyTestDevice and manages the scheduling
+// of a latency test. A single test is composed of a series of individual latency measurements
+// which are used to derive min, max, and an average latency value.
+//
+// Developers are required to call the following methods:
+//      SetDevice - Sets the LatencyTestDevice to be used for the tests.
+//      ProcessInputs - This should be called at the same place in the code where the game engine
+//                      reads the headset orientation from LibOVR (typically done by calling
+//                      'GetOrientation' on the SensorFusion object). Calling this at the right time
+//                      enables us to measure the same latency that occurs for headset orientation
+//                      changes.
+//      DisplayScreenColor -    The latency tester works by sensing the color of the pixels directly
+//                              beneath it. The color of these pixels can be set by drawing a small
+//                              quad at the end of the rendering stage. The quad should be small
+//                              such that it doesn't significantly impact the rendering of the scene,
+//                              but large enough to be 'seen' by the sensor. See the SDK
+//                              documentation for more information.
+//		GetResultsString -	Call this to get a string containing the most recent results.
+//							If the string has already been gotten then NULL will be returned.
+//							The string pointer will remain valid until the next time this 
+//							method is called.
+//
+
+class LatencyTest : public NewOverrideBase
+{
+public:
+    LatencyTest(LatencyTestDevice* device = NULL);
+    ~LatencyTest();
+    
+    // Set the Latency Tester device that we'll use to send commands to and receive
+    // notification messages from.
+    bool        SetDevice(LatencyTestDevice* device);
+
+    // Returns true if this LatencyTestUtil has a Latency Tester device.
+    bool        HasDevice() const
+    { return Handler.IsHandlerInstalled(); }
+
+    void        ProcessInputs();
+    bool        DisplayScreenColor(Color& colorToDisplay);
+	const char*	GetResultsString();
+
+    bool		IsMeasuringNow() const { return (State != State_WaitingForButton); }
+
+    // Begin test. Equivalent to pressing the button on the latency tester.
+    void BeginTest();
+
+private:
+    LatencyTest* getThis()  { return this; }
+
+    enum LatencyTestMessageType
+    {
+        LatencyTest_None,
+        LatencyTest_Timer,
+        LatencyTest_ProcessInputs,
+    };
+    
+    UInt32 getRandomComponent(UInt32 range);
+    void handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage = LatencyTest_None);
+    void reset();
+    void setTimer(UInt32 timeMilliS);
+    void clearTimer();
+
+    class LatencyTestHandler : public MessageHandler
+    {
+        LatencyTest*    pLatencyTestUtil;
+    public:
+        LatencyTestHandler(LatencyTest* latencyTester) : pLatencyTestUtil(latencyTester) { }
+        ~LatencyTestHandler();
+
+        virtual void OnMessage(const Message& msg);
+    };
+
+    bool areResultsComplete();
+    void processResults();
+    void updateForTimeouts();
+
+    Ptr<LatencyTestDevice>      Device;
+    LatencyTestHandler          Handler;
+
+    enum TesterState
+    {
+        State_WaitingForButton,
+        State_WaitingForSettlePreCalibrationColorBlack,
+        State_WaitingForSettlePostCalibrationColorBlack,
+        State_WaitingForSettlePreCalibrationColorWhite,
+        State_WaitingForSettlePostCalibrationColorWhite,
+        State_WaitingToTakeMeasurement,
+        State_WaitingForTestStarted,
+        State_WaitingForColorDetected,
+        State_WaitingForSettlePostMeasurement
+    };
+    TesterState                 State;
+
+    bool                        HaveOldTime;
+    UInt32                      OldTime;
+    UInt32                      ActiveTimerMilliS;
+
+    Color                       RenderColor;
+
+    struct MeasurementResult : public ListNode<MeasurementResult>, public NewOverrideBase
+    {
+        MeasurementResult()
+         :  DeviceMeasuredElapsedMilliS(0),
+            TimedOutWaitingForTestStarted(false),
+            TimedOutWaitingForColorDetected(false),
+            StartTestSeconds(0.0),
+            TestStartedSeconds(0.0)
+        {}
+
+        Color                   TargetColor;
+
+        UInt32                  DeviceMeasuredElapsedMilliS;
+
+        bool                    TimedOutWaitingForTestStarted;
+        bool                    TimedOutWaitingForColorDetected;
+
+        double                  StartTestSeconds;
+        double                  TestStartedSeconds;
+    };
+
+    List<MeasurementResult>     Results;
+    void clearMeasurementResults();
+
+    MeasurementResult*          getActiveResult();
+
+    StringBuffer			    ResultsString;
+	String					    ReturnedResultString;
+};
+
+}} // namespace OVR::Util
+
+#endif // OVR_Util_LatencyTest_h
diff --git a/LibOVR/Src/Util/Util_LatencyTest2.cpp b/LibOVR/Src/Util/Util_LatencyTest2.cpp
new file mode 100644
index 0000000..6fc8b1f
--- /dev/null
+++ b/LibOVR/Src/Util/Util_LatencyTest2.cpp
@@ -0,0 +1,191 @@
+/************************************************************************************
+
+Filename    :   Util_LatencyTest2.cpp
+Content     :   Wraps the lower level LatencyTester interface for DK2 and adds functionality.
+Created     :   March 10, 2014
+Authors     :   Volga Aksoy
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "Util_LatencyTest2.h"
+
+#include "../OVR_CAPI.h"
+#include "../Kernel/OVR_Log.h"
+#include "../Kernel/OVR_Timer.h"
+
+
+namespace OVR { namespace Util {
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTest2
+
+LatencyTest2::LatencyTest2(SensorDevice* device)
+ :  Handler(getThis())
+ ,  TestActive(false)
+ ,  StartTiming(-1)
+ ,  LatencyMeasuredInSeconds(-1)
+ ,  LastPixelReadMsg(NULL)
+ ,  RenderColorValue(0)
+ ,  NumMsgsBeforeSettle(0)
+ ,  NumTestsSuccessful(0)
+{
+    if (device != NULL)
+    {
+        SetSensorDevice(device);
+    }
+}
+
+LatencyTest2::~LatencyTest2()
+{
+    HmdDevice = NULL;
+    LatencyTesterDev = NULL;
+    
+    Handler.RemoveHandlerFromDevices();
+}
+
+bool LatencyTest2::SetSensorDevice(SensorDevice* device)
+{
+    Lock::Locker devLocker(&TesterLock);
+
+    // Enable/Disable pixel read from HMD
+    if (device != HmdDevice)
+    {
+        Handler.RemoveHandlerFromDevices();
+
+        HmdDevice = device;
+
+        if (HmdDevice != NULL)
+        {
+            HmdDevice->AddMessageHandler(&Handler);
+        }
+    }
+
+    return true;
+}
+
+bool LatencyTest2::SetDisplayDevice(LatencyTestDevice* device)
+{
+    Lock::Locker devLocker(&TesterLock);
+
+    if (device != LatencyTesterDev)
+    {
+        LatencyTesterDev = device;
+        if (LatencyTesterDev != NULL)
+        {
+            // Set display to initial (3 dashes).
+            LatencyTestDisplay ltd(2, 0x40400040);
+            LatencyTesterDev->SetDisplay(ltd);
+        }
+    }
+
+    return true;
+}
+
+void LatencyTest2::BeginTest(double startTime)
+{
+    Lock::Locker devLocker(&TesterLock);
+
+    if (!TestActive)
+    {
+        TestActive = true;
+        NumMsgsBeforeSettle = 0;
+
+        // Go to next pixel value
+        //RenderColorValue = (RenderColorValue == 0) ? 255 : 0;
+        RenderColorValue = (RenderColorValue + LT2_ColorIncrement) % 256;        
+        RawStartTiming   = LastPixelReadMsg.RawSensorTime;
+        
+        if (startTime > 0.0)
+            StartTiming = startTime;
+        else
+            StartTiming = ovr_GetTimeInSeconds();
+          
+    }
+}
+
+void LatencyTest2::handleMessage(const MessagePixelRead& msg)
+{
+    Lock::Locker devLocker(&TesterLock);
+
+    // Hold onto the last message as we will use this when we start a new test
+    LastPixelReadMsg = msg;
+
+    // If color readback index is valid, store it in the lock-less queue.
+    int readbackIndex = 0;
+    if (FrameTimeRecord::ColorToReadbackIndex(&readbackIndex, msg.PixelReadValue))
+    {
+        RecentFrameSet.AddValue(readbackIndex, msg.FrameTimeSeconds);
+        LockessRecords.SetState(RecentFrameSet);
+    }
+
+    NumMsgsBeforeSettle++;
+
+    if (TestActive)
+    {
+        int pixelValueDiff = RenderColorValue - LastPixelReadMsg.PixelReadValue;
+        int rawTimeDiff    = LastPixelReadMsg.RawFrameTime - RawStartTiming;
+
+        if (pixelValueDiff < LT2_PixelTestThreshold && pixelValueDiff > -LT2_PixelTestThreshold)
+        {
+            TestActive = false;
+
+            LatencyMeasuredInSeconds = LastPixelReadMsg.FrameTimeSeconds - StartTiming;
+            RawLatencyMeasured       = rawTimeDiff;
+            //LatencyMeasuredInSeconds = RawLatencyMeasured / 1000000.0;
+
+            if(LatencyTesterDev && (NumTestsSuccessful % 5) == 0)
+            {
+                int displayNum = (int)(RawLatencyMeasured / 100.0);
+                //int displayNum = NumMsgsBeforeSettle;
+                //int displayNum = (int)(LatencyMeasuredInSeconds * 1000.0);
+                LatencyTestDisplay ltd(1, displayNum);
+                LatencyTesterDev->SetDisplay(ltd);
+            }
+
+            NumTestsSuccessful++;
+        }
+        else if (TestActive && (rawTimeDiff / 1000) > LT2_TimeoutWaitingForColorDetected)
+        {
+            TestActive = false;
+            LatencyMeasuredInSeconds = -1;
+        }
+    }
+}
+
+LatencyTest2::PixelReadHandler::~PixelReadHandler()
+{
+    RemoveHandlerFromDevices();
+}
+
+void LatencyTest2::PixelReadHandler::OnMessage(const Message& msg)
+{
+    if(msg.Type == Message_PixelRead)
+        pLatencyTestUtil->handleMessage(static_cast<const MessagePixelRead&>(msg));
+}
+
+bool LatencyTest2::DisplayScreenColor(Color& colorToDisplay)
+{
+    Lock::Locker devLocker(&TesterLock);
+    colorToDisplay = Color(RenderColorValue, RenderColorValue, RenderColorValue, 255);
+
+    return TestActive;
+}
+
+}} // namespace OVR::Util
diff --git a/LibOVR/Src/Util/Util_LatencyTest2.h b/LibOVR/Src/Util/Util_LatencyTest2.h
new file mode 100644
index 0000000..61e8477
--- /dev/null
+++ b/LibOVR/Src/Util/Util_LatencyTest2.h
@@ -0,0 +1,238 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   Util_LatencyTest2.h
+Content     :   Wraps the lower level LatencyTester interface for DK2 and adds functionality.
+Created     :   March 10, 2014
+Authors     :   Volga Aksoy
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Util_LatencyTest2_h
+#define OVR_Util_LatencyTest2_h
+
+#include "../OVR_Device.h"
+
+#include "../Kernel/OVR_String.h"
+#include "../Kernel/OVR_List.h"
+#include "../Kernel/OVR_Lockless.h"
+
+namespace OVR { namespace Util {
+
+
+enum {
+    LT2_ColorIncrement                  = 32,
+    LT2_PixelTestThreshold              = LT2_ColorIncrement / 3,
+    LT2_IncrementCount                  = 256 / LT2_ColorIncrement,
+    LT2_TimeoutWaitingForColorDetected  = 1000  // 1 second
+};
+
+//-------------------------------------------------------------------------------------
+
+// Describes frame scanout time used for latency testing.
+struct FrameTimeRecord
+{
+    int    ReadbackIndex;
+    double TimeSeconds;
+
+    // Utility functions to convert color to readBack indices and back.
+    // The purpose of ReadbackIndex is to allow direct comparison by value.
+
+    static bool ColorToReadbackIndex(int *readbackIndex, unsigned char color)
+    {
+        int compareColor = color - LT2_ColorIncrement/2;
+        int index        = color / LT2_ColorIncrement;  // Use color without subtraction due to rounding.
+        int delta        = compareColor - index * LT2_ColorIncrement;
+
+        if ((delta < LT2_PixelTestThreshold) && (delta > -LT2_PixelTestThreshold))
+        {
+            *readbackIndex = index;
+            return true;
+        }
+        return false;
+    }
+
+    static unsigned char ReadbackIndexToColor(int readbackIndex)
+    {
+        OVR_ASSERT(readbackIndex < LT2_IncrementCount);
+        return (unsigned char)(readbackIndex * LT2_ColorIncrement + LT2_ColorIncrement/2);
+    }
+};
+
+// FrameTimeRecordSet is a container holding multiple consecutive frame timing records
+// returned from the lock-less state. Used by FrameTimeManager. 
+
+struct FrameTimeRecordSet
+{
+    enum {
+        RecordCount = 4,
+        RecordMask  = RecordCount - 1
+    };
+    FrameTimeRecord Records[RecordCount];    
+    int             NextWriteIndex;
+
+    FrameTimeRecordSet()
+    {
+        NextWriteIndex = 0;
+        memset(this, 0, sizeof(FrameTimeRecordSet));
+    }
+
+    void AddValue(int readValue, double timeSeconds)
+    {        
+        Records[NextWriteIndex].ReadbackIndex = readValue;
+        Records[NextWriteIndex].TimeSeconds   = timeSeconds;
+        NextWriteIndex ++;
+        if (NextWriteIndex == RecordCount)
+            NextWriteIndex = 0;
+    }
+    // Matching should be done starting from NextWrite index 
+    // until wrap-around
+
+    const FrameTimeRecord& operator [] (int i) const
+    {
+        return Records[(NextWriteIndex + i) & RecordMask];
+    }
+
+    const FrameTimeRecord& GetMostRecentFrame()
+    {
+        return Records[(NextWriteIndex - 1) & RecordMask];
+    }
+
+    // Advances I to  absolute color index
+    bool FindReadbackIndex(int* i, int readbackIndex) const
+    {
+        for (; *i < RecordCount; (*i)++)
+        {
+            if ((*this)[*i].ReadbackIndex == readbackIndex)
+                return true;
+        }
+        return false;
+    }
+
+    bool IsAllZeroes() const
+    {
+        for (int i = 0; i < RecordCount; i++)
+            if (Records[i].ReadbackIndex != 0)
+                return false;
+        return true;
+    }
+};
+
+
+//-------------------------------------------------------------------------------------
+// ***** LatencyTest2
+//
+// LatencyTest2 utility class wraps the low level SensorDevice and manages the scheduling
+// of a latency test. A single test is composed of a series of individual latency measurements
+// which are used to derive min, max, and an average latency value.
+//
+// Developers are required to call the following methods:
+//      SetDevice - Sets the SensorDevice to be used for the tests.
+//      ProcessInputs - This should be called at the same place in the code where the game engine
+//                      reads the headset orientation from LibOVR (typically done by calling
+//                      'GetOrientation' on the SensorFusion object). Calling this at the right time
+//                      enables us to measure the same latency that occurs for headset orientation
+//                      changes.
+//      DisplayScreenColor -    The latency tester works by sensing the color of the pixels directly
+//                              beneath it. The color of these pixels can be set by drawing a small
+//                              quad at the end of the rendering stage. The quad should be small
+//                              such that it doesn't significantly impact the rendering of the scene,
+//                              but large enough to be 'seen' by the sensor. See the SDK
+//                              documentation for more information.
+//		GetResultsString -	Call this to get a string containing the most recent results.
+//							If the string has already been gotten then NULL will be returned.
+//							The string pointer will remain valid until the next time this 
+//							method is called.
+//
+
+class LatencyTest2 : public NewOverrideBase
+{
+public:
+    LatencyTest2(SensorDevice* device = NULL);
+    ~LatencyTest2();
+    
+    // Set the Latency Tester device that we'll use to send commands to and receive
+    // notification messages from.
+    bool        SetSensorDevice(SensorDevice* device);
+    bool        SetDisplayDevice(LatencyTestDevice* device);
+
+    // Returns true if this LatencyTestUtil has a Latency Tester device.
+    bool        HasDisplayDevice() const { return LatencyTesterDev.GetPtr() != NULL; }
+    bool        HasDevice() const        { return Handler.IsHandlerInstalled(); }
+
+    bool        DisplayScreenColor(Color& colorToDisplay);
+	//const char*	GetResultsString();
+
+    // Begin test. Equivalent to pressing the button on the latency tester.
+    void        BeginTest(double startTime = -1.0f);
+    bool		IsMeasuringNow() const { return TestActive; }
+    double      GetMeasuredLatency() const { return LatencyMeasuredInSeconds; }
+
+//
+    FrameTimeRecordSet GetLocklessState() { return LockessRecords.GetState(); }
+
+private:
+    LatencyTest2* getThis()  { return this; }
+
+    enum LatencyTestMessageType
+    {
+        LatencyTest_None,
+        LatencyTest_Timer,
+        LatencyTest_ProcessInputs,
+    };
+    
+    void handleMessage(const MessagePixelRead& msg);
+
+    class PixelReadHandler : public MessageHandler
+    {
+        LatencyTest2*    pLatencyTestUtil;
+    public:
+        PixelReadHandler(LatencyTest2* latencyTester) : pLatencyTestUtil(latencyTester) { }
+        ~PixelReadHandler();
+
+        virtual void OnMessage(const Message& msg);
+    };
+    PixelReadHandler            Handler;
+    
+    Ptr<SensorDevice>           HmdDevice;
+    Ptr<LatencyTestDevice>      LatencyTesterDev;
+    
+    Lock                        TesterLock;
+    bool                        TestActive;
+    unsigned char               RenderColorValue;
+    MessagePixelRead            LastPixelReadMsg;
+    double                      StartTiming;
+    unsigned int                RawStartTiming;
+    UInt32                      RawLatencyMeasured;
+    double                      LatencyMeasuredInSeconds;
+    int                         NumMsgsBeforeSettle;
+    unsigned int                NumTestsSuccessful;
+
+    // MA:
+    // Frames are added here, then copied into lockess state
+    FrameTimeRecordSet                  RecentFrameSet;
+    LocklessUpdater<FrameTimeRecordSet> LockessRecords;
+};
+
+
+
+}} // namespace OVR::Util
+
+#endif // OVR_Util_LatencyTest2_h
diff --git a/LibOVR/Src/Util/Util_Render_Stereo.cpp b/LibOVR/Src/Util/Util_Render_Stereo.cpp
new file mode 100644
index 0000000..e84381e
--- /dev/null
+++ b/LibOVR/Src/Util/Util_Render_Stereo.cpp
@@ -0,0 +1,1472 @@
+/************************************************************************************
+
+Filename    :   Util_Render_Stereo.cpp
+Content     :   Stereo rendering configuration implementation
+Created     :   October 22, 2012
+Authors     :   Michael Antonov, Andrew Reisse, Tom Forsyth
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#include "Util_Render_Stereo.h"
+#include "../OVR_SensorFusion.h"
+
+namespace OVR { namespace Util { namespace Render {
+
+
+//-----------------------------------------------------------------------------------
+// **** Useful debug functions.
+
+char const* GetDebugNameEyeCupType ( EyeCupType eyeCupType )
+{
+    switch ( eyeCupType )
+    {
+    case EyeCup_DK1A:           return "DK1 A";             break;
+    case EyeCup_DK1B:           return "DK1 B";             break;
+    case EyeCup_DK1C:           return "DK1 C";             break;
+    case EyeCup_DKHD2A:         return "DKHD2 A";           break;
+    case EyeCup_OrangeA:        return "Orange A";          break;
+    case EyeCup_RedA:           return "Red A";             break;
+    case EyeCup_PinkA:          return "Pink A";            break;
+    case EyeCup_BlueA:          return "Blue A";            break;
+    case EyeCup_Delilah1A:      return "Delilah 1 A";       break;
+    case EyeCup_Delilah2A:      return "Delilah 2 A";       break;
+    case EyeCup_JamesA:         return "James A";           break;
+    case EyeCup_SunMandalaA:    return "Sun Mandala A";     break;
+    case EyeCup_DK2A:           return "DK2 A";             break;
+    case EyeCup_LAST:           return "LAST";              break;
+    default: OVR_ASSERT ( false ); return "Error"; break;
+    }
+}
+
+char const* GetDebugNameHmdType ( HmdTypeEnum hmdType )
+{
+    switch ( hmdType )
+    {
+    case HmdType_None:              return "None";                   break;
+    case HmdType_DK1:               return "DK1";                    break;
+    case HmdType_DKProto:           return "DK1 prototype";          break;
+    case HmdType_DKHDProto:         return "DK HD prototype 1";      break;
+    case HmdType_DKHDProto566Mi:    return "DK HD prototype 566 Mi"; break;
+    case HmdType_DKHD2Proto:        return "DK HD prototype 585";    break;
+    case HmdType_CrystalCoveProto:  return "Crystal Cove";           break;
+    case HmdType_DK2:               return "DK2";                    break;
+    case HmdType_Unknown:           return "Unknown";                break;
+    case HmdType_LAST:              return "LAST";                   break;
+    default: OVR_ASSERT ( false ); return "Error"; break;
+    }
+}
+
+
+//-----------------------------------------------------------------------------------
+// **** Internal pipeline functions.
+
+struct DistortionAndFov
+{
+    DistortionRenderDesc    Distortion;
+    FovPort                 Fov; 
+};
+
+static DistortionAndFov CalculateDistortionAndFovInternal ( StereoEye eyeType, HmdRenderInfo const &hmd,
+                                                            LensConfig const *pLensOverride = NULL,
+                                                            FovPort const *pTanHalfFovOverride = NULL,
+                                                            float extraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION )
+{
+    // pLensOverride can be NULL, which means no override.
+
+    DistortionRenderDesc localDistortion  = CalculateDistortionRenderDesc ( eyeType, hmd, pLensOverride );
+    FovPort              fov              = CalculateFovFromHmdInfo ( eyeType, localDistortion, hmd, extraEyeRotationInRadians );
+    // Here the app or the user would optionally clamp this visible fov to a smaller number if
+    // they want more perf or resolution and are willing to give up FOV.
+    // They may also choose to clamp UDLR differently e.g. to get cinemascope-style views.
+    if ( pTanHalfFovOverride != NULL )
+    {
+        fov = *pTanHalfFovOverride;
+    }
+
+    // Here we could call ClampToPhysicalScreenFov(), but we do want people
+    // to be able to play with larger-than-screen views.
+    // The calling app can always do the clamping itself.
+    DistortionAndFov result;
+    result.Distortion = localDistortion;
+    result.Fov        = fov;
+
+    return result;
+}
+
+
+static Recti CalculateViewportInternal ( StereoEye eyeType,
+                                            Sizei const actualRendertargetSurfaceSize,
+                                            Sizei const requestedRenderedPixelSize,
+                                            bool bRendertargetSharedByBothEyes,
+                                            bool bMonoRenderingMode = false )
+{
+    Recti renderedViewport;
+    if ( bMonoRenderingMode || !bRendertargetSharedByBothEyes || (eyeType == StereoEye_Center) )
+    {
+        // One eye per RT.
+        renderedViewport.x = 0;
+        renderedViewport.y = 0;
+        renderedViewport.w = Alg::Min ( actualRendertargetSurfaceSize.w, requestedRenderedPixelSize.w );
+        renderedViewport.h = Alg::Min ( actualRendertargetSurfaceSize.h, requestedRenderedPixelSize.h );
+    }
+    else
+    {
+        // Both eyes share the RT.
+        renderedViewport.x = 0;
+        renderedViewport.y = 0;
+        renderedViewport.w = Alg::Min ( actualRendertargetSurfaceSize.w/2, requestedRenderedPixelSize.w );
+        renderedViewport.h = Alg::Min ( actualRendertargetSurfaceSize.h,  requestedRenderedPixelSize.h );
+        if ( eyeType == StereoEye_Right )
+        {
+            renderedViewport.x = (actualRendertargetSurfaceSize.w+1)/2;      // Round up, not down.
+        }
+    }
+    return renderedViewport;
+}
+
+static Recti CalculateViewportDensityInternal ( StereoEye eyeType,
+                                                   DistortionRenderDesc const &distortion,
+                                                   FovPort const &fov,
+                                                   Sizei const &actualRendertargetSurfaceSize,
+                                                   bool bRendertargetSharedByBothEyes,
+                                                   float desiredPixelDensity = 1.0f,
+                                                   bool bMonoRenderingMode = false )
+{
+    OVR_ASSERT ( actualRendertargetSurfaceSize.w > 0 );
+    OVR_ASSERT ( actualRendertargetSurfaceSize.h > 0 );
+
+    // What size RT do we need to get 1:1 mapping?
+    Sizei idealPixelSize = CalculateIdealPixelSize ( eyeType, distortion, fov, desiredPixelDensity );
+    // ...but we might not actually get that size.
+    return CalculateViewportInternal ( eyeType,
+                                       actualRendertargetSurfaceSize,
+                                       idealPixelSize,
+                                       bRendertargetSharedByBothEyes, bMonoRenderingMode );
+}
+
+static ViewportScaleAndOffset CalculateViewportScaleAndOffsetInternal (
+                                                          ScaleAndOffset2D const &eyeToSourceNDC,
+                                                          Recti const &renderedViewport,
+                                                          Sizei const &actualRendertargetSurfaceSize )
+{
+    ViewportScaleAndOffset result;
+    result.RenderedViewport = renderedViewport;
+    result.EyeToSourceUV = CreateUVScaleAndOffsetfromNDCScaleandOffset(
+                                            eyeToSourceNDC, renderedViewport, actualRendertargetSurfaceSize );
+    return result;
+}
+
+
+static StereoEyeParams CalculateStereoEyeParamsInternal ( StereoEye eyeType, HmdRenderInfo const &hmd,
+                                                          DistortionRenderDesc const &distortion,
+                                                          FovPort const &fov,
+                                                          Sizei const &actualRendertargetSurfaceSize,
+                                                          Recti const &renderedViewport,
+                                                          bool bRightHanded = true, float zNear = 0.01f, float zFar = 10000.0f,
+                                                          bool bMonoRenderingMode = false,
+                                                          float zoomFactor = 1.0f )
+{
+    // Generate the projection matrix for intermediate rendertarget.
+    // Z range can also be inserted later by the app (though not in this particular case)
+    float fovScale = 1.0f / zoomFactor;
+    FovPort zoomedFov = fov;
+    zoomedFov.LeftTan  *= fovScale;
+    zoomedFov.RightTan *= fovScale;
+    zoomedFov.UpTan    *= fovScale;
+    zoomedFov.DownTan  *= fovScale;
+    Matrix4f projection = CreateProjection ( bRightHanded, zoomedFov, zNear, zFar );
+
+    // Find the mapping from TanAngle space to target NDC space.
+    // Note this does NOT take the zoom factor into account because
+    // this is the mapping of actual physical eye FOV (and our eyes do not zoom!)
+    // to screen space.
+    ScaleAndOffset2D eyeToSourceNDC = CreateNDCScaleAndOffsetFromFov ( fov );
+    
+    // The size of the final FB, which is fixed and determined by the physical size of the device display.
+    Recti distortedViewport   = GetFramebufferViewport ( eyeType, hmd );
+    Vector3f virtualCameraOffset = CalculateEyeVirtualCameraOffset(hmd, eyeType, bMonoRenderingMode);
+
+    StereoEyeParams result;
+    result.Eye                  = eyeType;
+    result.ViewAdjust           = Matrix4f::Translation(virtualCameraOffset);
+    result.Distortion           = distortion;
+    result.DistortionViewport   = distortedViewport;
+    result.Fov                  = fov;
+    result.RenderedProjection   = projection;
+    result.EyeToSourceNDC       = eyeToSourceNDC;
+    ViewportScaleAndOffset vsao = CalculateViewportScaleAndOffsetInternal ( eyeToSourceNDC, renderedViewport, actualRendertargetSurfaceSize );
+    result.RenderedViewport     = vsao.RenderedViewport;
+    result.EyeToSourceUV        = vsao.EyeToSourceUV;
+
+    return result;
+}
+
+
+Vector3f CalculateEyeVirtualCameraOffset(HmdRenderInfo const &hmd,
+                                         StereoEye eyeType, bool bmonoRenderingMode)
+{
+    Vector3f virtualCameraOffset(0);
+
+    if (!bmonoRenderingMode)
+    {
+        float eyeCenterRelief = hmd.GetEyeCenter().ReliefInMeters;
+
+        if (eyeType == StereoEye_Left)
+        {
+            virtualCameraOffset.x = hmd.EyeLeft.NoseToPupilInMeters;
+            virtualCameraOffset.z = eyeCenterRelief - hmd.EyeLeft.ReliefInMeters;
+        }
+        else if (eyeType == StereoEye_Right)
+        {
+            virtualCameraOffset.x = -hmd.EyeRight.NoseToPupilInMeters;
+            virtualCameraOffset.z = eyeCenterRelief - hmd.EyeRight.ReliefInMeters;
+        }
+    }
+
+    return virtualCameraOffset;
+}
+
+
+//-----------------------------------------------------------------------------------
+// **** Higher-level utility functions.
+
+Sizei CalculateRecommendedTextureSize ( HmdRenderInfo const &hmd,
+                                        bool bRendertargetSharedByBothEyes,
+                                        float pixelDensityInCenter /*= 1.0f*/ )
+{
+    Sizei idealPixelSize[2];
+    for ( int eyeNum = 0; eyeNum < 2; eyeNum++ )
+    {
+        StereoEye eyeType = ( eyeNum == 0 ) ? StereoEye_Left : StereoEye_Right;
+
+        DistortionAndFov distortionAndFov = CalculateDistortionAndFovInternal ( eyeType, hmd, NULL, NULL, OVR_DEFAULT_EXTRA_EYE_ROTATION );
+
+        idealPixelSize[eyeNum] = CalculateIdealPixelSize ( eyeType,
+                                        distortionAndFov.Distortion,
+                                        distortionAndFov.Fov,
+                                        pixelDensityInCenter );
+    }
+
+    Sizei result;
+    result.w = Alg::Max ( idealPixelSize[0].w, idealPixelSize[1].w );
+    result.h = Alg::Max ( idealPixelSize[0].h, idealPixelSize[1].h );
+    if ( bRendertargetSharedByBothEyes )
+    {
+        result.w *= 2;
+    }
+    return result;
+}
+
+StereoEyeParams CalculateStereoEyeParams ( HmdRenderInfo const &hmd,
+                                           StereoEye eyeType,
+                                           Sizei const &actualRendertargetSurfaceSize,
+                                           bool bRendertargetSharedByBothEyes,
+                                           bool bRightHanded /*= true*/,
+                                           float zNear /*= 0.01f*/, float zFar /*= 10000.0f*/,
+										   Sizei const *pOverrideRenderedPixelSize /* = NULL*/,
+                                           FovPort const *pOverrideFovport /*= NULL*/,
+                                           float zoomFactor /*= 1.0f*/ )
+{
+    DistortionAndFov distortionAndFov = CalculateDistortionAndFovInternal ( eyeType, hmd, NULL, NULL, OVR_DEFAULT_EXTRA_EYE_ROTATION );
+    if ( pOverrideFovport != NULL )
+    {
+        distortionAndFov.Fov = *pOverrideFovport;
+    }
+
+    Recti viewport;
+    if ( pOverrideRenderedPixelSize != NULL )
+    {
+        viewport = CalculateViewportInternal ( eyeType, actualRendertargetSurfaceSize, *pOverrideRenderedPixelSize, bRendertargetSharedByBothEyes, false );
+    }
+    else
+    {
+        viewport = CalculateViewportDensityInternal ( eyeType,
+                                                      distortionAndFov.Distortion,
+                                                      distortionAndFov.Fov,
+                                                      actualRendertargetSurfaceSize, bRendertargetSharedByBothEyes, 1.0f, false );
+    }
+
+    return CalculateStereoEyeParamsInternal (
+                                eyeType, hmd,
+                                distortionAndFov.Distortion,
+                                distortionAndFov.Fov,
+                                actualRendertargetSurfaceSize, viewport,
+                                bRightHanded, zNear, zFar, false, zoomFactor );
+}
+
+
+FovPort CalculateRecommendedFov ( HmdRenderInfo const &hmd,
+                                  StereoEye eyeType,
+                                  bool bMakeFovSymmetrical /* = false */ )
+{
+    DistortionAndFov distortionAndFov = CalculateDistortionAndFovInternal ( eyeType, hmd, NULL, NULL, OVR_DEFAULT_EXTRA_EYE_ROTATION );
+    FovPort fov = distortionAndFov.Fov;
+    if ( bMakeFovSymmetrical )
+    {
+        // Deal with engines that cannot support an off-center projection.
+        // Unfortunately this means they will be rendering pixels that the user can't actually see.
+        float fovTanH = Alg::Max ( fov.LeftTan, fov.RightTan );
+        float fovTanV = Alg::Max ( fov.UpTan, fov.DownTan );
+        fov.LeftTan = fovTanH;
+        fov.RightTan = fovTanH;
+        fov.UpTan = fovTanV;
+        fov.DownTan = fovTanV;
+    }
+    return fov;
+}
+
+ViewportScaleAndOffset ModifyRenderViewport ( StereoEyeParams const &params,
+                                              Sizei const &actualRendertargetSurfaceSize,
+                                              Recti const &renderViewport )
+{
+    return CalculateViewportScaleAndOffsetInternal ( params.EyeToSourceNDC, renderViewport, actualRendertargetSurfaceSize );
+}
+
+ViewportScaleAndOffset ModifyRenderSize ( StereoEyeParams const &params,
+                                          Sizei const &actualRendertargetSurfaceSize,
+                                          Sizei const &requestedRenderSize,
+                                          bool bRendertargetSharedByBothEyes /*= false*/ )
+{
+    Recti renderViewport = CalculateViewportInternal ( params.Eye, actualRendertargetSurfaceSize, requestedRenderSize, bRendertargetSharedByBothEyes, false );
+    return CalculateViewportScaleAndOffsetInternal ( params.EyeToSourceNDC, renderViewport, actualRendertargetSurfaceSize );
+}
+
+ViewportScaleAndOffset ModifyRenderDensity ( StereoEyeParams const &params,
+                                             Sizei const &actualRendertargetSurfaceSize,
+                                             float pixelDensity /*= 1.0f*/,
+                                             bool bRendertargetSharedByBothEyes /*= false*/ )
+{
+    Recti renderViewport = CalculateViewportDensityInternal ( params.Eye, params.Distortion, params.Fov, actualRendertargetSurfaceSize, bRendertargetSharedByBothEyes, pixelDensity, false );
+    return CalculateViewportScaleAndOffsetInternal ( params.EyeToSourceNDC, renderViewport, actualRendertargetSurfaceSize );
+}
+
+
+//-----------------------------------------------------------------------------------
+// **** StereoConfig Implementation
+
+StereoConfig::StereoConfig(StereoMode mode)
+    : Mode(mode),
+      DirtyFlag(true)
+{
+    // Initialize "fake" default HMD values for testing without HMD plugged in.
+    // These default values match those returned by DK1
+    // (at least they did at time of writing - certainly good enough for debugging)
+    Hmd.HmdType                                         = HmdType_None;
+    Hmd.ResolutionInPixels                              = Sizei(1280, 800);
+    Hmd.ScreenSizeInMeters                              = Sizef(0.1498f, 0.0936f);
+    Hmd.ScreenGapSizeInMeters                           = 0.0f;
+    Hmd.CenterFromTopInMeters                           = 0.0468f;
+    Hmd.LensSeparationInMeters                          = 0.0635f;
+    Hmd.LensDiameterInMeters                            = 0.035f;
+    Hmd.LensSurfaceToMidplateInMeters                   = 0.025f;
+    Hmd.EyeCups                                         = EyeCup_DK1A;
+    Hmd.Shutter.Type                                    = HmdShutter_RollingTopToBottom;
+    Hmd.Shutter.VsyncToNextVsync                        = ( 1.0f / 60.0f );
+    Hmd.Shutter.VsyncToFirstScanline                    = 0.000052f;
+    Hmd.Shutter.FirstScanlineToLastScanline             = 0.016580f;
+    Hmd.Shutter.PixelSettleTime                         = 0.015f;
+    Hmd.Shutter.PixelPersistence                        = ( 1.0f / 60.0f );
+    Hmd.EyeLeft.Distortion.SetToIdentity();
+    Hmd.EyeLeft.Distortion.MetersPerTanAngleAtCenter    = 0.043875f;
+    Hmd.EyeLeft.Distortion.Eqn                          = Distortion_RecipPoly4;
+    Hmd.EyeLeft.Distortion.K[0]                         = 1.0f;
+    Hmd.EyeLeft.Distortion.K[1]                         = -0.3999f;
+    Hmd.EyeLeft.Distortion.K[2]                         = 0.2408f;
+    Hmd.EyeLeft.Distortion.K[3]                         = -0.4589f;
+    Hmd.EyeLeft.Distortion.MaxR                         = 1.0f;
+	Hmd.EyeLeft.Distortion.ChromaticAberration[0]		= 0.006f;
+	Hmd.EyeLeft.Distortion.ChromaticAberration[1]		= 0.0f;
+	Hmd.EyeLeft.Distortion.ChromaticAberration[2]		= -0.014f;
+	Hmd.EyeLeft.Distortion.ChromaticAberration[3]		= 0.0f;
+    Hmd.EyeLeft.NoseToPupilInMeters                     = 0.62f;
+    Hmd.EyeLeft.ReliefInMeters                          = 0.013f;
+    Hmd.EyeRight = Hmd.EyeLeft;
+
+    SetViewportMode = SVPM_Density;
+    SetViewportPixelsPerDisplayPixel = 1.0f;
+    // Not used in this mode, but init them anyway.
+    SetViewportSize[0] = Sizei(0,0);
+    SetViewportSize[1] = Sizei(0,0);
+    SetViewport[0] = Recti(0,0,0,0);
+    SetViewport[1] = Recti(0,0,0,0);
+
+    OverrideLens = false;
+    OverrideTanHalfFov = false;
+    OverrideZeroIpd = false;
+    ExtraEyeRotationInRadians = OVR_DEFAULT_EXTRA_EYE_ROTATION;
+    IsRendertargetSharedByBothEyes = true;
+    RightHandedProjection = true;
+
+    // This should cause an assert if the app does not call SetRendertargetSize()
+    RendertargetSize = Sizei ( 0, 0 );
+
+    ZNear = 0.01f;
+    ZFar = 10000.0f;
+
+    Set2DAreaFov(DegreeToRad(85.0f));
+}
+
+void StereoConfig::SetHmdRenderInfo(const HmdRenderInfo& hmd)
+{
+    Hmd = hmd;
+    DirtyFlag = true;
+}
+
+void StereoConfig::Set2DAreaFov(float fovRadians)
+{
+    Area2DFov = fovRadians;
+    DirtyFlag = true;
+}
+
+const StereoEyeParamsWithOrtho& StereoConfig::GetEyeRenderParams(StereoEye eye)
+{
+    if ( DirtyFlag )
+    {
+        UpdateComputedState();
+    }
+
+    static const UByte eyeParamIndices[3] = { 0, 0, 1 };
+
+    OVR_ASSERT(eye < sizeof(eyeParamIndices));
+    return EyeRenderParams[eyeParamIndices[eye]];
+}
+
+void StereoConfig::SetLensOverride ( LensConfig const *pLensOverrideLeft  /*= NULL*/,
+                                     LensConfig const *pLensOverrideRight /*= NULL*/ )
+{
+    if ( pLensOverrideLeft == NULL )
+    {
+        OverrideLens = false;
+    }
+    else
+    {
+        OverrideLens = true;
+        LensOverrideLeft = *pLensOverrideLeft;
+        LensOverrideRight = *pLensOverrideLeft;
+        if ( pLensOverrideRight != NULL )
+        {
+            LensOverrideRight = *pLensOverrideRight;
+        }
+    }
+    DirtyFlag = true;
+}
+
+void StereoConfig::SetRendertargetSize (Size<int> const rendertargetSize,
+                                        bool rendertargetIsSharedByBothEyes )
+{
+    RendertargetSize = rendertargetSize;
+    IsRendertargetSharedByBothEyes = rendertargetIsSharedByBothEyes;
+    DirtyFlag = true;
+}
+
+void StereoConfig::SetFov ( FovPort const *pfovLeft  /*= NULL*/,
+                            FovPort const *pfovRight /*= NULL*/ )
+{
+    DirtyFlag = true;
+    if ( pfovLeft == NULL )
+    {
+        OverrideTanHalfFov = false;
+    }
+    else
+    {
+        OverrideTanHalfFov = true;
+        FovOverrideLeft  = *pfovLeft;
+        FovOverrideRight = *pfovLeft;
+        if ( pfovRight != NULL )
+        {
+            FovOverrideRight = *pfovRight;
+        }
+    }
+}
+
+
+void StereoConfig::SetZeroVirtualIpdOverride ( bool enableOverride )
+{
+    DirtyFlag = true;
+    OverrideZeroIpd = enableOverride;
+}
+
+
+void StereoConfig::SetZClipPlanesAndHandedness ( float zNear /*= 0.01f*/, float zFar /*= 10000.0f*/, bool rightHandedProjection /*= true*/ )
+{
+    DirtyFlag = true;
+    ZNear = zNear;
+    ZFar = zFar;
+    RightHandedProjection = rightHandedProjection;
+}
+
+void StereoConfig::SetExtraEyeRotation ( float extraEyeRotationInRadians )
+{
+    DirtyFlag = true;
+    ExtraEyeRotationInRadians = extraEyeRotationInRadians;
+}
+
+Sizei StereoConfig::CalculateRecommendedTextureSize ( bool rendertargetSharedByBothEyes,
+                                                      float pixelDensityInCenter /*= 1.0f*/ )
+{
+    return Render::CalculateRecommendedTextureSize ( Hmd, rendertargetSharedByBothEyes, pixelDensityInCenter );
+}
+
+
+
+void StereoConfig::UpdateComputedState()
+{
+    int numEyes = 2;
+    StereoEye eyeTypes[2];
+
+    switch ( Mode )
+    {
+    case Stereo_None:
+        numEyes         = 1;
+        eyeTypes[0]     = StereoEye_Center;
+        break;
+
+    case Stereo_LeftRight_Multipass:
+        numEyes         = 2;
+        eyeTypes[0]     = StereoEye_Left;
+        eyeTypes[1]     = StereoEye_Right;
+        break;
+
+    default:        
+        OVR_ASSERT( false ); break;
+    }
+
+    // If either of these fire, you've probably forgotten to call SetRendertargetSize()
+    OVR_ASSERT ( RendertargetSize.w > 0 );
+    OVR_ASSERT ( RendertargetSize.h > 0 );
+
+    for ( int eyeNum = 0; eyeNum < numEyes; eyeNum++ )
+    {
+        StereoEye eyeType = eyeTypes[eyeNum];
+        LensConfig *pLensOverride = NULL;
+        if ( OverrideLens )
+        {
+            if ( eyeType == StereoEye_Right )
+            {
+                pLensOverride = &LensOverrideRight;
+            }
+            else
+            {
+                pLensOverride = &LensOverrideLeft;
+            }
+        }
+
+        FovPort *pTanHalfFovOverride = NULL;
+        if ( OverrideTanHalfFov )
+        {
+            if ( eyeType == StereoEye_Right )
+            {
+                pTanHalfFovOverride = &FovOverrideRight;
+            }
+            else
+            {
+                pTanHalfFovOverride = &FovOverrideLeft;
+            }
+        }
+
+        DistortionAndFov distortionAndFov =
+            CalculateDistortionAndFovInternal ( eyeType, Hmd,
+                                                pLensOverride, pTanHalfFovOverride,
+                                                ExtraEyeRotationInRadians );
+
+        EyeRenderParams[eyeNum].StereoEye.Distortion = distortionAndFov.Distortion;
+        EyeRenderParams[eyeNum].StereoEye.Fov        = distortionAndFov.Fov;
+    }
+
+    if ( OverrideZeroIpd )
+    {
+        // Take the union of the calculated eye FOVs.
+        FovPort fov;
+        fov.UpTan    = Alg::Max ( EyeRenderParams[0].StereoEye.Fov.UpTan   , EyeRenderParams[1].StereoEye.Fov.UpTan    );
+        fov.DownTan  = Alg::Max ( EyeRenderParams[0].StereoEye.Fov.DownTan , EyeRenderParams[1].StereoEye.Fov.DownTan  );
+        fov.LeftTan  = Alg::Max ( EyeRenderParams[0].StereoEye.Fov.LeftTan , EyeRenderParams[1].StereoEye.Fov.LeftTan  );
+        fov.RightTan = Alg::Max ( EyeRenderParams[0].StereoEye.Fov.RightTan, EyeRenderParams[1].StereoEye.Fov.RightTan );
+        EyeRenderParams[0].StereoEye.Fov = fov;
+        EyeRenderParams[1].StereoEye.Fov = fov;
+    }
+
+    for ( int eyeNum = 0; eyeNum < numEyes; eyeNum++ )
+    {
+        StereoEye eyeType = eyeTypes[eyeNum];
+
+        DistortionRenderDesc localDistortion = EyeRenderParams[eyeNum].StereoEye.Distortion;
+        FovPort              fov             = EyeRenderParams[eyeNum].StereoEye.Fov;
+
+        // Use a placeholder - will be overridden later.
+        Recti tempViewport = Recti ( 0, 0, 1, 1 );
+
+        EyeRenderParams[eyeNum].StereoEye = CalculateStereoEyeParamsInternal (
+                                        eyeType, Hmd, localDistortion, fov,
+                                        RendertargetSize, tempViewport,
+                                        RightHandedProjection, ZNear, ZFar,
+                                        OverrideZeroIpd );
+
+        // We want to create a virtual 2D surface we can draw debug text messages to.
+        // We'd like it to be a fixed distance (OrthoDistance) away,
+        // and to cover a specific FOV (Area2DFov). We need to find the projection matrix for this,
+        // and also to know how large it is in pixels to achieve a 1:1 mapping at the center of the screen.
+        float orthoDistance = 0.8f;
+        float orthoHalfFov = tanf ( Area2DFov * 0.5f );
+        Vector2f unityOrthoPixelSize = localDistortion.PixelsPerTanAngleAtCenter * ( orthoHalfFov * 2.0f );
+        float localInterpupillaryDistance = Hmd.EyeLeft.NoseToPupilInMeters + Hmd.EyeRight.NoseToPupilInMeters;
+        if ( OverrideZeroIpd )
+        {
+            localInterpupillaryDistance = 0.0f;
+        }
+        Matrix4f ortho = CreateOrthoSubProjection ( true, eyeType,
+                                                    orthoHalfFov, orthoHalfFov,
+                                                    unityOrthoPixelSize.x, unityOrthoPixelSize.y,
+                                                    orthoDistance, localInterpupillaryDistance,
+                                                    EyeRenderParams[eyeNum].StereoEye.RenderedProjection );
+        EyeRenderParams[eyeNum].OrthoProjection = ortho;
+    }
+
+    // ...and now set up the viewport, scale & offset the way the app wanted.
+    setupViewportScaleAndOffsets();
+
+    if ( OverrideZeroIpd )
+    {
+        // Monocular rendering has some fragile parts... don't break any by accident.
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.Fov.UpTan                   == EyeRenderParams[1].StereoEye.Fov.UpTan    );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.Fov.DownTan                 == EyeRenderParams[1].StereoEye.Fov.DownTan  );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.Fov.LeftTan                 == EyeRenderParams[1].StereoEye.Fov.LeftTan  );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.Fov.RightTan                == EyeRenderParams[1].StereoEye.Fov.RightTan );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedProjection.M[0][0]  == EyeRenderParams[1].StereoEye.RenderedProjection.M[0][0] );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedProjection.M[1][1]  == EyeRenderParams[1].StereoEye.RenderedProjection.M[1][1] );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedProjection.M[0][2]  == EyeRenderParams[1].StereoEye.RenderedProjection.M[0][2] );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedProjection.M[1][2]  == EyeRenderParams[1].StereoEye.RenderedProjection.M[1][2] );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.RenderedViewport            == EyeRenderParams[1].StereoEye.RenderedViewport      );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.EyeToSourceUV.Offset        == EyeRenderParams[1].StereoEye.EyeToSourceUV.Offset  );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.EyeToSourceUV.Scale         == EyeRenderParams[1].StereoEye.EyeToSourceUV.Scale   );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.EyeToSourceNDC.Offset       == EyeRenderParams[1].StereoEye.EyeToSourceNDC.Offset );
+        OVR_ASSERT ( EyeRenderParams[0].StereoEye.EyeToSourceNDC.Scale        == EyeRenderParams[1].StereoEye.EyeToSourceNDC.Scale  );
+        OVR_ASSERT ( EyeRenderParams[0].OrthoProjection.M[0][0]               == EyeRenderParams[1].OrthoProjection.M[0][0] );
+        OVR_ASSERT ( EyeRenderParams[0].OrthoProjection.M[1][1]               == EyeRenderParams[1].OrthoProjection.M[1][1] );
+        OVR_ASSERT ( EyeRenderParams[0].OrthoProjection.M[0][2]               == EyeRenderParams[1].OrthoProjection.M[0][2] );
+        OVR_ASSERT ( EyeRenderParams[0].OrthoProjection.M[1][2]               == EyeRenderParams[1].OrthoProjection.M[1][2] );
+    }
+
+    DirtyFlag = false;
+}
+
+
+
+ViewportScaleAndOffsetBothEyes StereoConfig::setupViewportScaleAndOffsets()
+{
+    for ( int eyeNum = 0; eyeNum < 2; eyeNum++ )
+    {
+        StereoEye eyeType = ( eyeNum == 0 ) ? StereoEye_Left : StereoEye_Right;
+
+        DistortionRenderDesc localDistortion = EyeRenderParams[eyeNum].StereoEye.Distortion;
+        FovPort              fov             = EyeRenderParams[eyeNum].StereoEye.Fov;
+
+        Recti renderedViewport;
+        switch ( SetViewportMode )
+        {
+        case SVPM_Density:
+            renderedViewport = CalculateViewportDensityInternal (
+                                    eyeType, localDistortion, fov,
+                                    RendertargetSize, IsRendertargetSharedByBothEyes,
+                                    SetViewportPixelsPerDisplayPixel, OverrideZeroIpd );
+            break;
+        case SVPM_Size:
+            if ( ( eyeType == StereoEye_Right ) && !OverrideZeroIpd )
+            {
+                renderedViewport = CalculateViewportInternal (
+                                        eyeType, RendertargetSize,
+                                        SetViewportSize[1],
+                                        IsRendertargetSharedByBothEyes, OverrideZeroIpd );
+            }
+            else
+            {
+                renderedViewport = CalculateViewportInternal (
+                                        eyeType, RendertargetSize,
+                                        SetViewportSize[0],
+                                        IsRendertargetSharedByBothEyes, OverrideZeroIpd );
+            }
+            break;
+        case SVPM_Viewport:
+            if ( ( eyeType == StereoEye_Right ) && !OverrideZeroIpd )
+            {
+                renderedViewport = SetViewport[1];
+            }
+            else
+            {
+                renderedViewport = SetViewport[0];
+            }
+            break;
+        default: OVR_ASSERT ( false ); break;
+        }
+
+        ViewportScaleAndOffset vpsao = CalculateViewportScaleAndOffsetInternal (
+                                                EyeRenderParams[eyeNum].StereoEye.EyeToSourceNDC,
+                                                renderedViewport,
+                                                RendertargetSize );
+        EyeRenderParams[eyeNum].StereoEye.RenderedViewport = vpsao.RenderedViewport;
+        EyeRenderParams[eyeNum].StereoEye.EyeToSourceUV    = vpsao.EyeToSourceUV;
+    }
+
+    ViewportScaleAndOffsetBothEyes result;
+    result.Left.EyeToSourceUV     = EyeRenderParams[0].StereoEye.EyeToSourceUV;
+    result.Left.RenderedViewport  = EyeRenderParams[0].StereoEye.RenderedViewport;
+    result.Right.EyeToSourceUV    = EyeRenderParams[1].StereoEye.EyeToSourceUV;
+    result.Right.RenderedViewport = EyeRenderParams[1].StereoEye.RenderedViewport;
+    return result;
+}
+
+// Specify a pixel density - how many rendered pixels per pixel in the physical display.
+ViewportScaleAndOffsetBothEyes StereoConfig::SetRenderDensity ( float pixelsPerDisplayPixel )
+{
+    SetViewportMode  = SVPM_Density;
+    SetViewportPixelsPerDisplayPixel = pixelsPerDisplayPixel;
+    return setupViewportScaleAndOffsets();
+}
+
+// Supply the size directly. Will be clamped to the physical rendertarget size.
+ViewportScaleAndOffsetBothEyes StereoConfig::SetRenderSize ( Sizei const &renderSizeLeft, Sizei const &renderSizeRight )
+{
+    SetViewportMode  = SVPM_Size;
+    SetViewportSize[0] = renderSizeLeft;
+    SetViewportSize[1] = renderSizeRight;
+    return setupViewportScaleAndOffsets();
+}
+
+// Supply the viewport directly. This is not clamped to the physical rendertarget - careful now!
+ViewportScaleAndOffsetBothEyes StereoConfig::SetRenderViewport ( Recti const &renderViewportLeft, Recti const &renderViewportRight )
+{
+    SetViewportMode  = SVPM_Viewport;
+    SetViewport[0] = renderViewportLeft;
+    SetViewport[1] = renderViewportRight;
+    return setupViewportScaleAndOffsets();
+}
+
+Matrix4f StereoConfig::GetProjectionWithZoom ( StereoEye eye, float fovZoom ) const
+{
+    int eyeNum = ( eye == StereoEye_Right ) ? 1 : 0;
+    float fovScale = 1.0f / fovZoom;
+    FovPort fovPort = EyeRenderParams[eyeNum].StereoEye.Fov;
+    fovPort.LeftTan  *= fovScale;
+    fovPort.RightTan *= fovScale;
+    fovPort.UpTan    *= fovScale;
+    fovPort.DownTan  *= fovScale;
+    return CreateProjection ( RightHandedProjection, fovPort, ZNear, ZFar );
+}
+
+
+
+
+//-----------------------------------------------------------------------------------
+// *****  Distortion Mesh Rendering
+
+
+// Pow2 for the Morton order to work!
+// 4 is too low - it is easy to see the "wobbles" in the HMD.
+// 5 is realllly close but you can see pixel differences with even/odd frame checking.
+// 6 is indistinguishable on a monitor on even/odd frames.
+static const int DMA_GridSizeLog2   = 6;
+static const int DMA_GridSize       = 1<<DMA_GridSizeLog2;
+static const int DMA_NumVertsPerEye = (DMA_GridSize+1)*(DMA_GridSize+1);
+static const int DMA_NumTrisPerEye  = (DMA_GridSize)*(DMA_GridSize)*2;
+
+
+
+void DistortionMeshDestroy ( DistortionMeshVertexData *pVertices, UInt16 *pTriangleMeshIndices )
+{
+    OVR_FREE ( pVertices );
+    OVR_FREE ( pTriangleMeshIndices );
+}
+
+void DistortionMeshCreate ( DistortionMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices,
+                            int *pNumVertices, int *pNumTriangles,
+                            const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo )
+{
+    bool    rightEye      = ( stereoParams.Eye == StereoEye_Right );
+    int     vertexCount   = 0;
+    int     triangleCount = 0;
+
+    // Generate mesh into allocated data and return result.
+    DistortionMeshCreate(ppVertices, ppTriangleListIndices, &vertexCount, &triangleCount,
+                         rightEye, hmdRenderInfo, stereoParams.Distortion, stereoParams.EyeToSourceNDC);
+    
+    *pNumVertices  = vertexCount;
+    *pNumTriangles = triangleCount;
+}
+
+
+// Generate distortion mesh for a eye.
+void DistortionMeshCreate( DistortionMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices,
+                           int *pNumVertices, int *pNumTriangles,
+                           bool rightEye,
+                           const HmdRenderInfo &hmdRenderInfo, 
+                           const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC )
+{
+    *pNumVertices  = DMA_NumVertsPerEye;
+    *pNumTriangles = DMA_NumTrisPerEye;
+
+    *ppVertices = (DistortionMeshVertexData*)
+                      OVR_ALLOC( sizeof(DistortionMeshVertexData) * (*pNumVertices) );
+    *ppTriangleListIndices  = (UInt16*) OVR_ALLOC( sizeof(UInt16) * (*pNumTriangles) * 3 );
+
+    if (!*ppVertices || !*ppTriangleListIndices)
+    {
+        if (*ppVertices)
+        {
+            OVR_FREE(*ppVertices);
+        }
+        if (*ppTriangleListIndices)
+        {
+            OVR_FREE(*ppTriangleListIndices);
+        }
+        *ppVertices             = NULL;
+        *ppTriangleListIndices  = NULL;
+        *pNumTriangles          = 0;
+        *pNumVertices           = 0;
+        return;
+    }
+
+    // When does the fade-to-black edge start? Chosen heuristically.
+    const float fadeOutBorderFraction = 0.075f;
+      
+    
+    // Populate vertex buffer info
+    float xOffset = 0.0f;
+    float uOffset = 0.0f;
+    OVR_UNUSED(uOffset);
+
+    if (rightEye)
+    {
+        xOffset = 1.0f;
+        uOffset = 0.5f;
+    }
+
+    // First pass - build up raw vertex data.
+    DistortionMeshVertexData* pcurVert = *ppVertices;
+
+    for ( int y = 0; y <= DMA_GridSize; y++ )
+    {
+        for ( int x = 0; x <= DMA_GridSize; x++ )
+        {
+
+            Vector2f sourceCoordNDC;
+            // NDC texture coords [-1,+1]
+            sourceCoordNDC.x = 2.0f * ( (float)x / (float)DMA_GridSize ) - 1.0f;
+            sourceCoordNDC.y = 2.0f * ( (float)y / (float)DMA_GridSize ) - 1.0f;
+            Vector2f tanEyeAngle = TransformRendertargetNDCToTanFovSpace ( eyeToSourceNDC, sourceCoordNDC );
+
+            // This is the function that does the really heavy lifting.
+            Vector2f screenNDC = TransformTanFovSpaceToScreenNDC ( distortion, tanEyeAngle, false );
+
+            // We then need RGB UVs. Since chromatic aberration is generated from screen coords, not
+            // directly from texture NDCs, we can't just use tanEyeAngle, we need to go the long way round.
+            Vector2f tanEyeAnglesR, tanEyeAnglesG, tanEyeAnglesB;
+            TransformScreenNDCToTanFovSpaceChroma ( &tanEyeAnglesR, &tanEyeAnglesG, &tanEyeAnglesB,
+                                                    distortion, screenNDC );
+			
+			pcurVert->TanEyeAnglesR = tanEyeAnglesR;
+			pcurVert->TanEyeAnglesG = tanEyeAnglesG;
+			pcurVert->TanEyeAnglesB = tanEyeAnglesB;
+			
+
+            HmdShutterTypeEnum shutterType = hmdRenderInfo.Shutter.Type;
+            switch ( shutterType )
+            {
+            case HmdShutter_Global:
+                pcurVert->TimewarpLerp = 0.0f;
+                break;
+            case HmdShutter_RollingLeftToRight:
+                // Retrace is left to right - left eye goes 0.0 -> 0.5, then right goes 0.5 -> 1.0
+                pcurVert->TimewarpLerp = screenNDC.x * 0.25f + 0.25f;
+                if (rightEye)
+                {
+                    pcurVert->TimewarpLerp += 0.5f;
+                }
+                break;
+            case HmdShutter_RollingRightToLeft:
+                // Retrace is right to left - right eye goes 0.0 -> 0.5, then left goes 0.5 -> 1.0
+                pcurVert->TimewarpLerp = 0.75f - screenNDC.x * 0.25f;
+                if (rightEye)
+                {
+                    pcurVert->TimewarpLerp -= 0.5f;
+                }
+                break;
+            case HmdShutter_RollingTopToBottom:
+                // Retrace is top to bottom on both eyes at the same time.
+                pcurVert->TimewarpLerp = screenNDC.y * 0.5f + 0.5f;
+                break;
+            default: OVR_ASSERT ( false ); break;
+            }
+
+            // Fade out at texture edges.
+            float edgeFadeIn       = ( 1.0f / fadeOutBorderFraction ) *
+                                     ( 1.0f - Alg::Max ( Alg::Abs ( sourceCoordNDC.x ), Alg::Abs ( sourceCoordNDC.y ) ) );
+            // Also fade out at screen edges.
+            float edgeFadeInScreen = ( 2.0f / fadeOutBorderFraction ) *
+                                     ( 1.0f - Alg::Max ( Alg::Abs ( screenNDC.x ), Alg::Abs ( screenNDC.y ) ) );
+            edgeFadeIn = Alg::Min ( edgeFadeInScreen, edgeFadeIn );
+
+            // Don't let verts overlap to the other eye.
+            screenNDC.x = Alg::Max ( -1.0f, Alg::Min ( screenNDC.x, 1.0f ) );
+            screenNDC.y = Alg::Max ( -1.0f, Alg::Min ( screenNDC.y, 1.0f ) );
+
+            pcurVert->Shade = Alg::Max ( 0.0f, Alg::Min ( edgeFadeIn, 1.0f ) );
+            pcurVert->ScreenPosNDC.x = 0.5f * screenNDC.x - 0.5f + xOffset;
+            pcurVert->ScreenPosNDC.y = -screenNDC.y;
+
+            pcurVert++;
+        }
+    }
+
+
+    // Populate index buffer info  
+    UInt16 *pcurIndex = *ppTriangleListIndices;
+
+    for ( int triNum = 0; triNum < DMA_GridSize * DMA_GridSize; triNum++ )
+    {
+        // Use a Morton order to help locality of FB, texture and vertex cache.
+        // (0.325ms raster order -> 0.257ms Morton order)
+        OVR_ASSERT ( DMA_GridSize <= 256 );
+        int x = ( ( triNum & 0x0001 ) >> 0 ) |
+                ( ( triNum & 0x0004 ) >> 1 ) |
+                ( ( triNum & 0x0010 ) >> 2 ) |
+                ( ( triNum & 0x0040 ) >> 3 ) |
+                ( ( triNum & 0x0100 ) >> 4 ) |
+                ( ( triNum & 0x0400 ) >> 5 ) |
+                ( ( triNum & 0x1000 ) >> 6 ) |
+                ( ( triNum & 0x4000 ) >> 7 );
+        int y = ( ( triNum & 0x0002 ) >> 1 ) |
+                ( ( triNum & 0x0008 ) >> 2 ) |
+                ( ( triNum & 0x0020 ) >> 3 ) |
+                ( ( triNum & 0x0080 ) >> 4 ) |
+                ( ( triNum & 0x0200 ) >> 5 ) |
+                ( ( triNum & 0x0800 ) >> 6 ) |
+                ( ( triNum & 0x2000 ) >> 7 ) |
+                ( ( triNum & 0x8000 ) >> 8 );
+        int FirstVertex = x * (DMA_GridSize+1) + y;
+        // Another twist - we want the top-left and bottom-right quadrants to
+        // have the triangles split one way, the other two split the other.
+        // +---+---+---+---+
+        // |  /|  /|\  |\  |
+        // | / | / | \ | \ |
+        // |/  |/  |  \|  \|
+        // +---+---+---+---+
+        // |  /|  /|\  |\  |
+        // | / | / | \ | \ |
+        // |/  |/  |  \|  \|
+        // +---+---+---+---+
+        // |\  |\  |  /|  /|
+        // | \ | \ | / | / |
+        // |  \|  \|/  |/  |
+        // +---+---+---+---+
+        // |\  |\  |  /|  /|
+        // | \ | \ | / | / |
+        // |  \|  \|/  |/  |
+        // +---+---+---+---+
+        // This way triangle edges don't span long distances over the distortion function,
+        // so linear interpolation works better & we can use fewer tris.
+        if ( ( x < DMA_GridSize/2 ) != ( y < DMA_GridSize/2 ) )       // != is logical XOR
+        {
+            *pcurIndex++ = (UInt16)FirstVertex;
+            *pcurIndex++ = (UInt16)FirstVertex+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(DMA_GridSize+1)+1;
+
+            *pcurIndex++ = (UInt16)FirstVertex+(DMA_GridSize+1)+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(DMA_GridSize+1);
+            *pcurIndex++ = (UInt16)FirstVertex;
+        }
+        else
+        {
+            *pcurIndex++ = (UInt16)FirstVertex;
+            *pcurIndex++ = (UInt16)FirstVertex+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(DMA_GridSize+1);
+
+            *pcurIndex++ = (UInt16)FirstVertex+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(DMA_GridSize+1)+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(DMA_GridSize+1);
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------------
+// *****  Heightmap Mesh Rendering
+
+
+static const int HMA_GridSizeLog2   = 7;
+static const int HMA_GridSize       = 1<<HMA_GridSizeLog2;
+static const int HMA_NumVertsPerEye = (HMA_GridSize+1)*(HMA_GridSize+1);
+static const int HMA_NumTrisPerEye  = (HMA_GridSize)*(HMA_GridSize)*2;
+
+
+void HeightmapMeshDestroy ( HeightmapMeshVertexData *pVertices, UInt16 *pTriangleMeshIndices )
+{
+    OVR_FREE ( pVertices );
+    OVR_FREE ( pTriangleMeshIndices );
+}
+
+void HeightmapMeshCreate ( HeightmapMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices,
+    int *pNumVertices, int *pNumTriangles,
+    const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo )
+{
+    bool    rightEye      = ( stereoParams.Eye == StereoEye_Right );
+    int     vertexCount   = 0;
+    int     triangleCount = 0;
+
+    // Generate mesh into allocated data and return result.
+    HeightmapMeshCreate(ppVertices, ppTriangleListIndices, &vertexCount, &triangleCount,
+        rightEye, hmdRenderInfo, stereoParams.EyeToSourceNDC);
+
+    *pNumVertices  = vertexCount;
+    *pNumTriangles = triangleCount;
+}
+
+
+// Generate heightmap mesh for one eye.
+void HeightmapMeshCreate( HeightmapMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices,
+    int *pNumVertices, int *pNumTriangles, bool rightEye,
+    const HmdRenderInfo &hmdRenderInfo,
+    const ScaleAndOffset2D &eyeToSourceNDC )
+{
+    *pNumVertices  = HMA_NumVertsPerEye;
+    *pNumTriangles = HMA_NumTrisPerEye;
+
+    *ppVertices = (HeightmapMeshVertexData*) OVR_ALLOC( sizeof(HeightmapMeshVertexData) * (*pNumVertices) );
+    *ppTriangleListIndices  = (UInt16*) OVR_ALLOC( sizeof(UInt16) * (*pNumTriangles) * 3 );
+
+    if (!*ppVertices || !*ppTriangleListIndices)
+    {
+        if (*ppVertices)
+        {
+            OVR_FREE(*ppVertices);
+        }
+        if (*ppTriangleListIndices)
+        {
+            OVR_FREE(*ppTriangleListIndices);
+        }
+        *ppVertices             = NULL;
+        *ppTriangleListIndices  = NULL;
+        *pNumTriangles          = 0;
+        *pNumVertices           = 0;
+        return;
+    }
+
+    // Populate vertex buffer info
+    float xOffset = 0.0f;
+    float uOffset = 0.0f;
+
+    if (rightEye)
+    {
+        xOffset = 1.0f;
+        uOffset = 0.5f;
+    }
+
+    // First pass - build up raw vertex data.
+    HeightmapMeshVertexData* pcurVert = *ppVertices;
+
+    for ( int y = 0; y <= HMA_GridSize; y++ )
+    {
+        for ( int x = 0; x <= HMA_GridSize; x++ )
+        {
+            Vector2f sourceCoordNDC;
+            // NDC texture coords [-1,+1]
+            sourceCoordNDC.x = 2.0f * ( (float)x / (float)HMA_GridSize ) - 1.0f;
+            sourceCoordNDC.y = 2.0f * ( (float)y / (float)HMA_GridSize ) - 1.0f;
+            Vector2f tanEyeAngle = TransformRendertargetNDCToTanFovSpace ( eyeToSourceNDC, sourceCoordNDC );
+            
+            pcurVert->TanEyeAngles = tanEyeAngle;
+
+            HmdShutterTypeEnum shutterType = hmdRenderInfo.Shutter.Type;
+            switch ( shutterType )
+            {
+            case HmdShutter_Global:
+                pcurVert->TimewarpLerp = 0.0f;
+                break;
+            case HmdShutter_RollingLeftToRight:
+                // Retrace is left to right - left eye goes 0.0 -> 0.5, then right goes 0.5 -> 1.0
+                pcurVert->TimewarpLerp = sourceCoordNDC.x * 0.25f + 0.25f;
+                if (rightEye)
+                {
+                    pcurVert->TimewarpLerp += 0.5f;
+                }
+                break;
+            case HmdShutter_RollingRightToLeft:
+                // Retrace is right to left - right eye goes 0.0 -> 0.5, then left goes 0.5 -> 1.0
+                pcurVert->TimewarpLerp = 0.75f - sourceCoordNDC.x * 0.25f;
+                if (rightEye)
+                {
+                    pcurVert->TimewarpLerp -= 0.5f;
+                }
+                break;
+            case HmdShutter_RollingTopToBottom:
+                // Retrace is top to bottom on both eyes at the same time.
+                pcurVert->TimewarpLerp = sourceCoordNDC.y * 0.5f + 0.5f;
+                break;
+            default: OVR_ASSERT ( false ); break;
+            }
+
+            // Don't let verts overlap to the other eye.
+            //sourceCoordNDC.x = Alg::Max ( -1.0f, Alg::Min ( sourceCoordNDC.x, 1.0f ) );
+            //sourceCoordNDC.y = Alg::Max ( -1.0f, Alg::Min ( sourceCoordNDC.y, 1.0f ) );
+
+            //pcurVert->ScreenPosNDC.x = 0.5f * sourceCoordNDC.x - 0.5f + xOffset;
+            pcurVert->ScreenPosNDC.x = sourceCoordNDC.x;
+            pcurVert->ScreenPosNDC.y = -sourceCoordNDC.y;
+
+            pcurVert++;
+        }
+    }
+
+
+    // Populate index buffer info  
+    UInt16 *pcurIndex = *ppTriangleListIndices;
+
+    for ( int triNum = 0; triNum < HMA_GridSize * HMA_GridSize; triNum++ )
+    {
+        // Use a Morton order to help locality of FB, texture and vertex cache.
+        // (0.325ms raster order -> 0.257ms Morton order)
+        OVR_ASSERT ( HMA_GridSize < 256 );
+        int x = ( ( triNum & 0x0001 ) >> 0 ) |
+                ( ( triNum & 0x0004 ) >> 1 ) |
+                ( ( triNum & 0x0010 ) >> 2 ) |
+                ( ( triNum & 0x0040 ) >> 3 ) |
+                ( ( triNum & 0x0100 ) >> 4 ) |
+                ( ( triNum & 0x0400 ) >> 5 ) |
+                ( ( triNum & 0x1000 ) >> 6 ) |
+                ( ( triNum & 0x4000 ) >> 7 );
+        int y = ( ( triNum & 0x0002 ) >> 1 ) |
+                ( ( triNum & 0x0008 ) >> 2 ) |
+                ( ( triNum & 0x0020 ) >> 3 ) |
+                ( ( triNum & 0x0080 ) >> 4 ) |
+                ( ( triNum & 0x0200 ) >> 5 ) |
+                ( ( triNum & 0x0800 ) >> 6 ) |
+                ( ( triNum & 0x2000 ) >> 7 ) |
+                ( ( triNum & 0x8000 ) >> 8 );
+        int FirstVertex = x * (HMA_GridSize+1) + y;
+        // Another twist - we want the top-left and bottom-right quadrants to
+        // have the triangles split one way, the other two split the other.
+        // +---+---+---+---+
+        // |  /|  /|\  |\  |
+        // | / | / | \ | \ |
+        // |/  |/  |  \|  \|
+        // +---+---+---+---+
+        // |  /|  /|\  |\  |
+        // | / | / | \ | \ |
+        // |/  |/  |  \|  \|
+        // +---+---+---+---+
+        // |\  |\  |  /|  /|
+        // | \ | \ | / | / |
+        // |  \|  \|/  |/  |
+        // +---+---+---+---+
+        // |\  |\  |  /|  /|
+        // | \ | \ | / | / |
+        // |  \|  \|/  |/  |
+        // +---+---+---+---+
+        // This way triangle edges don't span long distances over the distortion function,
+        // so linear interpolation works better & we can use fewer tris.
+        if ( ( x < HMA_GridSize/2 ) != ( y < HMA_GridSize/2 ) )       // != is logical XOR
+        {
+            *pcurIndex++ = (UInt16)FirstVertex;
+            *pcurIndex++ = (UInt16)FirstVertex+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(HMA_GridSize+1)+1;
+
+            *pcurIndex++ = (UInt16)FirstVertex+(HMA_GridSize+1)+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(HMA_GridSize+1);
+            *pcurIndex++ = (UInt16)FirstVertex;
+        }
+        else
+        {
+            *pcurIndex++ = (UInt16)FirstVertex;
+            *pcurIndex++ = (UInt16)FirstVertex+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(HMA_GridSize+1);
+
+            *pcurIndex++ = (UInt16)FirstVertex+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(HMA_GridSize+1)+1;
+            *pcurIndex++ = (UInt16)FirstVertex+(HMA_GridSize+1);
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------------
+// ***** Prediction and timewarp.
+//
+
+// Calculates the values from the HMD info.
+PredictionValues PredictionGetDeviceValues ( const HmdRenderInfo &hmdRenderInfo,
+                                             bool withTimewarp /*= true*/,
+                                             bool withVsync /*= true*/ )
+{
+    PredictionValues result;
+
+    result.WithTimewarp = withTimewarp;
+    result.WithVsync = withVsync;
+
+    // For unclear reasons, most graphics systems add an extra frame of latency
+    // somewhere along the way. In time we'll debug this and figure it out, but
+    // for now this gets prediction a little bit better.
+    const float extraFramesOfBufferingKludge = 1.0f;
+
+    if ( withVsync )
+    {
+        // These are the times from the Present+Flush to when the middle of the scene is "averagely visible" (without timewarp)
+        // So if you had no timewarp, this, plus the time until the next vsync, is how much to predict by.
+        result.PresentFlushToRenderedScene  = extraFramesOfBufferingKludge * hmdRenderInfo.Shutter.FirstScanlineToLastScanline;
+        // Predict to the middle of the screen being scanned out.
+        result.PresentFlushToRenderedScene += hmdRenderInfo.Shutter.VsyncToFirstScanline + 0.5f * hmdRenderInfo.Shutter.FirstScanlineToLastScanline;
+        // Time for pixels to get half-way to settling.
+        result.PresentFlushToRenderedScene += hmdRenderInfo.Shutter.PixelSettleTime * 0.5f;
+        // Predict to half-way through persistence
+        result.PresentFlushToRenderedScene += hmdRenderInfo.Shutter.PixelPersistence * 0.5f;
+
+        // The time from the Present+Flush to when the first scanline is "averagely visible".
+        result.PresentFlushToTimewarpStart  = extraFramesOfBufferingKludge * hmdRenderInfo.Shutter.FirstScanlineToLastScanline;
+        // Predict to the first line being scanned out.
+        result.PresentFlushToTimewarpStart += hmdRenderInfo.Shutter.VsyncToFirstScanline;
+        // Time for pixels to get half-way to settling.
+        result.PresentFlushToTimewarpStart += hmdRenderInfo.Shutter.PixelSettleTime * 0.5f;
+        // Predict to half-way through persistence
+        result.PresentFlushToTimewarpStart += hmdRenderInfo.Shutter.PixelPersistence * 0.5f;
+
+        // Time to the the last scanline.
+        result.PresentFlushToTimewarpEnd    = result.PresentFlushToTimewarpStart + hmdRenderInfo.Shutter.FirstScanlineToLastScanline;
+
+        // Ideal framerate.
+        result.PresentFlushToPresentFlush   = hmdRenderInfo.Shutter.VsyncToNextVsync;
+    }
+    else
+    {
+        // Timewarp without vsync is a little odd.
+        // Currently, we assume that without vsync, we have no idea which scanline
+        // is currently being sent to the display. So we can't do lerping timewarp,
+        // we can just do a full-screen late-stage fixup.
+
+        // "PresentFlushToRenderedScene" means the time from the Present+Flush to when the middle of the scene is "averagely visible" (without timewarp)
+        // So if you had no timewarp, this, plus the time until the next flush (which is usually the time to render the frame), is how much to predict by.
+        // Time for pixels to get half-way to settling.
+        result.PresentFlushToRenderedScene  = hmdRenderInfo.Shutter.PixelSettleTime * 0.5f;
+        // Predict to half-way through persistence
+        result.PresentFlushToRenderedScene += hmdRenderInfo.Shutter.PixelPersistence * 0.5f;
+
+        // Without vsync, you don't know timings, and so can't do anything useful with lerped warping.
+        result.PresentFlushToTimewarpStart  = result.PresentFlushToRenderedScene;
+        result.PresentFlushToTimewarpEnd    = result.PresentFlushToRenderedScene;
+
+        // There's no concept of "ideal" when vsync is off.
+        result.PresentFlushToPresentFlush   = 0.0f;
+    }
+
+    return result;
+}
+
+Matrix4f TimewarpComputePoseDelta ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&eyeViewAdjust )
+{
+    Matrix4f worldFromPredictedView = (eyeViewAdjust * predictedViewFromWorld).InvertedHomogeneousTransform();
+    Matrix4f matRenderFromNowStart = (eyeViewAdjust * renderedViewFromWorld) * worldFromPredictedView;
+
+    // The sensor-predicted orientations have:                           X=right, Y=up,   Z=backwards.
+    // The vectors inside the mesh are in NDC to keep the shader simple: X=right, Y=down, Z=forwards.
+    // So we need to perform a similarity transform on this delta matrix.
+    // The verbose code would look like this:
+    /*
+    Matrix4f matBasisChange;
+    matBasisChange.SetIdentity();
+    matBasisChange.M[0][0] =  1.0f;
+    matBasisChange.M[1][1] = -1.0f;
+    matBasisChange.M[2][2] = -1.0f;
+    Matrix4f matBasisChangeInv = matBasisChange.Inverted();
+    matRenderFromNow = matBasisChangeInv * matRenderFromNow * matBasisChange;
+    */
+    // ...but of course all the above is a constant transform and much more easily done.
+    // We flip the signs of the Y&Z row, then flip the signs of the Y&Z column,
+    // and of course most of the flips cancel:
+    // +++                        +--                     +--
+    // +++ -> flip Y&Z columns -> +-- -> flip Y&Z rows -> -++
+    // +++                        +--                     -++
+    matRenderFromNowStart.M[0][1] = -matRenderFromNowStart.M[0][1];
+    matRenderFromNowStart.M[0][2] = -matRenderFromNowStart.M[0][2];
+    matRenderFromNowStart.M[1][0] = -matRenderFromNowStart.M[1][0];
+    matRenderFromNowStart.M[2][0] = -matRenderFromNowStart.M[2][0];
+    matRenderFromNowStart.M[1][3] = -matRenderFromNowStart.M[1][3];
+    matRenderFromNowStart.M[2][3] = -matRenderFromNowStart.M[2][3];
+
+    return matRenderFromNowStart;
+}
+
+Matrix4f TimewarpComputePoseDeltaPosition ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&eyeViewAdjust )
+{
+    Matrix4f worldFromPredictedView = (eyeViewAdjust * predictedViewFromWorld).InvertedHomogeneousTransform();
+    Matrix4f matRenderXform = (eyeViewAdjust * renderedViewFromWorld) * worldFromPredictedView;
+
+    return matRenderXform.Inverted();
+}
+
+TimewarpMachine::TimewarpMachine()
+{    
+    for ( int i = 0; i < 2; i++ )
+    {
+        EyeRenderPoses[i] = Transformf();
+    }
+    DistortionTimeCount = 0;
+    VsyncEnabled = false;
+}
+
+void TimewarpMachine::Reset(HmdRenderInfo& renderInfo, bool vsyncEnabled, double timeNow)
+{
+    RenderInfo = renderInfo;
+    VsyncEnabled = vsyncEnabled;
+    CurrentPredictionValues = PredictionGetDeviceValues ( renderInfo, true, VsyncEnabled );
+    PresentFlushToPresentFlushSeconds = 0.0f;
+    DistortionTimeCount = 0;
+    DistortionTimeAverage = 0.0f;
+    LastFramePresentFlushTime = timeNow;
+    AfterPresentAndFlush(timeNow);
+}
+
+void TimewarpMachine::AfterPresentAndFlush(double timeNow)
+{
+    PresentFlushToPresentFlushSeconds = (float)(timeNow - LastFramePresentFlushTime);
+    LastFramePresentFlushTime = timeNow;
+    NextFramePresentFlushTime = timeNow + (double)PresentFlushToPresentFlushSeconds;
+}
+
+double TimewarpMachine::GetViewRenderPredictionTime()
+{
+    // Note that PredictionGetDeviceValues() did all the vsync-dependent thinking for us.
+    return NextFramePresentFlushTime + CurrentPredictionValues.PresentFlushToRenderedScene;
+}
+
+Transformf TimewarpMachine::GetViewRenderPredictionPose(SensorFusion &sfusion)
+{
+    double predictionTime = GetViewRenderPredictionTime();
+    return sfusion.GetPoseAtTime(predictionTime);
+}
+
+double TimewarpMachine::GetVisiblePixelTimeStart()
+{
+    // Note that PredictionGetDeviceValues() did all the vsync-dependent thinking for us.
+    return NextFramePresentFlushTime + CurrentPredictionValues.PresentFlushToTimewarpStart;
+}
+double TimewarpMachine::GetVisiblePixelTimeEnd()
+{
+    // Note that PredictionGetDeviceValues() did all the vsync-dependent thinking for us.
+    return NextFramePresentFlushTime + CurrentPredictionValues.PresentFlushToTimewarpEnd;
+}
+Transformf TimewarpMachine::GetPredictedVisiblePixelPoseStart(SensorFusion &sfusion)
+{
+    double predictionTime = GetVisiblePixelTimeStart();
+    return sfusion.GetPoseAtTime(predictionTime);
+}
+Transformf TimewarpMachine::GetPredictedVisiblePixelPoseEnd  (SensorFusion &sfusion)
+{
+    double predictionTime = GetVisiblePixelTimeEnd();
+    return sfusion.GetPoseAtTime(predictionTime);
+}
+Matrix4f TimewarpMachine::GetTimewarpDeltaStart(SensorFusion &sfusion, Transformf const &renderedPose)
+{
+    Transformf visiblePose = GetPredictedVisiblePixelPoseStart ( sfusion );
+    Matrix4f visibleMatrix(visiblePose);
+    Matrix4f renderedMatrix(renderedPose);
+    Matrix4f identity;  // doesn't matter for orientation-only timewarp
+    return TimewarpComputePoseDelta ( renderedMatrix, visibleMatrix, identity );
+}
+Matrix4f TimewarpMachine::GetTimewarpDeltaEnd  (SensorFusion &sfusion, Transformf const &renderedPose)
+{
+    Transformf visiblePose = GetPredictedVisiblePixelPoseEnd ( sfusion );
+    Matrix4f visibleMatrix(visiblePose);
+    Matrix4f renderedMatrix(renderedPose);
+    Matrix4f identity;  // doesn't matter for orientation-only timewarp
+    return TimewarpComputePoseDelta ( renderedMatrix, visibleMatrix, identity );
+}
+
+
+// What time should the app wait until before starting distortion?
+double  TimewarpMachine::JustInTime_GetDistortionWaitUntilTime()
+{
+    if ( !VsyncEnabled || ( DistortionTimeCount < NumDistortionTimes ) )
+    {
+        // Don't wait.
+        return LastFramePresentFlushTime;
+    }
+
+    const float fudgeFactor = 0.002f;      // Found heuristically - 1ms is too short because of timing granularity - may need further tweaking!
+    float howLongBeforePresent = DistortionTimeAverage + fudgeFactor;
+    // Subtlety here. Technically, the correct time is NextFramePresentFlushTime - howLongBeforePresent.
+    // However, if the app drops a frame, this then perpetuates it,
+    // i.e. if the display is running at 60fps, but the last frame was slow,
+    // (e.g. because of swapping or whatever), then NextFramePresentFlushTime is
+    // 33ms in the future, not 16ms. Since this function supplies the 
+    // time to wait until, the app will indeed wait until 32ms, so the framerate
+    // drops to 30fps and never comes back up!
+    // So we return the *ideal* framerate, not the *actual* framerate.
+    return LastFramePresentFlushTime + (float)( CurrentPredictionValues.PresentFlushToPresentFlush - howLongBeforePresent );
+}
+
+
+bool    TimewarpMachine::JustInTime_NeedDistortionTimeMeasurement() const
+{
+    if (!VsyncEnabled)
+    {
+        return false;
+    }
+    return ( DistortionTimeCount < NumDistortionTimes );
+}
+
+void    TimewarpMachine::JustInTime_BeforeDistortionTimeMeasurement(double timeNow)
+{
+    DistortionTimeCurrentStart = timeNow;
+}
+
+void    TimewarpMachine::JustInTime_AfterDistortionTimeMeasurement(double timeNow)
+{
+    float timeDelta = (float)( timeNow - DistortionTimeCurrentStart );
+    if ( DistortionTimeCount < NumDistortionTimes )
+    {
+        DistortionTimes[DistortionTimeCount] = timeDelta;
+        DistortionTimeCount++;
+        if ( DistortionTimeCount == NumDistortionTimes )
+        {
+            // Median.
+            float distortionTimeMedian = 0.0f;
+            for ( int i = 0; i < NumDistortionTimes/2; i++ )
+            {
+                // Find the maximum time of those remaining.
+                float maxTime = DistortionTimes[0];
+                int maxIndex = 0;
+                for ( int j = 1; j < NumDistortionTimes; j++ )
+                {
+                    if ( maxTime < DistortionTimes[j] )
+                    {
+                        maxTime = DistortionTimes[j];
+                        maxIndex = j;
+                    }
+                }
+                // Zero that max time, so we'll find the next-highest time.
+                DistortionTimes[maxIndex] = 0.0f;
+                distortionTimeMedian = maxTime;
+            }
+            DistortionTimeAverage = distortionTimeMedian;
+        }
+    }
+    else
+    {
+        OVR_ASSERT ( !"Really didn't need more measurements, thanks" );
+    }
+}
+
+
+}}}  // OVR::Util::Render
+
diff --git a/LibOVR/Src/Util/Util_Render_Stereo.h b/LibOVR/Src/Util/Util_Render_Stereo.h
new file mode 100644
index 0000000..326059e
--- /dev/null
+++ b/LibOVR/Src/Util/Util_Render_Stereo.h
@@ -0,0 +1,498 @@
+/************************************************************************************
+
+PublicHeader:   OVR.h
+Filename    :   Util_Render_Stereo.h
+Content     :   Sample stereo rendering configuration classes.
+Created     :   October 22, 2012
+Authors     :   Michael Antonov, Tom Forsyth
+
+Copyright   :   Copyright 2014 Oculus VR, Inc. All Rights reserved.
+
+Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); 
+you may not use the Oculus VR Rift SDK except in compliance with the License, 
+which is provided at the time of installation or download, or which 
+otherwise accompanies this software in either electronic or hard copy form.
+
+You may obtain a copy of the License at
+
+http://www.oculusvr.com/licenses/LICENSE-3.1 
+
+Unless required by applicable law or agreed to in writing, the Oculus VR SDK 
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+*************************************************************************************/
+
+#ifndef OVR_Util_Render_Stereo_h
+#define OVR_Util_Render_Stereo_h
+
+#include "../OVR_Stereo.h"
+
+
+namespace OVR {
+
+class SensorFusion;
+
+namespace Util { namespace Render {
+
+
+
+//-----------------------------------------------------------------------------------
+// **** Useful debug functions.
+//
+// Purely for debugging - the results are not very end-user-friendly.
+char const* GetDebugNameEyeCupType ( EyeCupType eyeCupType );
+char const* GetDebugNameHmdType ( HmdTypeEnum hmdType );
+
+
+
+//-----------------------------------------------------------------------------------
+// **** Higher-level utility functions.
+
+Sizei CalculateRecommendedTextureSize    ( HmdRenderInfo const &hmd,
+                                           bool bRendertargetSharedByBothEyes,
+                                           float pixelDensityInCenter = 1.0f );
+
+FovPort CalculateRecommendedFov          ( HmdRenderInfo const &hmd,
+                                           StereoEye eyeType,
+                                           bool bMakeFovSymmetrical = false);
+
+StereoEyeParams CalculateStereoEyeParams ( HmdRenderInfo const &hmd,
+                                           StereoEye eyeType,
+                                           Sizei const &actualRendertargetSurfaceSize,
+                                           bool bRendertargetSharedByBothEyes,
+                                           bool bRightHanded = true,
+                                           float zNear = 0.01f, float zFar = 10000.0f,
+										   Sizei const *pOverrideRenderedPixelSize = NULL,
+                                           FovPort const *pOverrideFovport = NULL,
+                                           float zoomFactor = 1.0f );
+
+Vector3f CalculateEyeVirtualCameraOffset(HmdRenderInfo const &hmd,
+                                         StereoEye eyeType, bool bMonoRenderingMode );
+
+
+// These are two components from StereoEyeParams that can be changed
+// very easily without full recomputation of everything.
+struct ViewportScaleAndOffset
+{
+    Recti               RenderedViewport;
+    ScaleAndOffset2D    EyeToSourceUV;
+};
+
+// Three ways to override the size of the render view dynamically.
+// None of these require changing the distortion parameters or the regenerating the distortion mesh,
+// and can be called every frame if desired.
+ViewportScaleAndOffset ModifyRenderViewport ( StereoEyeParams const &params,
+                                              Sizei const &actualRendertargetSurfaceSize,
+                                              Recti const &renderViewport );
+
+ViewportScaleAndOffset ModifyRenderSize ( StereoEyeParams const &params,
+                                          Sizei const &actualRendertargetSurfaceSize,
+                                          Sizei const &requestedRenderSize,
+                                          bool bRendertargetSharedByBothEyes = false );
+
+ViewportScaleAndOffset ModifyRenderDensity ( StereoEyeParams const &params,
+                                             Sizei const &actualRendertargetSurfaceSize,
+                                             float pixelDensity = 1.0f,
+                                             bool bRendertargetSharedByBothEyes = false );
+
+
+//-----------------------------------------------------------------------------------
+// *****  StereoConfig
+
+// StereoConfig maintains a scene stereo state and allow switching between different
+// stereo rendering modes. To support rendering, StereoConfig keeps track of HMD
+// variables such as screen size, eye-to-screen distance and distortion, and computes
+// extra data such as FOV and distortion center offsets based on it. Rendering
+// parameters are returned though StereoEyeParams for each eye.
+//
+// Beyond regular 3D projection, this class supports rendering a 2D orthographic
+// surface for UI and text. The 2D surface will be defined by CreateOrthoSubProjection().
+// The (0,0) coordinate corresponds to eye center location.
+// 
+// Applications are not required to use this class, but they should be doing very
+// similar sequences of operations, and it may be useful to start with this class
+// and modify it.
+
+struct StereoEyeParamsWithOrtho
+{
+    StereoEyeParams         StereoEye;
+    Matrix4f                OrthoProjection;
+};
+
+struct ViewportScaleAndOffsetBothEyes
+{
+    ViewportScaleAndOffset  Left;
+    ViewportScaleAndOffset  Right;
+};
+
+class StereoConfig
+{
+public:
+
+    // StereoMode describes rendering modes that can be used by StereoConfig.
+    // These modes control whether stereo rendering is used or not (Stereo_None),
+    // and how it is implemented.
+    enum StereoMode
+    {
+        Stereo_None                     = 0,        // Single eye
+        Stereo_LeftRight_Multipass      = 1,        // One frustum per eye
+    };
+
+
+    StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass);
+ 
+    //---------------------------------------------------------------------------------------------
+    // *** Core functions - every app MUST call these functions at least once.
+
+    // Sets HMD parameters; also initializes distortion coefficients.
+    void        SetHmdRenderInfo(const HmdRenderInfo& hmd);
+
+    // Set the physical size of the rendertarget surface the app created,
+    // and whether one RT is shared by both eyes, or each eye has its own RT:
+    // true: both eyes are rendered to the same RT. Left eye starts at top-left, right eye starts at top-middle.
+    // false: each eye is rendered to its own RT. Some GPU architectures prefer this arrangement.
+    // Typically, the app would call CalculateRecommendedTextureSize() to suggest the choice of RT size.
+    // This setting must be exactly the size of the actual RT created, or the UVs produced will be incorrect.
+    // If the app wants to render to a subsection of the RT, it should use SetRenderSize()
+    void        SetRendertargetSize (Size<int> const rendertargetSize,
+                                     bool rendertargetIsSharedByBothEyes );
+
+    // Returns full set of Stereo rendering parameters for the specified eye.
+    const StereoEyeParamsWithOrtho& GetEyeRenderParams(StereoEye eye);
+
+
+
+    //---------------------------------------------------------------------------------------------
+    // *** Optional functions - an app may call these to override default behaviours.
+
+    const HmdRenderInfo& GetHmdRenderInfo() const { return Hmd; }
+
+    // Returns the recommended size of rendertargets.
+    // If rendertargetIsSharedByBothEyes is true, this is the size of the combined buffer.
+    // If rendertargetIsSharedByBothEyes is false, this is the size of each individual buffer.
+    // pixelDensityInCenter may be set to any number - by default it will match the HMD resolution in the center of the image.
+    // After creating the rendertargets, the application MUST call SetRendertargetSize() with the actual size created
+    // (which can be larger or smaller as the app wishes, but StereoConfig needs to know either way)
+    Sizei       CalculateRecommendedTextureSize ( bool rendertargetSharedByBothEyes,
+                                                  float pixelDensityInCenter = 1.0f );
+
+    // Sets a stereo rendering mode and updates internal cached
+    // state (matrices, per-eye view) based on it.
+    void        SetStereoMode(StereoMode mode)  { Mode = mode; DirtyFlag = true; }
+    StereoMode  GetStereoMode() const           { return Mode; }
+
+    // Sets the fieldOfView that the 2D coordinate area stretches to.
+    void        Set2DAreaFov(float fovRadians);
+
+    // Really only for science experiments - no normal app should ever need to override
+    // the HMD's lens descriptors. Passing NULL removes the override.
+    // Supply both = set left and right.
+    // Supply just left = set both to the same.
+    // Supply neither = remove override.
+    void        SetLensOverride ( LensConfig const *pLensOverrideLeft  = NULL,
+                                  LensConfig const *pLensOverrideRight = NULL );
+ 
+    // Override the rendered FOV in various ways. All angles in tangent units.
+    // This is not clamped to the physical FOV of the display - you'll need to do that yourself!
+    // Supply both = set left and right.
+    // Supply just left = set both to the same.
+    // Supply neither = remove override.
+    void        SetFov ( FovPort const *pfovLeft  = NULL,
+					     FovPort const *pfovRight = NULL );
+    
+    void        SetFovPortRadians ( float horizontal, float vertical )
+    {
+        FovPort fov = FovPort::CreateFromRadians(horizontal, vertical);
+        SetFov( &fov, &fov );
+    }
+
+
+    // This forces a "zero IPD" mode where there is just a single render with an FOV that
+    //   is the union of the two calculated FOVs.
+    // The calculated render is for the left eye. Any size & FOV overrides for the right
+    //   eye will be ignored.
+    // If you query the right eye's size, you will get the same render
+    //   size & position as the left eye - you should not actually do the render of course!
+    //   The distortion values will be different, because it goes to a different place on the framebuffer.
+    // Note that if you do this, the rendertarget does not need to be twice the width of
+    //   the render size any more.
+    void        SetZeroVirtualIpdOverride ( bool enableOverride );
+
+    // Allows the app to specify near and far clip planes and the right/left-handedness of the projection matrix.
+    void        SetZClipPlanesAndHandedness ( float zNear = 0.01f, float zFar = 10000.0f,
+                                              bool rightHandedProjection = true );
+
+    // Allows the app to specify how much extra eye rotation to allow when determining the visible FOV.
+    void        SetExtraEyeRotation ( float extraEyeRotationInRadians = 0.0f );
+
+    // The dirty flag is set by any of the above calls. Just handy for the app to know
+    // if e.g. the distortion mesh needs regeneration.
+    void        SetDirty() { DirtyFlag = true; }
+    bool        IsDirty() { return DirtyFlag; }
+
+    // An app never needs to call this - GetEyeRenderParams will call it internally if
+    // the state is dirty. However apps can call this explicitly to control when and where
+    // computation is performed (e.g. not inside critical loops)
+    void        UpdateComputedState();
+
+    // This returns the projection matrix with a "zoom". Does not modify any internal state.
+    Matrix4f    GetProjectionWithZoom ( StereoEye eye, float fovZoom ) const;
+
+
+    //---------------------------------------------------------------------------------------------
+    // The SetRender* functions are special.
+    //
+    // They do not require a full recalculation of state, and they do not change anything but the
+    // ViewportScaleAndOffset data for the eyes (which they return), and do not set the dirty flag!
+    // This means they can be called without regenerating the distortion mesh, and thus 
+    // can happily be called every frame without causing performance problems. Dynamic rescaling 
+    // of the rendertarget can help keep framerate up in demanding VR applications.
+    // See the documentation for more details on their use.
+
+    // Specify a pixel density - how many rendered pixels per pixel in the physical display.
+    ViewportScaleAndOffsetBothEyes SetRenderDensity ( float pixelsPerDisplayPixel );
+
+    // Supply the size directly. Will be clamped to the physical rendertarget size.
+    ViewportScaleAndOffsetBothEyes SetRenderSize ( Sizei const &renderSizeLeft, Sizei const &renderSizeRight );
+
+    // Supply the viewport directly. This is not clamped to the physical rendertarget - careful now!
+    ViewportScaleAndOffsetBothEyes SetRenderViewport ( Recti const &renderViewportLeft, Recti const &renderViewportRight );
+
+private:
+
+    // *** Modifiable State
+
+    StereoMode         Mode;
+    HmdRenderInfo      Hmd;
+
+    float              Area2DFov;           // FOV range mapping to the 2D area.
+
+    // Only one of these three overrides can be true!
+    enum SetViewportModeEnum
+    {
+        SVPM_Density,
+        SVPM_Size,
+        SVPM_Viewport,
+    }                  SetViewportMode;
+    // ...and depending which it is, one of the following are used.
+    float              SetViewportPixelsPerDisplayPixel;
+    Sizei              SetViewportSize[2];
+    Recti           SetViewport[2];
+
+    // Other overrides.
+    bool               OverrideLens;
+    LensConfig         LensOverrideLeft;
+    LensConfig         LensOverrideRight;
+    Sizei              RendertargetSize;
+    bool               OverrideTanHalfFov;
+    FovPort            FovOverrideLeft;
+    FovPort            FovOverrideRight;
+    bool               OverrideZeroIpd;
+    float              ZNear;
+    float              ZFar;
+    float              ExtraEyeRotationInRadians;
+    bool               IsRendertargetSharedByBothEyes;
+    bool               RightHandedProjection;
+
+    bool               DirtyFlag;   // Set when any if the modifiable state changed. Does NOT get set by SetRender*()
+
+    // Utility function.
+    ViewportScaleAndOffsetBothEyes setupViewportScaleAndOffsets();
+
+    // *** Computed State
+
+public:     // Small hack for the config tool. Normal code should never read EyeRenderParams directly - use GetEyeRenderParams() instead.
+    // 0/1 = left/right main views.
+    StereoEyeParamsWithOrtho    EyeRenderParams[2];
+};
+
+
+//-----------------------------------------------------------------------------------
+// *****  Distortion Mesh Rendering
+//
+
+// Stores both texture UV coords, or tan(angle) values.
+// Use whichever set of data the specific distortion algorithm requires.
+// This struct *must* be binary compatible with CAPI ovrDistortionVertex.
+struct DistortionMeshVertexData
+{
+    // [-1,+1],[-1,+1] over the entire framebuffer.
+    Vector2f    ScreenPosNDC;
+    // [0.0-1.0] interpolation value for timewarping - see documentation for details.
+    float       TimewarpLerp;
+    // [0.0-1.0] fade-to-black at the edges to reduce peripheral vision noise.
+    float       Shade;        
+    // The red, green, and blue vectors in tan(angle) space.
+    // Scale and offset by the values in StereoEyeParams.EyeToSourceUV.Scale
+    // and StereoParams.EyeToSourceUV.Offset to get to real texture UV coords.
+    Vector2f    TanEyeAnglesR;
+    Vector2f    TanEyeAnglesG;
+    Vector2f    TanEyeAnglesB;    
+};
+
+
+void DistortionMeshCreate ( DistortionMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices,
+                            int *pNumVertices, int *pNumTriangles,
+                            const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo );
+
+// Generate distortion mesh for a eye. This version requires less data then stereoParms, supporting
+// dynamic change in render target viewport.
+void DistortionMeshCreate( DistortionMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices,
+                           int *pNumVertices, int *pNumTriangles,
+                           bool rightEye,
+                           const HmdRenderInfo &hmdRenderInfo, 
+                           const DistortionRenderDesc &distortion, const ScaleAndOffset2D &eyeToSourceNDC );
+
+void DistortionMeshDestroy ( DistortionMeshVertexData *pVertices, UInt16 *pTriangleMeshIndices );
+
+
+//-----------------------------------------------------------------------------------
+// *****  Heightmap Mesh Rendering
+//
+
+// Stores both texture UV coords, or tan(angle) values.
+// This struct *must* be binary compatible with CAPI ovrHeightmapVertex.
+struct HeightmapMeshVertexData
+{
+    // [-1,+1],[-1,+1] over the entire framebuffer.
+    Vector2f    ScreenPosNDC;
+    // [0.0-1.0] interpolation value for timewarping - see documentation for details.
+    float       TimewarpLerp;
+    // The vectors in tan(angle) space.
+    // Scale and offset by the values in StereoEyeParams.EyeToSourceUV.Scale
+    // and StereoParams.EyeToSourceUV.Offset to get to real texture UV coords.
+    Vector2f    TanEyeAngles;    
+};
+
+
+void HeightmapMeshCreate ( HeightmapMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices,
+    int *pNumVertices, int *pNumTriangles,
+    const StereoEyeParams &stereoParams, const HmdRenderInfo &hmdRenderInfo );
+
+// Generate heightmap mesh for a eye. This version requires less data then stereoParms, supporting
+// dynamic change in render target viewport.
+void HeightmapMeshCreate( HeightmapMeshVertexData **ppVertices, UInt16 **ppTriangleListIndices,
+    int *pNumVertices, int *pNumTriangles, bool rightEye,
+    const HmdRenderInfo &hmdRenderInfo, const ScaleAndOffset2D &eyeToSourceNDC );
+
+void HeightmapMeshDestroy ( HeightmapMeshVertexData *pVertices, UInt16 *pTriangleMeshIndices );
+
+
+
+//-----------------------------------------------------------------------------------
+// ***** Prediction and timewarp.
+//
+
+struct PredictionValues
+{
+    // All values in seconds.
+    // These are the times in seconds from a present+flush to the relevant display element.
+    // The time is measured to the middle of that element's visibility window,
+    // e.g. if the device is a full-persistence display, the element will be visible for
+    // an entire frame, so the time measures to the middle of that period, i.e. half the frame time.
+    float PresentFlushToRenderedScene;        // To the overall rendered 3D scene being visible.
+    float PresentFlushToTimewarpStart;        // To when the first timewarped scanline will be visible.
+    float PresentFlushToTimewarpEnd;          // To when the last timewarped scanline will be visible.
+    float PresentFlushToPresentFlush;         // To the next present+flush, i.e. the ideal framerate.
+
+    bool  WithTimewarp;
+    bool  WithVsync;
+};
+
+// Calculates the values from the HMD info.
+PredictionValues PredictionGetDeviceValues ( const HmdRenderInfo &hmdRenderInfo,
+                                             bool withTimewarp = true,
+                                             bool withVsync = true );
+
+// Pass in an orientation used to render the scene, and then the predicted orientation
+// (which may have been computed later on, and thus is more accurate), and this
+// will return the matrix to pass to the timewarp distortion shader.
+// TODO: deal with different handedness?
+Matrix4f TimewarpComputePoseDelta ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&eyeViewAdjust );
+Matrix4f TimewarpComputePoseDeltaPosition ( Matrix4f const &renderedViewFromWorld, Matrix4f const &predictedViewFromWorld, Matrix4f const&eyeViewAdjust );
+
+
+
+// TimewarpMachine helps keep track of rendered frame timing and
+// handles predictions for time-warp rendering.
+class TimewarpMachine
+{
+public:
+    TimewarpMachine();
+   
+    // Call this on and every time something about the setup changes.
+    void        Reset ( HmdRenderInfo& renderInfo, bool vsyncEnabled, double timeNow );
+
+    // The only reliable time in most engines is directly after the frame-present and GPU flush-and-wait.
+    // This call should be done right after that to give this system the timing info it needs.
+    void        AfterPresentAndFlush(double timeNow);
+
+    // The "average" time the rendered frame will show up,
+    // and the predicted pose of the HMD at that time.
+    // You usually only need to call one of these functions.
+    double      GetViewRenderPredictionTime();
+    Transformf  GetViewRenderPredictionPose(SensorFusion &sfusion);
+
+
+    // Timewarp prediction functions. You usually only need to call one of these three sets of functions.
+
+    // The predicted times that the first and last pixel will be visible on-screen.
+    double      GetVisiblePixelTimeStart();
+    double      GetVisiblePixelTimeEnd();
+    // Predicted poses of the HMD at those first and last pixels.
+    Transformf  GetPredictedVisiblePixelPoseStart(SensorFusion &sfusion);
+    Transformf  GetPredictedVisiblePixelPoseEnd  (SensorFusion &sfusion);
+    // The delta matrices to feed to the timewarp distortion code,
+    // given the pose that was used for rendering.
+    // (usually the one returned by GetViewRenderPredictionPose() earlier)
+    Matrix4f    GetTimewarpDeltaStart(SensorFusion &sfusion, Transformf const &renderedPose);
+    Matrix4f    GetTimewarpDeltaEnd  (SensorFusion &sfusion, Transformf const &renderedPose);
+
+
+    // Just-In-Time distortion aims to delay the second sensor reading & distortion
+    // until the very last moment to improve prediction. However, it is a little scary,
+    // since the delay might wait too long and miss the vsync completely!
+    // Use of the JustInTime_* functions is entirely optional, and we advise allowing
+    // users to turn it off in their video options to cope with odd machine configurations.
+
+    // What time should the app wait until before starting distortion?
+    double      JustInTime_GetDistortionWaitUntilTime();
+
+    // Used to time the distortion rendering
+    bool        JustInTime_NeedDistortionTimeMeasurement() const;
+    void        JustInTime_BeforeDistortionTimeMeasurement(double timeNow);
+    void        JustInTime_AfterDistortionTimeMeasurement(double timeNow);
+
+
+private:
+
+    bool                VsyncEnabled;
+    HmdRenderInfo       RenderInfo;
+    PredictionValues    CurrentPredictionValues;
+
+    enum { NumDistortionTimes = 10 };
+    int                 DistortionTimeCount;
+    double              DistortionTimeCurrentStart;
+    float               DistortionTimes[NumDistortionTimes];
+    float               DistortionTimeAverage;
+
+    // Pose at which last time the eye was rendered.
+    Transformf               EyeRenderPoses[2];
+
+    // Absolute time of the last present+flush
+    double              LastFramePresentFlushTime;
+    // Seconds between presentflushes
+    float               PresentFlushToPresentFlushSeconds;
+    // Predicted absolute time of the next present+flush
+    double              NextFramePresentFlushTime;
+
+};
+
+
+
+}}}  // OVR::Util::Render
+
+#endif
-- 
cgit v1.2.3