oculus1

changeset 1:e2f9e4603129

added LibOVR and started a simple vr wrapper.
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 14 Sep 2013 16:14:59 +0300
parents c7b50cd7184c
children 59fc487ba58e
files .hgignore Makefile libovr/Include/OVR.h libovr/Include/OVRVersion.h libovr/Src/Kernel/OVR_Alg.cpp libovr/Src/Kernel/OVR_Alg.h libovr/Src/Kernel/OVR_Allocator.cpp libovr/Src/Kernel/OVR_Allocator.h libovr/Src/Kernel/OVR_Array.h libovr/Src/Kernel/OVR_Atomic.cpp libovr/Src/Kernel/OVR_Atomic.h libovr/Src/Kernel/OVR_Color.h libovr/Src/Kernel/OVR_ContainerAllocator.h libovr/Src/Kernel/OVR_File.cpp libovr/Src/Kernel/OVR_File.h libovr/Src/Kernel/OVR_FileFILE.cpp libovr/Src/Kernel/OVR_Hash.h libovr/Src/Kernel/OVR_KeyCodes.h libovr/Src/Kernel/OVR_List.h libovr/Src/Kernel/OVR_Log.cpp libovr/Src/Kernel/OVR_Log.h libovr/Src/Kernel/OVR_Math.cpp libovr/Src/Kernel/OVR_Math.h libovr/Src/Kernel/OVR_RefCount.cpp libovr/Src/Kernel/OVR_RefCount.h libovr/Src/Kernel/OVR_Std.cpp libovr/Src/Kernel/OVR_Std.h libovr/Src/Kernel/OVR_String.cpp libovr/Src/Kernel/OVR_String.h libovr/Src/Kernel/OVR_StringHash.h libovr/Src/Kernel/OVR_String_FormatUtil.cpp libovr/Src/Kernel/OVR_String_PathUtil.cpp libovr/Src/Kernel/OVR_SysFile.cpp libovr/Src/Kernel/OVR_SysFile.h libovr/Src/Kernel/OVR_System.cpp libovr/Src/Kernel/OVR_System.h libovr/Src/Kernel/OVR_Threads.h libovr/Src/Kernel/OVR_Timer.cpp libovr/Src/Kernel/OVR_Timer.h libovr/Src/Kernel/OVR_Types.h libovr/Src/Kernel/OVR_UTF8Util.cpp libovr/Src/Kernel/OVR_UTF8Util.h libovr/Src/OVR_Device.h libovr/Src/OVR_DeviceConstants.h libovr/Src/OVR_DeviceHandle.cpp libovr/Src/OVR_DeviceHandle.h libovr/Src/OVR_DeviceImpl.cpp libovr/Src/OVR_DeviceImpl.h libovr/Src/OVR_DeviceMessages.h libovr/Src/OVR_HIDDevice.h libovr/Src/OVR_HIDDeviceBase.h libovr/Src/OVR_HIDDeviceImpl.h libovr/Src/OVR_JSON.cpp libovr/Src/OVR_JSON.h libovr/Src/OVR_LatencyTestImpl.cpp libovr/Src/OVR_LatencyTestImpl.h libovr/Src/OVR_Profile.cpp libovr/Src/OVR_Profile.h libovr/Src/OVR_SensorFilter.cpp libovr/Src/OVR_SensorFilter.h libovr/Src/OVR_SensorFusion.cpp libovr/Src/OVR_SensorFusion.h libovr/Src/OVR_SensorImpl.cpp libovr/Src/OVR_SensorImpl.h libovr/Src/OVR_ThreadCommandQueue.cpp libovr/Src/OVR_ThreadCommandQueue.h libovr/Src/Util/Util_LatencyTest.cpp libovr/Src/Util/Util_LatencyTest.h libovr/Src/Util/Util_MagCalibration.cpp libovr/Src/Util/Util_MagCalibration.h libovr/Src/Util/Util_Render_Stereo.cpp libovr/Src/Util/Util_Render_Stereo.h libovr/Src/linux/OVR_Linux_DeviceManager.cpp libovr/Src/linux/OVR_Linux_DeviceManager.h libovr/Src/linux/OVR_Linux_HIDDevice.cpp libovr/Src/linux/OVR_Linux_HIDDevice.h libovr/Src/linux/OVR_Linux_HMDDevice.cpp libovr/Src/linux/OVR_Linux_HMDDevice.h libovr/Src/linux/OVR_Linux_SensorDevice.cpp libovr/Src/linux/OVR_ThreadsPthread.cpp libovr/Src/osx/OVR_OSX_DeviceManager.cpp libovr/Src/osx/OVR_OSX_DeviceManager.h libovr/Src/osx/OVR_OSX_HIDDevice.cpp libovr/Src/osx/OVR_OSX_HIDDevice.h libovr/Src/osx/OVR_OSX_HMDDevice.cpp libovr/Src/osx/OVR_OSX_HMDDevice.h libovr/Src/osx/OVR_OSX_SensorDevice.cpp libovr/Src/osx/OVR_ThreadsPthread.cpp libovr/Src/win32/OVR_ThreadsWinAPI.cpp libovr/Src/win32/OVR_Win32_DeviceManager.cpp libovr/Src/win32/OVR_Win32_DeviceManager.h libovr/Src/win32/OVR_Win32_DeviceStatus.cpp libovr/Src/win32/OVR_Win32_DeviceStatus.h libovr/Src/win32/OVR_Win32_HIDDevice.cpp libovr/Src/win32/OVR_Win32_HIDDevice.h libovr/Src/win32/OVR_Win32_HMDDevice.cpp libovr/Src/win32/OVR_Win32_HMDDevice.h libovr/Src/win32/OVR_Win32_SensorDevice.cpp libovr/Src/win32/OVR_Win32_SensorDevice.h src/main.cc src/vr.cc src/vr.h src/vr_impl.h
diffstat 103 files changed, 15643 insertions(+), 11 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Sat Sep 14 16:14:59 2013 +0300
     1.3 @@ -0,0 +1,4 @@
     1.4 +\.o$
     1.5 +\.d$
     1.6 +\.swp$
     1.7 +^oculus1$
     2.1 --- a/Makefile	Fri Aug 30 06:08:34 2013 +0300
     2.2 +++ b/Makefile	Sat Sep 14 16:14:59 2013 +0300
     2.3 @@ -1,16 +1,26 @@
     2.4  src = $(wildcard src/*.cc)
     2.5 -obj = $(src:.cc=.o)
     2.6 +ovr_src = $(wildcard libovr/Src/*.cpp) \
     2.7 +		  $(wildcard libovr/Src/Kernel/*.cpp) \
     2.8 +		  $(wildcard libovr/Src/Util/*.cpp)
     2.9 +
    2.10 +obj = $(src:.cc=.o) $(ovr_src:.cpp=.o) $(ovr_sys_src:.cpp=.o)
    2.11  bin = oculus1
    2.12  
    2.13 -CXXFLAGS = -pedantic -Wall -g -I/usr/local/include
    2.14 +
    2.15 +CXXFLAGS = -Wall -g -I/usr/local/include $(ovr_include) -DUSE_OVR
    2.16  LDFLAGS = -L/usr/local/lib $(libgl) $(ovrlibs) -lm
    2.17  
    2.18  ifeq ($(shell uname -s), Darwin)
    2.19  	libgl = -framework OpenGL -framework GLUT -lGLEW
    2.20 -	ovrlibs = -lovr -framework CoreFoundation -framework ApplicationServices -framework IOKit
    2.21 +	ovrlibs = -framework CoreFoundation -framework ApplicationServices -framework IOKit
    2.22 +
    2.23 +	ovr_include = -Ilibovr/Include -Ilibovr/Src -Ilibovr/Src/osx
    2.24 +	ovr_sys_src = $(wildcard libovr/Src/osx/*.cpp)
    2.25  else
    2.26  	libgl = -lGL -lGLU -lglut -lGLEW
    2.27 -	ovrlibs = -lovr
    2.28 +
    2.29 +	ovr_include = -Ilibovr/Include -Ilibovr/Src -Ilibovr/Src/linux
    2.30 +	ovr_sys_src = $(wildcard libovr/Src/linux/*.cpp)
    2.31  endif
    2.32  
    2.33  $(bin): $(obj)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/libovr/Include/OVR.h	Sat Sep 14 16:14:59 2013 +0300
     3.3 @@ -0,0 +1,34 @@
     3.4 +/************************************************************************************
     3.5 +
     3.6 +Filename    :   OVR.h
     3.7 +Content     :   This contains references to all OVR-specific headers in Src folder.
     3.8 +                Should be generated automatically based on PublicHeader tags.
     3.9 +
    3.10 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    3.11 +
    3.12 +Use of this software is subject to the terms of the Oculus license
    3.13 +agreement provided at the time of installation or download, or which
    3.14 +otherwise accompanies this software in either electronic or hard copy form.
    3.15 +
    3.16 +*************************************************************************************/
    3.17 +
    3.18 +#ifndef OVR_h
    3.19 +#define OVR_h
    3.20 +
    3.21 +#include "../Src/Kernel/OVR_Allocator.h"
    3.22 +#include "../Src/Kernel/OVR_Log.h"
    3.23 +#include "../Src/Kernel/OVR_Math.h"
    3.24 +#include "../Src/Kernel/OVR_System.h"
    3.25 +#include "../Src/Kernel/OVR_Types.h"
    3.26 +#include "../Src/OVR_Device.h"
    3.27 +#include "../Src/OVR_DeviceConstants.h"
    3.28 +#include "../Src/OVR_DeviceHandle.h"
    3.29 +#include "../Src/OVR_DeviceMessages.h"
    3.30 +#include "../Src/OVR_SensorFusion.h"
    3.31 +#include "../Src/OVR_Profile.h"
    3.32 +#include "../Src/Util/Util_LatencyTest.h"
    3.33 +#include "../Src/Util/Util_Render_Stereo.h"
    3.34 +#include "../Src/Util/Util_MagCalibration.h"
    3.35 +
    3.36 +#endif
    3.37 +
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/libovr/Include/OVRVersion.h	Sat Sep 14 16:14:59 2013 +0300
     4.3 @@ -0,0 +1,22 @@
     4.4 +/************************************************************************************
     4.5 +
     4.6 +Filename    :   OVRVersion.h
     4.7 +Content     :   
     4.8 +
     4.9 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    4.10 +
    4.11 +Use of this software is subject to the terms of the Oculus license
    4.12 +agreement provided at the time of installation or download, or which
    4.13 +otherwise accompanies this software in either electronic or hard copy form.
    4.14 +
    4.15 +*************************************************************************************/
    4.16 +
    4.17 +#ifndef _OVR_VERSION_H
    4.18 +#define _OVR_VERSION_H
    4.19 +
    4.20 +#define OVR_MAJOR_VERSION 0
    4.21 +#define OVR_MINOR_VERSION 2
    4.22 +#define OVR_BUILD_VERSION 4
    4.23 +#define OVR_VERSION_STRING "0.2.4"
    4.24 +
    4.25 +#endif
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/libovr/Src/Kernel/OVR_Alg.cpp	Sat Sep 14 16:14:59 2013 +0300
     5.3 @@ -0,0 +1,1 @@
     5.4 +/************************************************************************************
     5.5 
     5.6 Filename    :   OVR_Alg.cpp
     5.7 Content     :   Static lookup tables for Alg functions
     5.8 Created     :   September 19, 2012
     5.9 Notes       : 
    5.10 
    5.11 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    5.12 
    5.13 Use of this software is subject to the terms of the Oculus license
    5.14 agreement provided at the time of installation or download, or which
    5.15 otherwise accompanies this software in either electronic or hard copy form.
    5.16 
    5.17 ************************************************************************************/
    5.18 
    5.19 #include "OVR_Types.h"
    5.20 
    5.21 namespace OVR { namespace Alg {
    5.22 
    5.23 //------------------------------------------------------------------------
    5.24 extern const UByte UpperBitTable[256] =
    5.25 {
    5.26     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.27     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
    5.28     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,
    5.29     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,
    5.30     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,
    5.31     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,
    5.32     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,
    5.33     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
    5.34 };
    5.35 
    5.36 extern const UByte LowerBitTable[256] =
    5.37 {
    5.38     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.39     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,
    5.40     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.41     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,
    5.42     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.43     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,
    5.44     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.45     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
    5.46 };
    5.47 
    5.48 
    5.49 }} // OVE::Alg
    5.50 \ No newline at end of file
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/libovr/Src/Kernel/OVR_Alg.h	Sat Sep 14 16:14:59 2013 +0300
     6.3 @@ -0,0 +1,1 @@
     6.4 +/************************************************************************************
     6.5 
     6.6 PublicHeader:   OVR.h
     6.7 Filename    :   OVR_Alg.h
     6.8 Content     :   Simple general purpose algorithms: Sort, Binary Search, etc.
     6.9 Created     :   September 19, 2012
    6.10 Notes       : 
    6.11 
    6.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    6.13 
    6.14 Use of this software is subject to the terms of the Oculus license
    6.15 agreement provided at the time of installation or download, or which
    6.16 otherwise accompanies this software in either electronic or hard copy form.
    6.17 
    6.18 ************************************************************************************/
    6.19 
    6.20 #ifndef OVR_Alg_h
    6.21 #define OVR_Alg_h
    6.22 
    6.23 #include "OVR_Types.h"
    6.24 #include <string.h>
    6.25 
    6.26 namespace OVR { namespace Alg {
    6.27 
    6.28 
    6.29 //-----------------------------------------------------------------------------------
    6.30 // ***** Operator extensions
    6.31 
    6.32 template <typename T> OVR_FORCE_INLINE void Swap(T &a, T &b) 
    6.33 {  T temp(a); a = b; b = temp; }
    6.34 
    6.35 
    6.36 // ***** min/max are not implemented in Visual Studio 6 standard STL
    6.37 
    6.38 template <typename T> OVR_FORCE_INLINE const T Min(const T a, const T b)
    6.39 { return (a < b) ? a : b; }
    6.40 
    6.41 template <typename T> OVR_FORCE_INLINE const T Max(const T a, const T b)
    6.42 { return (b < a) ? a : b; }
    6.43 
    6.44 template <typename T> OVR_FORCE_INLINE const T Clamp(const T v, const T minVal, const T maxVal)
    6.45 { return Max<T>(minVal, Min<T>(v, maxVal)); }
    6.46 
    6.47 template <typename T> OVR_FORCE_INLINE int     Chop(T f)
    6.48 { return (int)f; }
    6.49 
    6.50 template <typename T> OVR_FORCE_INLINE T       Lerp(T a, T b, T f) 
    6.51 { return (b - a) * f + a; }
    6.52 
    6.53 
    6.54 // These functions stand to fix a stupid VC++ warning (with /Wp64 on):
    6.55 // "warning C4267: 'argument' : conversion from 'size_t' to 'const unsigned', possible loss of data"
    6.56 // Use these functions instead of gmin/gmax if the argument has size
    6.57 // of the pointer to avoid the warning. Though, functionally they are
    6.58 // absolutelly the same as regular gmin/gmax.
    6.59 template <typename T>   OVR_FORCE_INLINE const T PMin(const T a, const T b)
    6.60 {
    6.61     OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt));
    6.62     return (a < b) ? a : b;
    6.63 }
    6.64 template <typename T>   OVR_FORCE_INLINE const T PMax(const T a, const T b)
    6.65 {
    6.66     OVR_COMPILER_ASSERT(sizeof(T) == sizeof(UPInt));
    6.67     return (b < a) ? a : b;
    6.68 }
    6.69 
    6.70 
    6.71 template <typename T>   OVR_FORCE_INLINE const T Abs(const T v)
    6.72 { return (v>=0) ? v : -v; }
    6.73 
    6.74 
    6.75 //-----------------------------------------------------------------------------------
    6.76 // ***** OperatorLess
    6.77 //
    6.78 template<class T> struct OperatorLess
    6.79 {
    6.80     static bool Compare(const T& a, const T& b)
    6.81     {
    6.82         return a < b;
    6.83     }
    6.84 };
    6.85 
    6.86 
    6.87 //-----------------------------------------------------------------------------------
    6.88 // ***** QuickSortSliced
    6.89 //
    6.90 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
    6.91 // The range is specified with start, end, where "end" is exclusive!
    6.92 // The comparison predicate must be specified.
    6.93 template<class Array, class Less> 
    6.94 void QuickSortSliced(Array& arr, UPInt start, UPInt end, Less less)
    6.95 {
    6.96     enum 
    6.97     {
    6.98         Threshold = 9
    6.99     };
   6.100 
   6.101     if(end - start <  2) return;
   6.102 
   6.103     SPInt  stack[80];
   6.104     SPInt* top   = stack; 
   6.105     SPInt  base  = (SPInt)start;
   6.106     SPInt  limit = (SPInt)end;
   6.107 
   6.108     for(;;)
   6.109     {
   6.110         SPInt len = limit - base;
   6.111         SPInt i, j, pivot;
   6.112 
   6.113         if(len > Threshold)
   6.114         {
   6.115             // we use base + len/2 as the pivot
   6.116             pivot = base + len / 2;
   6.117             Swap(arr[base], arr[pivot]);
   6.118 
   6.119             i = base + 1;
   6.120             j = limit - 1;
   6.121 
   6.122             // now ensure that *i <= *base <= *j 
   6.123             if(less(arr[j],    arr[i])) Swap(arr[j],    arr[i]);
   6.124             if(less(arr[base], arr[i])) Swap(arr[base], arr[i]);
   6.125             if(less(arr[j], arr[base])) Swap(arr[j], arr[base]);
   6.126 
   6.127             for(;;)
   6.128             {
   6.129                 do i++; while( less(arr[i], arr[base]) );
   6.130                 do j--; while( less(arr[base], arr[j]) );
   6.131 
   6.132                 if( i > j )
   6.133                 {
   6.134                     break;
   6.135                 }
   6.136 
   6.137                 Swap(arr[i], arr[j]);
   6.138             }
   6.139 
   6.140             Swap(arr[base], arr[j]);
   6.141 
   6.142             // now, push the largest sub-array
   6.143             if(j - base > limit - i)
   6.144             {
   6.145                 top[0] = base;
   6.146                 top[1] = j;
   6.147                 base   = i;
   6.148             }
   6.149             else
   6.150             {
   6.151                 top[0] = i;
   6.152                 top[1] = limit;
   6.153                 limit  = j;
   6.154             }
   6.155             top += 2;
   6.156         }
   6.157         else
   6.158         {
   6.159             // the sub-array is small, perform insertion sort
   6.160             j = base;
   6.161             i = j + 1;
   6.162 
   6.163             for(; i < limit; j = i, i++)
   6.164             {
   6.165                 for(; less(arr[j + 1], arr[j]); j--)
   6.166                 {
   6.167                     Swap(arr[j + 1], arr[j]);
   6.168                     if(j == base)
   6.169                     {
   6.170                         break;
   6.171                     }
   6.172                 }
   6.173             }
   6.174             if(top > stack)
   6.175             {
   6.176                 top  -= 2;
   6.177                 base  = top[0];
   6.178                 limit = top[1];
   6.179             }
   6.180             else
   6.181             {
   6.182                 break;
   6.183             }
   6.184         }
   6.185     }
   6.186 }
   6.187 
   6.188 
   6.189 //-----------------------------------------------------------------------------------
   6.190 // ***** QuickSortSliced
   6.191 //
   6.192 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
   6.193 // The range is specified with start, end, where "end" is exclusive!
   6.194 // The data type must have a defined "<" operator.
   6.195 template<class Array> 
   6.196 void QuickSortSliced(Array& arr, UPInt start, UPInt end)
   6.197 {
   6.198     typedef typename Array::ValueType ValueType;
   6.199     QuickSortSliced(arr, start, end, OperatorLess<ValueType>::Compare);
   6.200 }
   6.201 
   6.202 // Same as corresponding G_QuickSortSliced but with checking array limits to avoid
   6.203 // crash in the case of wrong comparator functor.
   6.204 template<class Array, class Less> 
   6.205 bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end, Less less)
   6.206 {
   6.207     enum 
   6.208     {
   6.209         Threshold = 9
   6.210     };
   6.211 
   6.212     if(end - start <  2) return true;
   6.213 
   6.214     SPInt  stack[80];
   6.215     SPInt* top   = stack; 
   6.216     SPInt  base  = (SPInt)start;
   6.217     SPInt  limit = (SPInt)end;
   6.218 
   6.219     for(;;)
   6.220     {
   6.221         SPInt len = limit - base;
   6.222         SPInt i, j, pivot;
   6.223 
   6.224         if(len > Threshold)
   6.225         {
   6.226             // we use base + len/2 as the pivot
   6.227             pivot = base + len / 2;
   6.228             Swap(arr[base], arr[pivot]);
   6.229 
   6.230             i = base + 1;
   6.231             j = limit - 1;
   6.232 
   6.233             // now ensure that *i <= *base <= *j 
   6.234             if(less(arr[j],    arr[i])) Swap(arr[j],    arr[i]);
   6.235             if(less(arr[base], arr[i])) Swap(arr[base], arr[i]);
   6.236             if(less(arr[j], arr[base])) Swap(arr[j], arr[base]);
   6.237 
   6.238             for(;;)
   6.239             {
   6.240                 do 
   6.241                 {   
   6.242                     i++; 
   6.243                     if (i >= limit)
   6.244                         return false;
   6.245                 } while( less(arr[i], arr[base]) );
   6.246                 do 
   6.247                 {
   6.248                     j--; 
   6.249                     if (j < 0)
   6.250                         return false;
   6.251                 } while( less(arr[base], arr[j]) );
   6.252 
   6.253                 if( i > j )
   6.254                 {
   6.255                     break;
   6.256                 }
   6.257 
   6.258                 Swap(arr[i], arr[j]);
   6.259             }
   6.260 
   6.261             Swap(arr[base], arr[j]);
   6.262 
   6.263             // now, push the largest sub-array
   6.264             if(j - base > limit - i)
   6.265             {
   6.266                 top[0] = base;
   6.267                 top[1] = j;
   6.268                 base   = i;
   6.269             }
   6.270             else
   6.271             {
   6.272                 top[0] = i;
   6.273                 top[1] = limit;
   6.274                 limit  = j;
   6.275             }
   6.276             top += 2;
   6.277         }
   6.278         else
   6.279         {
   6.280             // the sub-array is small, perform insertion sort
   6.281             j = base;
   6.282             i = j + 1;
   6.283 
   6.284             for(; i < limit; j = i, i++)
   6.285             {
   6.286                 for(; less(arr[j + 1], arr[j]); j--)
   6.287                 {
   6.288                     Swap(arr[j + 1], arr[j]);
   6.289                     if(j == base)
   6.290                     {
   6.291                         break;
   6.292                     }
   6.293                 }
   6.294             }
   6.295             if(top > stack)
   6.296             {
   6.297                 top  -= 2;
   6.298                 base  = top[0];
   6.299                 limit = top[1];
   6.300             }
   6.301             else
   6.302             {
   6.303                 break;
   6.304             }
   6.305         }
   6.306     }
   6.307     return true;
   6.308 }
   6.309 
   6.310 template<class Array> 
   6.311 bool QuickSortSlicedSafe(Array& arr, UPInt start, UPInt end)
   6.312 {
   6.313     typedef typename Array::ValueType ValueType;
   6.314     return QuickSortSlicedSafe(arr, start, end, OperatorLess<ValueType>::Compare);
   6.315 }
   6.316 
   6.317 //-----------------------------------------------------------------------------------
   6.318 // ***** QuickSort
   6.319 //
   6.320 // Sort an array Array, ArrayPaged, ArrayUnsafe.
   6.321 // The array must have GetSize() function.
   6.322 // The comparison predicate must be specified.
   6.323 template<class Array, class Less> 
   6.324 void QuickSort(Array& arr, Less less)
   6.325 {
   6.326     QuickSortSliced(arr, 0, arr.GetSize(), less);
   6.327 }
   6.328 
   6.329 // checks for boundaries
   6.330 template<class Array, class Less> 
   6.331 bool QuickSortSafe(Array& arr, Less less)
   6.332 {
   6.333     return QuickSortSlicedSafe(arr, 0, arr.GetSize(), less);
   6.334 }
   6.335 
   6.336 
   6.337 //-----------------------------------------------------------------------------------
   6.338 // ***** QuickSort
   6.339 //
   6.340 // Sort an array Array, ArrayPaged, ArrayUnsafe.
   6.341 // The array must have GetSize() function.
   6.342 // The data type must have a defined "<" operator.
   6.343 template<class Array> 
   6.344 void QuickSort(Array& arr)
   6.345 {
   6.346     typedef typename Array::ValueType ValueType;
   6.347     QuickSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
   6.348 }
   6.349 
   6.350 template<class Array> 
   6.351 bool QuickSortSafe(Array& arr)
   6.352 {
   6.353     typedef typename Array::ValueType ValueType;
   6.354     return QuickSortSlicedSafe(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
   6.355 }
   6.356 
   6.357 //-----------------------------------------------------------------------------------
   6.358 // ***** InsertionSortSliced
   6.359 //
   6.360 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
   6.361 // The range is specified with start, end, where "end" is exclusive!
   6.362 // The comparison predicate must be specified.
   6.363 // Unlike Quick Sort, the Insertion Sort works much slower in average, 
   6.364 // but may be much faster on almost sorted arrays. Besides, it guarantees
   6.365 // that the elements will not be swapped if not necessary. For example, 
   6.366 // an array with all equal elements will remain "untouched", while 
   6.367 // Quick Sort will considerably shuffle the elements in this case.
   6.368 template<class Array, class Less> 
   6.369 void InsertionSortSliced(Array& arr, UPInt start, UPInt end, Less less)
   6.370 {
   6.371     UPInt j = start;
   6.372     UPInt i = j + 1;
   6.373     UPInt limit = end;
   6.374 
   6.375     for(; i < limit; j = i, i++)
   6.376     {
   6.377         for(; less(arr[j + 1], arr[j]); j--)
   6.378         {
   6.379             Swap(arr[j + 1], arr[j]);
   6.380             if(j <= start)
   6.381             {
   6.382                 break;
   6.383             }
   6.384         }
   6.385     }
   6.386 }
   6.387 
   6.388 
   6.389 //-----------------------------------------------------------------------------------
   6.390 // ***** InsertionSortSliced
   6.391 //
   6.392 // Sort any part of any array: plain, Array, ArrayPaged, ArrayUnsafe.
   6.393 // The range is specified with start, end, where "end" is exclusive!
   6.394 // The data type must have a defined "<" operator.
   6.395 template<class Array> 
   6.396 void InsertionSortSliced(Array& arr, UPInt start, UPInt end)
   6.397 {
   6.398     typedef typename Array::ValueType ValueType;
   6.399     InsertionSortSliced(arr, start, end, OperatorLess<ValueType>::Compare);
   6.400 }
   6.401 
   6.402 //-----------------------------------------------------------------------------------
   6.403 // ***** InsertionSort
   6.404 //
   6.405 // Sort an array Array, ArrayPaged, ArrayUnsafe.
   6.406 // The array must have GetSize() function.
   6.407 // The comparison predicate must be specified.
   6.408 
   6.409 template<class Array, class Less> 
   6.410 void InsertionSort(Array& arr, Less less)
   6.411 {
   6.412     InsertionSortSliced(arr, 0, arr.GetSize(), less);
   6.413 }
   6.414 
   6.415 //-----------------------------------------------------------------------------------
   6.416 // ***** InsertionSort
   6.417 //
   6.418 // Sort an array Array, ArrayPaged, ArrayUnsafe.
   6.419 // The array must have GetSize() function.
   6.420 // The data type must have a defined "<" operator.
   6.421 template<class Array> 
   6.422 void InsertionSort(Array& arr)
   6.423 {
   6.424     typedef typename Array::ValueType ValueType;
   6.425     InsertionSortSliced(arr, 0, arr.GetSize(), OperatorLess<ValueType>::Compare);
   6.426 }
   6.427 
   6.428 
   6.429 
   6.430 //-----------------------------------------------------------------------------------
   6.431 // ***** LowerBoundSliced
   6.432 //
   6.433 template<class Array, class Value, class Less>
   6.434 UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less)
   6.435 {
   6.436     SPInt first = (SPInt)start;
   6.437     SPInt len   = (SPInt)(end - start);
   6.438     SPInt half;
   6.439     SPInt middle;
   6.440     
   6.441     while(len > 0) 
   6.442     {
   6.443         half = len >> 1;
   6.444         middle = first + half;
   6.445         if(less(arr[middle], val)) 
   6.446         {
   6.447             first = middle + 1;
   6.448             len   = len - half - 1;
   6.449         }
   6.450         else
   6.451         {
   6.452             len = half;
   6.453         }
   6.454     }
   6.455     return (UPInt)first;
   6.456 }
   6.457 
   6.458 
   6.459 //-----------------------------------------------------------------------------------
   6.460 // ***** LowerBoundSliced
   6.461 //
   6.462 template<class Array, class Value>
   6.463 UPInt LowerBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val)
   6.464 {
   6.465     return LowerBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare);
   6.466 }
   6.467 
   6.468 //-----------------------------------------------------------------------------------
   6.469 // ***** LowerBoundSized
   6.470 //
   6.471 template<class Array, class Value>
   6.472 UPInt LowerBoundSized(const Array& arr, UPInt size, const Value& val)
   6.473 {
   6.474     return LowerBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare);
   6.475 }
   6.476 
   6.477 //-----------------------------------------------------------------------------------
   6.478 // ***** LowerBound
   6.479 //
   6.480 template<class Array, class Value, class Less>
   6.481 UPInt LowerBound(const Array& arr, const Value& val, Less less)
   6.482 {
   6.483     return LowerBoundSliced(arr, 0, arr.GetSize(), val, less);
   6.484 }
   6.485 
   6.486 
   6.487 //-----------------------------------------------------------------------------------
   6.488 // ***** LowerBound
   6.489 //
   6.490 template<class Array, class Value>
   6.491 UPInt LowerBound(const Array& arr, const Value& val)
   6.492 {
   6.493     return LowerBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare);
   6.494 }
   6.495 
   6.496 
   6.497 
   6.498 //-----------------------------------------------------------------------------------
   6.499 // ***** UpperBoundSliced
   6.500 //
   6.501 template<class Array, class Value, class Less>
   6.502 UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val, Less less)
   6.503 {
   6.504     SPInt first = (SPInt)start;
   6.505     SPInt len   = (SPInt)(end - start);
   6.506     SPInt half;
   6.507     SPInt middle;
   6.508     
   6.509     while(len > 0) 
   6.510     {
   6.511         half = len >> 1;
   6.512         middle = first + half;
   6.513         if(less(val, arr[middle]))
   6.514         {
   6.515             len = half;
   6.516         }
   6.517         else 
   6.518         {
   6.519             first = middle + 1;
   6.520             len   = len - half - 1;
   6.521         }
   6.522     }
   6.523     return (UPInt)first;
   6.524 }
   6.525 
   6.526 
   6.527 //-----------------------------------------------------------------------------------
   6.528 // ***** UpperBoundSliced
   6.529 //
   6.530 template<class Array, class Value>
   6.531 UPInt UpperBoundSliced(const Array& arr, UPInt start, UPInt end, const Value& val)
   6.532 {
   6.533     return UpperBoundSliced(arr, start, end, val, OperatorLess<Value>::Compare);
   6.534 }
   6.535 
   6.536 
   6.537 //-----------------------------------------------------------------------------------
   6.538 // ***** UpperBoundSized
   6.539 //
   6.540 template<class Array, class Value>
   6.541 UPInt UpperBoundSized(const Array& arr, UPInt size, const Value& val)
   6.542 {
   6.543     return UpperBoundSliced(arr, 0, size, val, OperatorLess<Value>::Compare);
   6.544 }
   6.545 
   6.546 
   6.547 //-----------------------------------------------------------------------------------
   6.548 // ***** UpperBound
   6.549 //
   6.550 template<class Array, class Value, class Less>
   6.551 UPInt UpperBound(const Array& arr, const Value& val, Less less)
   6.552 {
   6.553     return UpperBoundSliced(arr, 0, arr.GetSize(), val, less);
   6.554 }
   6.555 
   6.556 
   6.557 //-----------------------------------------------------------------------------------
   6.558 // ***** UpperBound
   6.559 //
   6.560 template<class Array, class Value>
   6.561 UPInt UpperBound(const Array& arr, const Value& val)
   6.562 {
   6.563     return UpperBoundSliced(arr, 0, arr.GetSize(), val, OperatorLess<Value>::Compare);
   6.564 }
   6.565 
   6.566 
   6.567 //-----------------------------------------------------------------------------------
   6.568 // ***** ReverseArray
   6.569 //
   6.570 template<class Array> void ReverseArray(Array& arr)
   6.571 {
   6.572     SPInt from = 0;
   6.573     SPInt to   = arr.GetSize() - 1;
   6.574     while(from < to)
   6.575     {
   6.576         Swap(arr[from], arr[to]);
   6.577         ++from;
   6.578         --to;
   6.579     }
   6.580 }
   6.581 
   6.582 
   6.583 // ***** AppendArray
   6.584 //
   6.585 template<class CDst, class CSrc> 
   6.586 void AppendArray(CDst& dst, const CSrc& src)
   6.587 {
   6.588     UPInt i;
   6.589     for(i = 0; i < src.GetSize(); i++) 
   6.590         dst.PushBack(src[i]);
   6.591 }
   6.592 
   6.593 //-----------------------------------------------------------------------------------
   6.594 // ***** ArrayAdaptor
   6.595 //
   6.596 // A simple adapter that provides the GetSize() method and overloads 
   6.597 // operator []. Used to wrap plain arrays in QuickSort and such.
   6.598 template<class T> class ArrayAdaptor
   6.599 {
   6.600 public:
   6.601     typedef T ValueType;
   6.602     ArrayAdaptor() : Data(0), Size(0) {}
   6.603     ArrayAdaptor(T* ptr, UPInt size) : Data(ptr), Size(size) {}
   6.604     UPInt GetSize() const { return Size; }
   6.605     const T& operator [] (UPInt i) const { return Data[i]; }
   6.606           T& operator [] (UPInt i)       { return Data[i]; }
   6.607 private:
   6.608     T*      Data;
   6.609     UPInt   Size;
   6.610 };
   6.611 
   6.612 
   6.613 //-----------------------------------------------------------------------------------
   6.614 // ***** GConstArrayAdaptor
   6.615 //
   6.616 // A simple const adapter that provides the GetSize() method and overloads 
   6.617 // operator []. Used to wrap plain arrays in LowerBound and such.
   6.618 template<class T> class ConstArrayAdaptor
   6.619 {
   6.620 public:
   6.621     typedef T ValueType;
   6.622     ConstArrayAdaptor() : Data(0), Size(0) {}
   6.623     ConstArrayAdaptor(const T* ptr, UPInt size) : Data(ptr), Size(size) {}
   6.624     UPInt GetSize() const { return Size; }
   6.625     const T& operator [] (UPInt i) const { return Data[i]; }
   6.626 private:
   6.627     const T* Data;
   6.628     UPInt    Size;
   6.629 };
   6.630 
   6.631 
   6.632 
   6.633 //-----------------------------------------------------------------------------------
   6.634 extern const UByte UpperBitTable[256];
   6.635 extern const UByte LowerBitTable[256];
   6.636 
   6.637 
   6.638 
   6.639 //-----------------------------------------------------------------------------------
   6.640 inline UByte UpperBit(UPInt val)
   6.641 {
   6.642 #ifndef OVR_64BIT_POINTERS
   6.643 
   6.644     if (val & 0xFFFF0000)
   6.645     {
   6.646         return (val & 0xFF000000) ? 
   6.647             UpperBitTable[(val >> 24)       ] + 24: 
   6.648             UpperBitTable[(val >> 16) & 0xFF] + 16;
   6.649     }
   6.650     return (val & 0xFF00) ?
   6.651         UpperBitTable[(val >> 8) & 0xFF] + 8:
   6.652         UpperBitTable[(val     ) & 0xFF];
   6.653 
   6.654 #else
   6.655 
   6.656     if (val & 0xFFFFFFFF00000000)
   6.657     {
   6.658         if (val & 0xFFFF000000000000)
   6.659         {
   6.660             return (val & 0xFF00000000000000) ?
   6.661                 UpperBitTable[(val >> 56)       ] + 56: 
   6.662                 UpperBitTable[(val >> 48) & 0xFF] + 48;
   6.663         }
   6.664         return (val & 0xFF0000000000) ?
   6.665             UpperBitTable[(val >> 40) & 0xFF] + 40:
   6.666             UpperBitTable[(val >> 32) & 0xFF] + 32;
   6.667     }
   6.668     else
   6.669     {
   6.670         if (val & 0xFFFF0000)
   6.671         {
   6.672             return (val & 0xFF000000) ? 
   6.673                 UpperBitTable[(val >> 24)       ] + 24: 
   6.674                 UpperBitTable[(val >> 16) & 0xFF] + 16;
   6.675         }
   6.676         return (val & 0xFF00) ?
   6.677             UpperBitTable[(val >> 8) & 0xFF] + 8:
   6.678             UpperBitTable[(val     ) & 0xFF];
   6.679     }
   6.680 
   6.681 #endif
   6.682 }
   6.683 
   6.684 //-----------------------------------------------------------------------------------
   6.685 inline UByte LowerBit(UPInt val)
   6.686 {
   6.687 #ifndef OVR_64BIT_POINTERS
   6.688 
   6.689     if (val & 0xFFFF)
   6.690     {
   6.691         return (val & 0xFF) ?
   6.692             LowerBitTable[ val & 0xFF]:
   6.693             LowerBitTable[(val >> 8) & 0xFF] + 8;
   6.694     }
   6.695     return (val & 0xFF0000) ?
   6.696             LowerBitTable[(val >> 16) & 0xFF] + 16:
   6.697             LowerBitTable[(val >> 24) & 0xFF] + 24;
   6.698 
   6.699 #else
   6.700 
   6.701     if (val & 0xFFFFFFFF)
   6.702     {
   6.703         if (val & 0xFFFF)
   6.704         {
   6.705             return (val & 0xFF) ?
   6.706                 LowerBitTable[ val & 0xFF]:
   6.707                 LowerBitTable[(val >> 8) & 0xFF] + 8;
   6.708         }
   6.709         return (val & 0xFF0000) ?
   6.710                 LowerBitTable[(val >> 16) & 0xFF] + 16:
   6.711                 LowerBitTable[(val >> 24) & 0xFF] + 24;
   6.712     }
   6.713     else
   6.714     {
   6.715         if (val & 0xFFFF00000000)
   6.716         {
   6.717              return (val & 0xFF00000000) ?
   6.718                 LowerBitTable[(val >> 32) & 0xFF] + 32:
   6.719                 LowerBitTable[(val >> 40) & 0xFF] + 40;
   6.720         }
   6.721         return (val & 0xFF000000000000) ?
   6.722             LowerBitTable[(val >> 48) & 0xFF] + 48:
   6.723             LowerBitTable[(val >> 56) & 0xFF] + 56;
   6.724     }
   6.725 
   6.726 #endif
   6.727 }
   6.728 
   6.729 
   6.730 
   6.731 // ******* Special (optimized) memory routines
   6.732 // Note: null (bad) pointer is not tested
   6.733 class MemUtil
   6.734 {
   6.735 public:
   6.736                                     
   6.737     // Memory compare
   6.738     static int      Cmp  (const void* p1, const void* p2, UPInt byteCount)      { return memcmp(p1, p2, byteCount); }
   6.739     static int      Cmp16(const void* p1, const void* p2, UPInt int16Count);
   6.740     static int      Cmp32(const void* p1, const void* p2, UPInt int32Count);
   6.741     static int      Cmp64(const void* p1, const void* p2, UPInt int64Count); 
   6.742 };
   6.743 
   6.744 // ** Inline Implementation
   6.745 
   6.746 inline int MemUtil::Cmp16(const void* p1, const void* p2, UPInt int16Count)
   6.747 {
   6.748     SInt16*  pa  = (SInt16*)p1; 
   6.749     SInt16*  pb  = (SInt16*)p2;
   6.750     unsigned ic  = 0;
   6.751     if (int16Count == 0)
   6.752         return 0;
   6.753     while (pa[ic] == pb[ic])
   6.754         if (++ic==int16Count)
   6.755             return 0;
   6.756     return pa[ic] > pb[ic] ? 1 : -1;
   6.757 }
   6.758 inline int MemUtil::Cmp32(const void* p1, const void* p2, UPInt int32Count)
   6.759 {
   6.760     SInt32*  pa  = (SInt32*)p1;
   6.761     SInt32*  pb  = (SInt32*)p2;
   6.762     unsigned ic  = 0;
   6.763     if (int32Count == 0)
   6.764         return 0;
   6.765     while (pa[ic] == pb[ic])
   6.766         if (++ic==int32Count)
   6.767             return 0;
   6.768     return pa[ic] > pb[ic] ? 1 : -1;
   6.769 }
   6.770 inline int MemUtil::Cmp64(const void* p1, const void* p2, UPInt int64Count)
   6.771 {
   6.772     SInt64*  pa  = (SInt64*)p1;
   6.773     SInt64*  pb  = (SInt64*)p2;
   6.774     unsigned ic  = 0;
   6.775     if (int64Count == 0)
   6.776         return 0;
   6.777     while (pa[ic] == pb[ic])
   6.778         if (++ic==int64Count)
   6.779             return 0;
   6.780     return pa[ic] > pb[ic] ? 1 : -1;
   6.781 }
   6.782 
   6.783 // ** End Inline Implementation
   6.784 
   6.785 
   6.786 //-----------------------------------------------------------------------------------
   6.787 // ******* Byte Order Conversions
   6.788 namespace ByteUtil {
   6.789 
   6.790     // *** Swap Byte Order
   6.791 
   6.792     // Swap the byte order of a byte array
   6.793     inline void     SwapOrder(void* pv, int size)
   6.794     {
   6.795         UByte*  pb = (UByte*)pv;
   6.796         UByte   temp;
   6.797         for (int i = 0; i < size>>1; i++)
   6.798         { 
   6.799             temp            = pb[size-1-i];
   6.800             pb[size-1-i]    = pb[i];
   6.801             pb[i]           = temp; 
   6.802         }
   6.803     }
   6.804 
   6.805     // Swap the byte order of primitive types
   6.806     inline UByte    SwapOrder(UByte v)      { return v; }
   6.807     inline SByte    SwapOrder(SByte v)      { return v; }
   6.808     inline UInt16   SwapOrder(UInt16 v)     { return UInt16(v>>8)|UInt16(v<<8); }
   6.809     inline SInt16   SwapOrder(SInt16 v)     { return SInt16((UInt16(v)>>8)|(v<<8)); }
   6.810     inline UInt32   SwapOrder(UInt32 v)     { return (v>>24)|((v&0x00FF0000)>>8)|((v&0x0000FF00)<<8)|(v<<24); }
   6.811     inline SInt32   SwapOrder(SInt32 p)     { return (SInt32)SwapOrder(UInt32(p)); }
   6.812     inline UInt64   SwapOrder(UInt64 v)
   6.813     { 
   6.814         return   (v>>56) |
   6.815                  ((v&UInt64(0x00FF000000000000))>>40) |
   6.816                  ((v&UInt64(0x0000FF0000000000))>>24) |
   6.817                  ((v&UInt64(0x000000FF00000000))>>8)  |
   6.818                  ((v&UInt64(0x00000000FF000000))<<8)  |
   6.819                  ((v&UInt64(0x0000000000FF0000))<<24) |
   6.820                  ((v&UInt64(0x000000000000FF00))<<40) |
   6.821                  (v<<56); 
   6.822     }
   6.823     inline SInt64   SwapOrder(SInt64 v)     { return (SInt64)SwapOrder(UInt64(v)); }
   6.824     inline float    SwapOrder(float p)      
   6.825     { 
   6.826         union {
   6.827             float p;
   6.828             UInt32 v;
   6.829         } u;
   6.830         u.p = p;
   6.831         u.v = SwapOrder(u.v);
   6.832         return u.p;
   6.833     }
   6.834 
   6.835     inline double   SwapOrder(double p)
   6.836     { 
   6.837         union {
   6.838             double p;
   6.839             UInt64 v;
   6.840         } u;
   6.841         u.p = p;
   6.842         u.v = SwapOrder(u.v);
   6.843         return u.p;
   6.844     }
   6.845     
   6.846     // *** Byte-order conversion
   6.847 
   6.848 #if (OVR_BYTE_ORDER == OVR_LITTLE_ENDIAN)
   6.849     // Little Endian to System (LE)
   6.850     inline UByte    LEToSystem(UByte  v)    { return v; }
   6.851     inline SByte    LEToSystem(SByte  v)    { return v; }
   6.852     inline UInt16   LEToSystem(UInt16 v)    { return v; }
   6.853     inline SInt16   LEToSystem(SInt16 v)    { return v; }
   6.854     inline UInt32   LEToSystem(UInt32 v)    { return v; }
   6.855     inline SInt32   LEToSystem(SInt32 v)    { return v; }
   6.856     inline UInt64   LEToSystem(UInt64 v)    { return v; }
   6.857     inline SInt64   LEToSystem(SInt64 v)    { return v; }
   6.858     inline float    LEToSystem(float  v)    { return v; }
   6.859     inline double   LEToSystem(double v)    { return v; }
   6.860 
   6.861     // Big Endian to System (LE)
   6.862     inline UByte    BEToSystem(UByte  v)    { return SwapOrder(v); }
   6.863     inline SByte    BEToSystem(SByte  v)    { return SwapOrder(v); }
   6.864     inline UInt16   BEToSystem(UInt16 v)    { return SwapOrder(v); }
   6.865     inline SInt16   BEToSystem(SInt16 v)    { return SwapOrder(v); }
   6.866     inline UInt32   BEToSystem(UInt32 v)    { return SwapOrder(v); }
   6.867     inline SInt32   BEToSystem(SInt32 v)    { return SwapOrder(v); }
   6.868     inline UInt64   BEToSystem(UInt64 v)    { return SwapOrder(v); }
   6.869     inline SInt64   BEToSystem(SInt64 v)    { return SwapOrder(v); }
   6.870     inline float    BEToSystem(float  v)    { return SwapOrder(v); }
   6.871     inline double   BEToSystem(double v)    { return SwapOrder(v); }
   6.872 
   6.873     // System (LE) to Little Endian
   6.874     inline UByte    SystemToLE(UByte  v)    { return v; }
   6.875     inline SByte    SystemToLE(SByte  v)    { return v; }
   6.876     inline UInt16   SystemToLE(UInt16 v)    { return v; }
   6.877     inline SInt16   SystemToLE(SInt16 v)    { return v; }
   6.878     inline UInt32   SystemToLE(UInt32 v)    { return v; }
   6.879     inline SInt32   SystemToLE(SInt32 v)    { return v; }
   6.880     inline UInt64   SystemToLE(UInt64 v)    { return v; }
   6.881     inline SInt64   SystemToLE(SInt64 v)    { return v; }
   6.882     inline float    SystemToLE(float  v)    { return v; }
   6.883     inline double   SystemToLE(double v)    { return v; }   
   6.884 
   6.885     // System (LE) to Big Endian
   6.886     inline UByte    SystemToBE(UByte  v)    { return SwapOrder(v); }
   6.887     inline SByte    SystemToBE(SByte  v)    { return SwapOrder(v); }
   6.888     inline UInt16   SystemToBE(UInt16 v)    { return SwapOrder(v); }
   6.889     inline SInt16   SystemToBE(SInt16 v)    { return SwapOrder(v); }
   6.890     inline UInt32   SystemToBE(UInt32 v)    { return SwapOrder(v); }
   6.891     inline SInt32   SystemToBE(SInt32 v)    { return SwapOrder(v); }
   6.892     inline UInt64   SystemToBE(UInt64 v)    { return SwapOrder(v); }
   6.893     inline SInt64   SystemToBE(SInt64 v)    { return SwapOrder(v); }
   6.894     inline float    SystemToBE(float  v)    { return SwapOrder(v); }
   6.895     inline double   SystemToBE(double v)    { return SwapOrder(v); }
   6.896 
   6.897 #elif (OVR_BYTE_ORDER == OVR_BIG_ENDIAN)
   6.898     // Little Endian to System (BE)
   6.899     inline UByte    LEToSystem(UByte  v)    { return SwapOrder(v); }
   6.900     inline SByte    LEToSystem(SByte  v)    { return SwapOrder(v); }
   6.901     inline UInt16   LEToSystem(UInt16 v)    { return SwapOrder(v); }
   6.902     inline SInt16   LEToSystem(SInt16 v)    { return SwapOrder(v); }
   6.903     inline UInt32   LEToSystem(UInt32 v)    { return SwapOrder(v); }
   6.904     inline SInt32   LEToSystem(SInt32 v)    { return SwapOrder(v); }
   6.905     inline UInt64   LEToSystem(UInt64 v)    { return SwapOrder(v); }
   6.906     inline SInt64   LEToSystem(SInt64 v)    { return SwapOrder(v); }
   6.907     inline float    LEToSystem(float  v)    { return SwapOrder(v); }
   6.908     inline double   LEToSystem(double v)    { return SwapOrder(v); }
   6.909 
   6.910     // Big Endian to System (BE)
   6.911     inline UByte    BEToSystem(UByte  v)    { return v; }
   6.912     inline SByte    BEToSystem(SByte  v)    { return v; }
   6.913     inline UInt16   BEToSystem(UInt16 v)    { return v; }
   6.914     inline SInt16   BEToSystem(SInt16 v)    { return v; }
   6.915     inline UInt32   BEToSystem(UInt32 v)    { return v; }
   6.916     inline SInt32   BEToSystem(SInt32 v)    { return v; }
   6.917     inline UInt64   BEToSystem(UInt64 v)    { return v; }
   6.918     inline SInt64   BEToSystem(SInt64 v)    { return v; }
   6.919     inline float    BEToSystem(float  v)    { return v; }
   6.920     inline double   BEToSystem(double v)    { return v; }
   6.921 
   6.922     // System (BE) to Little Endian
   6.923     inline UByte    SystemToLE(UByte  v)    { return SwapOrder(v); }
   6.924     inline SByte    SystemToLE(SByte  v)    { return SwapOrder(v); }
   6.925     inline UInt16   SystemToLE(UInt16 v)    { return SwapOrder(v); }
   6.926     inline SInt16   SystemToLE(SInt16 v)    { return SwapOrder(v); }
   6.927     inline UInt32   SystemToLE(UInt32 v)    { return SwapOrder(v); }
   6.928     inline SInt32   SystemToLE(SInt32 v)    { return SwapOrder(v); }
   6.929     inline UInt64   SystemToLE(UInt64 v)    { return SwapOrder(v); }
   6.930     inline SInt64   SystemToLE(SInt64 v)    { return SwapOrder(v); }
   6.931     inline float    SystemToLE(float  v)    { return SwapOrder(v); }
   6.932     inline double   SystemToLE(double v)    { return SwapOrder(v); }
   6.933 
   6.934     // System (BE) to Big Endian
   6.935     inline UByte    SystemToBE(UByte  v)    { return v; }
   6.936     inline SByte    SystemToBE(SByte  v)    { return v; }
   6.937     inline UInt16   SystemToBE(UInt16 v)    { return v; }
   6.938     inline SInt16   SystemToBE(SInt16 v)    { return v; }
   6.939     inline UInt32   SystemToBE(UInt32 v)    { return v; }
   6.940     inline SInt32   SystemToBE(SInt32 v)    { return v; }
   6.941     inline UInt64   SystemToBE(UInt64 v)    { return v; }
   6.942     inline SInt64   SystemToBE(SInt64 v)    { return v; }
   6.943     inline float    SystemToBE(float  v)    { return v; }
   6.944     inline double   SystemToBE(double v)    { return v; }
   6.945 
   6.946 #else
   6.947     #error "OVR_BYTE_ORDER must be defined to OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN"
   6.948 #endif
   6.949 
   6.950 } // namespace ByteUtil
   6.951 
   6.952 
   6.953 
   6.954 }} // OVR::Alg
   6.955 
   6.956 #endif
   6.957 \ No newline at end of file
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/libovr/Src/Kernel/OVR_Allocator.cpp	Sat Sep 14 16:14:59 2013 +0300
     7.3 @@ -0,0 +1,1 @@
     7.4 +/************************************************************************************
     7.5 
     7.6 Filename    :   OVR_Allocator.cpp
     7.7 Content     :   Installable memory allocator implementation
     7.8 Created     :   September 19, 2012
     7.9 Notes       : 
    7.10 
    7.11 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    7.12 
    7.13 Use of this software is subject to the terms of the Oculus license
    7.14 agreement provided at the time of installation or download, or which
    7.15 otherwise accompanies this software in either electronic or hard copy form.
    7.16 
    7.17 ************************************************************************************/
    7.18 
    7.19 #include "OVR_Allocator.h"
    7.20 #ifdef OVR_OS_MAC
    7.21  #include <stdlib.h>
    7.22 #else
    7.23  #include <malloc.h>
    7.24 #endif
    7.25 
    7.26 namespace OVR {
    7.27 
    7.28 //-----------------------------------------------------------------------------------
    7.29 // ***** Allocator
    7.30 
    7.31 Allocator* Allocator::pInstance = 0;
    7.32 
    7.33 // Default AlignedAlloc implementation will delegate to Alloc/Free after doing rounding.
    7.34 void* Allocator::AllocAligned(UPInt size, UPInt align)
    7.35 {
    7.36     OVR_ASSERT((align & (align-1)) == 0);
    7.37     align = (align > sizeof(UPInt)) ? align : sizeof(UPInt);
    7.38     UPInt p = (UPInt)Alloc(size+align);
    7.39     UPInt aligned = 0;
    7.40     if (p)
    7.41     {
    7.42         aligned = (UPInt(p) + align-1) & ~(align-1);
    7.43         if (aligned == p) 
    7.44             aligned += align;
    7.45         *(((UPInt*)aligned)-1) = aligned-p;
    7.46     }
    7.47     return (void*)aligned;
    7.48 }
    7.49 
    7.50 void Allocator::FreeAligned(void* p)
    7.51 {
    7.52     UPInt src = UPInt(p) - *(((UPInt*)p)-1);
    7.53     Free((void*)src);
    7.54 }
    7.55 
    7.56 
    7.57 //------------------------------------------------------------------------
    7.58 // ***** Default Allocator
    7.59 
    7.60 // This allocator is created and used if no other allocator is installed.
    7.61 // Default allocator delegates to system malloc.
    7.62 
    7.63 void* DefaultAllocator::Alloc(UPInt size)
    7.64 {
    7.65     return malloc(size);
    7.66 }
    7.67 void* DefaultAllocator::AllocDebug(UPInt size, const char* file, unsigned line)
    7.68 {
    7.69 #if defined(OVR_CC_MSVC) && defined(_CRTDBG_MAP_ALLOC)
    7.70     return _malloc_dbg(size, _NORMAL_BLOCK, file, line);
    7.71 #else
    7.72     OVR_UNUSED2(file, line);
    7.73     return malloc(size);
    7.74 #endif
    7.75 }
    7.76 
    7.77 void* DefaultAllocator::Realloc(void* p, UPInt newSize)
    7.78 {
    7.79     return realloc(p, newSize);
    7.80 }
    7.81 void DefaultAllocator::Free(void *p)
    7.82 {
    7.83     return free(p);
    7.84 }
    7.85 
    7.86 
    7.87 } // OVR
    7.88 \ No newline at end of file
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/libovr/Src/Kernel/OVR_Allocator.h	Sat Sep 14 16:14:59 2013 +0300
     8.3 @@ -0,0 +1,1 @@
     8.4 +/************************************************************************************
     8.5 
     8.6 PublicHeader:   OVR.h
     8.7 Filename    :   OVR_Allocator.h
     8.8 Content     :   Installable memory allocator
     8.9 Created     :   September 19, 2012
    8.10 Notes       : 
    8.11 
    8.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    8.13 
    8.14 Use of this software is subject to the terms of the Oculus license
    8.15 agreement provided at the time of installation or download, or which
    8.16 otherwise accompanies this software in either electronic or hard copy form.
    8.17 
    8.18 ************************************************************************************/
    8.19 
    8.20 #ifndef OVR_Allocator_h
    8.21 #define OVR_Allocator_h
    8.22 
    8.23 #include "OVR_Types.h"
    8.24 
    8.25 //-----------------------------------------------------------------------------------
    8.26 
    8.27 // ***** Disable template-unfriendly MS VC++ warnings
    8.28 #if defined(OVR_CC_MSVC)
    8.29 // Pragma to prevent long name warnings in in VC++
    8.30 #pragma warning(disable : 4503)
    8.31 #pragma warning(disable : 4786)
    8.32 // In MSVC 7.1, warning about placement new POD default initializer
    8.33 #pragma warning(disable : 4345)
    8.34 #endif
    8.35 
    8.36 // Un-define new so that placement constructors work
    8.37 #undef new
    8.38 
    8.39 
    8.40 //-----------------------------------------------------------------------------------
    8.41 // ***** Placement new overrides
    8.42 
    8.43 // Calls constructor on own memory created with "new(ptr) type"
    8.44 #ifndef __PLACEMENT_NEW_INLINE
    8.45 #define __PLACEMENT_NEW_INLINE
    8.46 
    8.47 #   if defined(OVR_CC_MWERKS) || defined(OVR_CC_BORLAND) || defined(OVR_CC_GNU)
    8.48 #      include <new>
    8.49 #   else
    8.50     // Useful on MSVC
    8.51     OVR_FORCE_INLINE void* operator new     (OVR::UPInt n, void *ptr) { OVR_UNUSED(n); return ptr; }
    8.52     OVR_FORCE_INLINE void  operator delete  (void *, void *)     { }
    8.53 #   endif
    8.54 
    8.55 #endif // __PLACEMENT_NEW_INLINE
    8.56 
    8.57 
    8.58 
    8.59 //------------------------------------------------------------------------
    8.60 // ***** Macros to redefine class new/delete operators
    8.61 
    8.62 // Types specifically declared to allow disambiguation of address in
    8.63 // class member operator new.
    8.64 
    8.65 #define OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, check_delete)                          \
    8.66     void*   operator new(UPInt sz)                                                      \
    8.67     { void *p = OVR_ALLOC_DEBUG(sz, __FILE__, __LINE__); return p; }                                              \
    8.68     void*   operator new(UPInt sz, const char* file, int line)                          \
    8.69     { void* p = OVR_ALLOC_DEBUG(sz, file, line); OVR_UNUSED2(file, line); return p; }   \
    8.70     void    operator delete(void *p)                                                    \
    8.71     { check_delete(class_name, p); OVR_FREE(p); }                                       \
    8.72     void    operator delete(void *p, const char*, int)                                  \
    8.73     { check_delete(class_name, p); OVR_FREE(p); }                          
    8.74 
    8.75 #define OVR_MEMORY_DEFINE_PLACEMENT_NEW                                                 \
    8.76     void*   operator new        (UPInt n, void *ptr)    { OVR_UNUSED(n); return ptr; }  \
    8.77     void    operator delete     (void *ptr, void *ptr2) { OVR_UNUSED2(ptr,ptr2); }
    8.78 
    8.79 
    8.80 #define OVR_MEMORY_CHECK_DELETE_NONE(class_name, p)
    8.81 
    8.82 // Redefined all delete/new operators in a class without custom memory initialization
    8.83 #define OVR_MEMORY_REDEFINE_NEW(class_name) \
    8.84     OVR_MEMORY_REDEFINE_NEW_IMPL(class_name, OVR_MEMORY_CHECK_DELETE_NONE)
    8.85 
    8.86 
    8.87 namespace OVR {
    8.88 
    8.89 //-----------------------------------------------------------------------------------
    8.90 // ***** Construct / Destruct
    8.91 
    8.92 // Construct/Destruct functions are useful when new is redefined, as they can
    8.93 // be called instead of placement new constructors.
    8.94 
    8.95 
    8.96 template <class T>
    8.97 OVR_FORCE_INLINE T*  Construct(void *p)
    8.98 {
    8.99     return ::new(p) T;
   8.100 }
   8.101 
   8.102 template <class T>
   8.103 OVR_FORCE_INLINE T*  Construct(void *p, const T& source)
   8.104 {
   8.105     return ::new(p) T(source);
   8.106 }
   8.107 
   8.108 // Same as above, but allows for a different type of constructor.
   8.109 template <class T, class S>
   8.110 OVR_FORCE_INLINE T*  ConstructAlt(void *p, const S& source)
   8.111 {
   8.112     return ::new(p) T(source);
   8.113 }
   8.114 
   8.115 template <class T, class S1, class S2>
   8.116 OVR_FORCE_INLINE T*  ConstructAlt(void *p, const S1& src1, const S2& src2)
   8.117 {
   8.118     return ::new(p) T(src1, src2);
   8.119 }
   8.120 
   8.121 template <class T>
   8.122 OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count)
   8.123 {
   8.124     UByte *pdata = (UByte*)p;
   8.125     for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
   8.126     {
   8.127         Construct<T>(pdata);
   8.128     }
   8.129 }
   8.130 
   8.131 template <class T>
   8.132 OVR_FORCE_INLINE void ConstructArray(void *p, UPInt count, const T& source)
   8.133 {
   8.134     UByte *pdata = (UByte*)p;
   8.135     for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
   8.136     {
   8.137         Construct<T>(pdata, source);
   8.138     }
   8.139 }
   8.140 
   8.141 template <class T>
   8.142 OVR_FORCE_INLINE void Destruct(T *pobj)
   8.143 {
   8.144     pobj->~T();
   8.145     OVR_UNUSED1(pobj); // Fix incorrect 'unused variable' MSVC warning.
   8.146 }
   8.147 
   8.148 template <class T>
   8.149 OVR_FORCE_INLINE void DestructArray(T *pobj, UPInt count)
   8.150 {   
   8.151     for (UPInt i=0; i<count; ++i, ++pobj)
   8.152         pobj->~T();
   8.153 }
   8.154 
   8.155 
   8.156 //-----------------------------------------------------------------------------------
   8.157 // ***** Allocator
   8.158 
   8.159 // Allocator defines a memory allocation interface that developers can override
   8.160 // to to provide memory for OVR; an instance of this class is typically created on
   8.161 // application startup and passed into System or OVR::System constructor.
   8.162 // 
   8.163 //
   8.164 // Users implementing this interface must provide three functions: Alloc, Free,
   8.165 // and Realloc. Implementations of these functions must honor the requested alignment.
   8.166 // Although arbitrary alignment requests are possible, requested alignment will
   8.167 // typically be small, such as 16 bytes or less.
   8.168 
   8.169 class Allocator
   8.170 {
   8.171     friend class System;
   8.172 public:
   8.173 
   8.174     // *** Standard Alignment Alloc/Free
   8.175 
   8.176     // Allocate memory of specified size with default alignment.
   8.177     // Alloc of size==0 will allocate a tiny block & return a valid pointer;
   8.178     // this makes it suitable for new operator.
   8.179     virtual void*   Alloc(UPInt size) = 0;
   8.180     // Same as Alloc, but provides an option of passing debug data.
   8.181     virtual void*   AllocDebug(UPInt size, const char* file, unsigned line)
   8.182     { OVR_UNUSED2(file, line); return Alloc(size); }
   8.183 
   8.184     // Reallocate memory block to a new size, copying data if necessary. Returns the pointer to
   8.185     // new memory block, which may be the same as original pointer. Will return 0 if reallocation
   8.186     // failed, in which case previous memory is still valid.
   8.187     // Realloc to decrease size will never fail.
   8.188     // Realloc of pointer == 0 is equivalent to Alloc
   8.189     // Realloc to size == 0, shrinks to the minimal size, pointer remains valid and requires Free().
   8.190     virtual void*   Realloc(void* p, UPInt newSize) = 0;
   8.191 
   8.192     // Frees memory allocated by Alloc/Realloc.
   8.193     // Free of null pointer is valid and will do nothing.
   8.194     virtual void    Free(void *p) = 0;
   8.195 
   8.196 
   8.197     // *** Standard Alignment Alloc/Free
   8.198 
   8.199     // Allocate memory of specified alignment.
   8.200     // Memory allocated with AllocAligned MUST be freed with FreeAligned.
   8.201     // Default implementation will delegate to Alloc/Free after doing rounding.
   8.202     virtual void*   AllocAligned(UPInt size, UPInt align);    
   8.203     // Frees memory allocated with AllocAligned.
   8.204     virtual void    FreeAligned(void* p);
   8.205     
   8.206     // Returns the pointer to the current globally installed Allocator instance.
   8.207     // This pointer is used for most of the memory allocations.
   8.208     static Allocator* GetInstance() { return pInstance; }
   8.209 
   8.210 
   8.211 protected:
   8.212     // onSystemShutdown is called on the allocator during System::Shutdown.
   8.213     // At this point, all allocations should've been freed.
   8.214     virtual void    onSystemShutdown() { }
   8.215 
   8.216 public:
   8.217     static  void    setInstance(Allocator* palloc)    
   8.218     {
   8.219         OVR_ASSERT((pInstance == 0) || (palloc == 0));
   8.220         pInstance = palloc;
   8.221     }
   8.222 
   8.223 private:
   8.224 
   8.225     static Allocator* pInstance;
   8.226 };
   8.227 
   8.228 
   8.229 
   8.230 //------------------------------------------------------------------------
   8.231 // ***** Allocator_SingletonSupport
   8.232 
   8.233 // Allocator_SingletonSupport is a Allocator wrapper class that implements
   8.234 // the InitSystemSingleton static function, used to create a global singleton
   8.235 // used for the OVR::System default argument initialization.
   8.236 //
   8.237 // End users implementing custom Allocator interface don't need to make use of this base
   8.238 // class; they can just create an instance of their own class on stack and pass it to System.
   8.239 
   8.240 template<class D>
   8.241 class Allocator_SingletonSupport : public Allocator
   8.242 {
   8.243     struct AllocContainer
   8.244     {        
   8.245         UPInt Data[(sizeof(D) + sizeof(UPInt)-1) / sizeof(UPInt)];
   8.246         bool  Initialized;
   8.247         AllocContainer() : Initialized(0) { }
   8.248     };
   8.249 
   8.250     AllocContainer* pContainer;
   8.251 
   8.252 public:
   8.253     Allocator_SingletonSupport() : pContainer(0) { }
   8.254 
   8.255     // Creates a singleton instance of this Allocator class used
   8.256     // on OVR_DEFAULT_ALLOCATOR during System initialization.
   8.257     static  D*  InitSystemSingleton()
   8.258     {
   8.259         static AllocContainer Container;
   8.260         OVR_ASSERT(Container.Initialized == false);
   8.261 
   8.262         Allocator_SingletonSupport<D> *presult = Construct<D>((void*)Container.Data);
   8.263         presult->pContainer   = &Container;
   8.264         Container.Initialized = true;
   8.265         return (D*)presult;
   8.266     }
   8.267 
   8.268 protected:
   8.269     virtual void onSystemShutdown()
   8.270     {
   8.271         Allocator::onSystemShutdown();
   8.272         if (pContainer)
   8.273         {
   8.274             pContainer->Initialized = false;
   8.275             Destruct((D*)this);
   8.276             pContainer = 0;
   8.277         }
   8.278     }
   8.279 };
   8.280 
   8.281 //------------------------------------------------------------------------
   8.282 // ***** Default Allocator
   8.283 
   8.284 // This allocator is created and used if no other allocator is installed.
   8.285 // Default allocator delegates to system malloc.
   8.286 
   8.287 class DefaultAllocator : public Allocator_SingletonSupport<DefaultAllocator>
   8.288 {
   8.289 public:
   8.290     virtual void*   Alloc(UPInt size);
   8.291     virtual void*   AllocDebug(UPInt size, const char* file, unsigned line);
   8.292     virtual void*   Realloc(void* p, UPInt newSize);
   8.293     virtual void    Free(void *p);
   8.294 };
   8.295 
   8.296 
   8.297 //------------------------------------------------------------------------
   8.298 // ***** Memory Allocation Macros
   8.299 
   8.300 // These macros should be used for global allocation. In the future, these
   8.301 // macros will allows allocation to be extended with debug file/line information
   8.302 // if necessary.
   8.303 
   8.304 #define OVR_REALLOC(p,s)        OVR::Allocator::GetInstance()->Realloc((p),(s))
   8.305 #define OVR_FREE(p)             OVR::Allocator::GetInstance()->Free((p))
   8.306 #define OVR_ALLOC_ALIGNED(s,a)  OVR::Allocator::GetInstance()->AllocAligned((s),(a))
   8.307 #define OVR_FREE_ALIGNED(p)     OVR::Allocator::GetInstance()->FreeAligned((p))
   8.308 
   8.309 #ifdef OVR_BUILD_DEBUG
   8.310 #define OVR_ALLOC(s)            OVR::Allocator::GetInstance()->AllocDebug((s), __FILE__, __LINE__)
   8.311 #define OVR_ALLOC_DEBUG(s,f,l)  OVR::Allocator::GetInstance()->AllocDebug((s), f, l)
   8.312 #else
   8.313 #define OVR_ALLOC(s)            OVR::Allocator::GetInstance()->Alloc((s))
   8.314 #define OVR_ALLOC_DEBUG(s,f,l)  OVR::Allocator::GetInstance()->Alloc((s))
   8.315 #endif
   8.316 
   8.317 //------------------------------------------------------------------------
   8.318 
   8.319 // Base class that overrides the new and delete operators.
   8.320 // Deriving from this class, even as a multiple base, incurs no space overhead.
   8.321 class NewOverrideBase
   8.322 {
   8.323 public:
   8.324 
   8.325     // Redefine all new & delete operators.
   8.326     OVR_MEMORY_REDEFINE_NEW(NewOverrideBase)
   8.327 };
   8.328 
   8.329 
   8.330 } // OVR
   8.331 
   8.332 
   8.333 // Redefine operator 'new' if necessary.
   8.334 #if defined(OVR_DEFINE_NEW)
   8.335 #define new OVR_DEFINE_NEW
   8.336 #endif
   8.337 
   8.338 
   8.339 #endif // OVR_Memory
   8.340 \ No newline at end of file
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/libovr/Src/Kernel/OVR_Array.h	Sat Sep 14 16:14:59 2013 +0300
     9.3 @@ -0,0 +1,1 @@
     9.4 +/************************************************************************************
     9.5 
     9.6 PublicHeader:   OVR.h
     9.7 Filename    :   OVR_Array.h
     9.8 Content     :   Template implementation for Array
     9.9 Created     :   September 19, 2012
    9.10 Notes       : 
    9.11 
    9.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    9.13 
    9.14 Use of this software is subject to the terms of the Oculus license
    9.15 agreement provided at the time of installation or download, or which
    9.16 otherwise accompanies this software in either electronic or hard copy form.
    9.17 
    9.18 ************************************************************************************/
    9.19 
    9.20 #ifndef OVR_Array_h
    9.21 #define OVR_Array_h
    9.22 
    9.23 #include "OVR_ContainerAllocator.h"
    9.24 
    9.25 namespace OVR {
    9.26 
    9.27 //-----------------------------------------------------------------------------------
    9.28 // ***** ArrayDefaultPolicy
    9.29 //
    9.30 // Default resize behavior. No minimal capacity, Granularity=4, 
    9.31 // Shrinking as needed. ArrayConstPolicy actually is the same as 
    9.32 // ArrayDefaultPolicy, but parametrized with constants. 
    9.33 // This struct is used only in order to reduce the template "matroska".
    9.34 struct ArrayDefaultPolicy
    9.35 {
    9.36     ArrayDefaultPolicy() : Capacity(0) {}
    9.37     ArrayDefaultPolicy(const ArrayDefaultPolicy&) : Capacity(0) {}
    9.38 
    9.39     UPInt GetMinCapacity() const { return 0; }
    9.40     UPInt GetGranularity() const { return 4; }
    9.41     bool  NeverShrinking() const { return 0; }
    9.42 
    9.43     UPInt GetCapacity()    const      { return Capacity; }
    9.44     void  SetCapacity(UPInt capacity) { Capacity = capacity; }
    9.45 private:
    9.46     UPInt Capacity;
    9.47 };
    9.48 
    9.49 
    9.50 //-----------------------------------------------------------------------------------
    9.51 // ***** ArrayConstPolicy
    9.52 //
    9.53 // Statically parametrized resizing behavior:
    9.54 // MinCapacity, Granularity, and Shrinking flag.
    9.55 template<int MinCapacity=0, int Granularity=4, bool NeverShrink=false>
    9.56 struct ArrayConstPolicy
    9.57 {
    9.58     typedef ArrayConstPolicy<MinCapacity, Granularity, NeverShrink> SelfType;
    9.59 
    9.60     ArrayConstPolicy() : Capacity(0) {}
    9.61     ArrayConstPolicy(const SelfType&) : Capacity(0) {}
    9.62 
    9.63     UPInt GetMinCapacity() const { return MinCapacity; }
    9.64     UPInt GetGranularity() const { return Granularity; }
    9.65     bool  NeverShrinking() const { return NeverShrink; }
    9.66 
    9.67     UPInt GetCapacity()    const      { return Capacity; }
    9.68     void  SetCapacity(UPInt capacity) { Capacity = capacity; }
    9.69 private:
    9.70     UPInt Capacity;
    9.71 };
    9.72 
    9.73 //-----------------------------------------------------------------------------------
    9.74 // ***** ArrayDataBase
    9.75 //
    9.76 // Basic operations with array data: Reserve, Resize, Free, ArrayPolicy.
    9.77 // For internal use only: ArrayData,ArrayDataCC and others.
    9.78 template<class T, class Allocator, class SizePolicy>
    9.79 struct ArrayDataBase
    9.80 {
    9.81     typedef T                                           ValueType;
    9.82     typedef Allocator                                   AllocatorType;
    9.83     typedef SizePolicy                                  SizePolicyType;
    9.84     typedef ArrayDataBase<T, Allocator, SizePolicy>     SelfType;
    9.85 
    9.86     ArrayDataBase()
    9.87         : Data(0), Size(0), Policy() {}
    9.88 
    9.89     ArrayDataBase(const SizePolicy& p)
    9.90         : Data(0), Size(0), Policy(p) {}
    9.91 
    9.92     ~ArrayDataBase() 
    9.93     {
    9.94         Allocator::DestructArray(Data, Size);
    9.95         Allocator::Free(Data);
    9.96     }
    9.97 
    9.98     UPInt GetCapacity() const 
    9.99     { 
   9.100         return Policy.GetCapacity(); 
   9.101     }
   9.102 
   9.103     void ClearAndRelease()
   9.104     {
   9.105         Allocator::DestructArray(Data, Size);
   9.106         Allocator::Free(Data);
   9.107         Data = 0;
   9.108         Size = 0;
   9.109         Policy.SetCapacity(0);
   9.110     }
   9.111 
   9.112     void Reserve(UPInt newCapacity)
   9.113     {
   9.114         if (Policy.NeverShrinking() && newCapacity < GetCapacity())
   9.115             return;
   9.116 
   9.117         if (newCapacity < Policy.GetMinCapacity())
   9.118             newCapacity = Policy.GetMinCapacity();
   9.119 
   9.120         // Resize the buffer.
   9.121         if (newCapacity == 0)
   9.122         {
   9.123             if (Data)
   9.124             {
   9.125                 Allocator::Free(Data);
   9.126                 Data = 0;
   9.127             }
   9.128             Policy.SetCapacity(0);
   9.129         }
   9.130         else
   9.131         {
   9.132             UPInt gran = Policy.GetGranularity();
   9.133             newCapacity = (newCapacity + gran - 1) / gran * gran;
   9.134             if (Data)
   9.135             {
   9.136                 if (Allocator::IsMovable())
   9.137                 {
   9.138                     Data = (T*)Allocator::Realloc(Data, sizeof(T) * newCapacity);
   9.139                 }
   9.140                 else
   9.141                 {
   9.142                     T* newData = (T*)Allocator::Alloc(sizeof(T) * newCapacity);
   9.143                     UPInt i, s;
   9.144                     s = (Size < newCapacity) ? Size : newCapacity;
   9.145                     for (i = 0; i < s; ++i)
   9.146                     {
   9.147                         Allocator::Construct(&newData[i], Data[i]);
   9.148                         Allocator::Destruct(&Data[i]);
   9.149                     }
   9.150                     for (i = s; i < Size; ++i)
   9.151                     {
   9.152                         Allocator::Destruct(&Data[i]);
   9.153                     }
   9.154                     Allocator::Free(Data);
   9.155                     Data = newData;
   9.156                 }
   9.157             }
   9.158             else
   9.159             {
   9.160                 Data = (T*)Allocator::Alloc(sizeof(T) * newCapacity);
   9.161                 //memset(Buffer, 0, (sizeof(ValueType) * newSize)); // Do we need this?
   9.162             }
   9.163             Policy.SetCapacity(newCapacity);
   9.164             // OVR_ASSERT(Data); // need to throw (or something) on alloc failure!
   9.165         }
   9.166     }
   9.167 
   9.168     // This version of Resize DOES NOT construct the elements.
   9.169     // It's done to optimize PushBack, which uses a copy constructor 
   9.170     // instead of the default constructor and assignment
   9.171     void ResizeNoConstruct(UPInt newSize)
   9.172     {
   9.173         UPInt oldSize = Size;
   9.174 
   9.175         if (newSize < oldSize)
   9.176         {
   9.177             Allocator::DestructArray(Data + newSize, oldSize - newSize);
   9.178             if (newSize < (Policy.GetCapacity() >> 1))
   9.179             {
   9.180                 Reserve(newSize);
   9.181             }
   9.182         }
   9.183         else if(newSize >= Policy.GetCapacity())
   9.184         {
   9.185             Reserve(newSize + (newSize >> 2));
   9.186         }
   9.187         //! IMPORTANT to modify Size only after Reserve completes, because garbage collectable
   9.188         // array may use this array and may traverse it during Reserve (in the case, if 
   9.189         // collection occurs because of heap limit exceeded).
   9.190         Size = newSize;
   9.191     }
   9.192 
   9.193     ValueType*  Data;
   9.194     UPInt       Size;
   9.195     SizePolicy  Policy;
   9.196 };
   9.197 
   9.198 
   9.199 
   9.200 //-----------------------------------------------------------------------------------
   9.201 // ***** ArrayData
   9.202 //
   9.203 // General purpose array data.
   9.204 // For internal use only in Array, ArrayLH, ArrayPOD and so on.
   9.205 template<class T, class Allocator, class SizePolicy>
   9.206 struct ArrayData : ArrayDataBase<T, Allocator, SizePolicy>
   9.207 {
   9.208     typedef T ValueType;
   9.209     typedef Allocator                                   AllocatorType;
   9.210     typedef SizePolicy                                  SizePolicyType;
   9.211     typedef ArrayDataBase<T, Allocator, SizePolicy>     BaseType;
   9.212     typedef ArrayData    <T, Allocator, SizePolicy>     SelfType;
   9.213 
   9.214     ArrayData()
   9.215         : BaseType() { }
   9.216 
   9.217     ArrayData(int size)
   9.218         : BaseType() { Resize(size); }
   9.219 
   9.220     ArrayData(const SelfType& a)
   9.221         : BaseType(a.Policy) { Append(a.Data, a.Size); }
   9.222 
   9.223 
   9.224     void Resize(UPInt newSize)
   9.225     {
   9.226         UPInt oldSize = this->Size;
   9.227         BaseType::ResizeNoConstruct(newSize);
   9.228         if(newSize > oldSize)
   9.229             Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize);
   9.230     }
   9.231 
   9.232     void PushBack(const ValueType& val)
   9.233     {
   9.234         BaseType::ResizeNoConstruct(this->Size + 1);
   9.235         Allocator::Construct(this->Data + this->Size - 1, val);
   9.236     }
   9.237 
   9.238     template<class S>
   9.239     void PushBackAlt(const S& val)
   9.240     {
   9.241         BaseType::ResizeNoConstruct(this->Size + 1);
   9.242         Allocator::ConstructAlt(this->Data + this->Size - 1, val);
   9.243     }
   9.244 
   9.245     // Append the given data to the array.
   9.246     void Append(const ValueType other[], UPInt count)
   9.247     {
   9.248         if (count)
   9.249         {
   9.250             UPInt oldSize = this->Size;
   9.251             BaseType::ResizeNoConstruct(this->Size + count);
   9.252             Allocator::ConstructArray(this->Data + oldSize, count, other);
   9.253         }
   9.254     }
   9.255 };
   9.256 
   9.257 
   9.258 
   9.259 //-----------------------------------------------------------------------------------
   9.260 // ***** ArrayDataCC
   9.261 //
   9.262 // A modification of ArrayData that always copy-constructs new elements
   9.263 // using a specified DefaultValue. For internal use only in ArrayCC.
   9.264 template<class T, class Allocator, class SizePolicy>
   9.265 struct ArrayDataCC : ArrayDataBase<T, Allocator, SizePolicy>
   9.266 {
   9.267     typedef T                                           ValueType;
   9.268     typedef Allocator                                   AllocatorType;
   9.269     typedef SizePolicy                                  SizePolicyType;
   9.270     typedef ArrayDataBase<T, Allocator, SizePolicy>     BaseType;
   9.271     typedef ArrayDataCC  <T, Allocator, SizePolicy>     SelfType;
   9.272 
   9.273     ArrayDataCC(const ValueType& defval)
   9.274         : BaseType(), DefaultValue(defval) { }
   9.275 
   9.276     ArrayDataCC(const ValueType& defval, int size)
   9.277         : BaseType(), DefaultValue(defval) { Resize(size); }
   9.278 
   9.279     ArrayDataCC(const SelfType& a)
   9.280         : BaseType(a.Policy), DefaultValue(a.DefaultValue) { Append(a.Data, a.Size); }
   9.281 
   9.282 
   9.283     void Resize(UPInt newSize)
   9.284     {
   9.285         UPInt oldSize = this->Size;
   9.286         BaseType::ResizeNoConstruct(newSize);
   9.287         if(newSize > oldSize)
   9.288             Allocator::ConstructArray(this->Data + oldSize, newSize - oldSize, DefaultValue);
   9.289     }
   9.290 
   9.291     void PushBack(const ValueType& val)
   9.292     {
   9.293         BaseType::ResizeNoConstruct(this->Size + 1);
   9.294         Allocator::Construct(this->Data + this->Size - 1, val);
   9.295     }
   9.296 
   9.297     template<class S>
   9.298     void PushBackAlt(const S& val)
   9.299     {
   9.300         BaseType::ResizeNoConstruct(this->Size + 1);
   9.301         Allocator::ConstructAlt(this->Data + this->Size - 1, val);
   9.302     }
   9.303 
   9.304     // Append the given data to the array.
   9.305     void Append(const ValueType other[], UPInt count)
   9.306     {
   9.307         if (count)
   9.308         {
   9.309             UPInt oldSize = this->Size;
   9.310             BaseType::ResizeNoConstruct(this->Size + count);
   9.311             Allocator::ConstructArray(this->Data + oldSize, count, other);
   9.312         }
   9.313     }
   9.314 
   9.315     ValueType   DefaultValue;
   9.316 };
   9.317 
   9.318 
   9.319 
   9.320 
   9.321 
   9.322 //-----------------------------------------------------------------------------------
   9.323 // ***** ArrayBase
   9.324 //
   9.325 // Resizable array. The behavior can be POD (suffix _POD) and 
   9.326 // Movable (no suffix) depending on the allocator policy.
   9.327 // In case of _POD the constructors and destructors are not called.
   9.328 // 
   9.329 // Arrays can't handle non-movable objects! Don't put anything in here 
   9.330 // that can't be moved around by bitwise copy. 
   9.331 // 
   9.332 // The addresses of elements are not persistent! Don't keep the address 
   9.333 // of an element; the array contents will move around as it gets resized.
   9.334 template<class ArrayData>
   9.335 class ArrayBase
   9.336 {
   9.337 public:
   9.338     typedef typename ArrayData::ValueType       ValueType;
   9.339     typedef typename ArrayData::AllocatorType   AllocatorType;
   9.340     typedef typename ArrayData::SizePolicyType  SizePolicyType;
   9.341     typedef ArrayBase<ArrayData>                SelfType;
   9.342 
   9.343 
   9.344 #undef new
   9.345     OVR_MEMORY_REDEFINE_NEW(ArrayBase)
   9.346 // Redefine operator 'new' if necessary.
   9.347 #if defined(OVR_DEFINE_NEW)
   9.348 #define new OVR_DEFINE_NEW
   9.349 #endif
   9.350 
   9.351 
   9.352     ArrayBase()
   9.353         : Data() {}
   9.354     ArrayBase(int size)
   9.355         : Data(size) {}
   9.356     ArrayBase(const SelfType& a)
   9.357         : Data(a.Data) {}
   9.358 
   9.359     ArrayBase(const ValueType& defval)
   9.360         : Data(defval) {}
   9.361     ArrayBase(const ValueType& defval, int size)
   9.362         : Data(defval, size) {}
   9.363   
   9.364     SizePolicyType* GetSizePolicy() const                  { return Data.Policy; }
   9.365     void            SetSizePolicy(const SizePolicyType& p) { Data.Policy = p; }
   9.366 
   9.367     bool    NeverShrinking()const       { return Data.Policy.NeverShrinking(); }
   9.368     UPInt   GetSize()       const       { return Data.Size;  }
   9.369     bool    IsEmpty()       const       { return Data.Size == 0; }
   9.370     UPInt   GetCapacity()   const       { return Data.GetCapacity(); }
   9.371     UPInt   GetNumBytes()   const       { return Data.GetCapacity() * sizeof(ValueType); }
   9.372 
   9.373     void    ClearAndRelease()           { Data.ClearAndRelease(); }
   9.374     void    Clear()                     { Data.Resize(0); }
   9.375     void    Resize(UPInt newSize)       { Data.Resize(newSize); }
   9.376 
   9.377     // Reserve can only increase the capacity
   9.378     void    Reserve(UPInt newCapacity)  
   9.379     { 
   9.380         if (newCapacity > Data.GetCapacity())
   9.381             Data.Reserve(newCapacity); 
   9.382     }
   9.383 
   9.384     // Basic access.
   9.385     ValueType& At(UPInt index)
   9.386     {
   9.387         OVR_ASSERT(index < Data.Size);
   9.388         return Data.Data[index]; 
   9.389     }
   9.390     const ValueType& At(UPInt index) const
   9.391     {
   9.392         OVR_ASSERT(index < Data.Size);
   9.393         return Data.Data[index]; 
   9.394     }
   9.395 
   9.396     ValueType ValueAt(UPInt index) const
   9.397     {
   9.398         OVR_ASSERT(index < Data.Size);
   9.399         return Data.Data[index]; 
   9.400     }
   9.401 
   9.402     // Basic access.
   9.403     ValueType& operator [] (UPInt index)
   9.404     {
   9.405         OVR_ASSERT(index < Data.Size);
   9.406         return Data.Data[index]; 
   9.407     }
   9.408     const ValueType& operator [] (UPInt index) const
   9.409     {
   9.410         OVR_ASSERT(index < Data.Size);
   9.411         return Data.Data[index]; 
   9.412     }
   9.413 
   9.414     // Raw pointer to the data. Use with caution!
   9.415     const ValueType* GetDataPtr() const { return Data.Data; }
   9.416           ValueType* GetDataPtr()       { return Data.Data; }
   9.417 
   9.418     // Insert the given element at the end of the array.
   9.419     void    PushBack(const ValueType& val)
   9.420     {
   9.421         // DO NOT pass elements of your own vector into
   9.422         // push_back()!  Since we're using references,
   9.423         // resize() may munge the element storage!
   9.424         // OVR_ASSERT(&val < &Buffer[0] || &val > &Buffer[BufferSize]);
   9.425         Data.PushBack(val);
   9.426     }
   9.427 
   9.428     template<class S>
   9.429     void PushBackAlt(const S& val)
   9.430     {
   9.431         Data.PushBackAlt(val);
   9.432     }
   9.433 
   9.434     // Remove the last element.
   9.435     void    PopBack(UPInt count = 1)
   9.436     {
   9.437         OVR_ASSERT(Data.Size >= count);
   9.438         Data.Resize(Data.Size - count);
   9.439     }
   9.440 
   9.441     ValueType& PushDefault()
   9.442     {
   9.443         Data.PushBack(ValueType());
   9.444         return Back();
   9.445     }
   9.446 
   9.447     ValueType Pop()
   9.448     {
   9.449         ValueType t = Back();
   9.450         PopBack();
   9.451         return t;
   9.452     }
   9.453 
   9.454 
   9.455     // Access the first element.
   9.456     ValueType&          Front()         { return At(0); }
   9.457     const ValueType&    Front() const   { return At(0); }
   9.458 
   9.459     // Access the last element.
   9.460     ValueType&          Back()          { return At(Data.Size - 1); }
   9.461     const ValueType&    Back() const    { return At(Data.Size - 1); }
   9.462 
   9.463     // Array copy.  Copies the contents of a into this array.
   9.464     const SelfType& operator = (const SelfType& a)   
   9.465     {
   9.466         Resize(a.GetSize());
   9.467         for (UPInt i = 0; i < Data.Size; i++) {
   9.468             *(Data.Data + i) = a[i];
   9.469         }
   9.470         return *this;
   9.471     }
   9.472 
   9.473     // Removing multiple elements from the array.
   9.474     void    RemoveMultipleAt(UPInt index, UPInt num)
   9.475     {
   9.476         OVR_ASSERT(index + num <= Data.Size);
   9.477         if (Data.Size == num)
   9.478         {
   9.479             Clear();
   9.480         }
   9.481         else
   9.482         {
   9.483             AllocatorType::DestructArray(Data.Data + index, num);
   9.484             AllocatorType::CopyArrayForward(
   9.485                 Data.Data + index, 
   9.486                 Data.Data + index + num,
   9.487                 Data.Size - num - index);
   9.488             Data.Size -= num;
   9.489         }
   9.490     }
   9.491 
   9.492     // Removing an element from the array is an expensive operation!
   9.493     // It compacts only after removing the last element.
   9.494     void    RemoveAt(UPInt index)
   9.495     {
   9.496         OVR_ASSERT(index < Data.Size);
   9.497         if (Data.Size == 1)
   9.498         {
   9.499             Clear();
   9.500         }
   9.501         else
   9.502         {
   9.503             AllocatorType::Destruct(Data.Data + index);
   9.504             AllocatorType::CopyArrayForward(
   9.505                 Data.Data + index, 
   9.506                 Data.Data + index + 1,
   9.507                 Data.Size - 1 - index);
   9.508             --Data.Size;
   9.509         }
   9.510     }
   9.511 
   9.512     // Insert the given object at the given index shifting all the elements up.
   9.513     void    InsertAt(UPInt index, const ValueType& val = ValueType())
   9.514     {
   9.515         OVR_ASSERT(index <= Data.Size);
   9.516 
   9.517         Data.Resize(Data.Size + 1);
   9.518         if (index < Data.Size - 1)
   9.519         {
   9.520             AllocatorType::CopyArrayBackward(
   9.521                 Data.Data + index + 1, 
   9.522                 Data.Data + index, 
   9.523                 Data.Size - 1 - index);
   9.524         }
   9.525         AllocatorType::Construct(Data.Data + index, val);
   9.526     }
   9.527 
   9.528     // Insert the given object at the given index shifting all the elements up.
   9.529     void    InsertMultipleAt(UPInt index, UPInt num, const ValueType& val = ValueType())
   9.530     {
   9.531         OVR_ASSERT(index <= Data.Size);
   9.532 
   9.533         Data.Resize(Data.Size + num);
   9.534         if (index < Data.Size - num)
   9.535         {
   9.536             AllocatorType::CopyArrayBackward(
   9.537                 Data.Data + index + num,
   9.538                 Data.Data + index,
   9.539                 Data.Size - num - index);
   9.540         }
   9.541         for (UPInt i = 0; i < num; ++i)
   9.542             AllocatorType::Construct(Data.Data + index + i, val);
   9.543     }
   9.544 
   9.545     // Append the given data to the array.
   9.546     void    Append(const SelfType& other)
   9.547     {
   9.548         Append(other.Data.Data, other.GetSize());
   9.549     }
   9.550 
   9.551     // Append the given data to the array.
   9.552     void    Append(const ValueType other[], UPInt count)
   9.553     {
   9.554         Data.Append(other, count);
   9.555     }
   9.556 
   9.557     class Iterator
   9.558     {
   9.559         SelfType*       pArray;
   9.560         SPInt           CurIndex;
   9.561 
   9.562     public:
   9.563         Iterator() : pArray(0), CurIndex(-1) {}
   9.564         Iterator(SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {}
   9.565 
   9.566         bool operator==(const Iterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; }
   9.567         bool operator!=(const Iterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; }
   9.568 
   9.569         Iterator& operator++()
   9.570         {
   9.571             if (pArray)
   9.572             {
   9.573                 if (CurIndex < (SPInt)pArray->GetSize())
   9.574                     ++CurIndex;
   9.575             }
   9.576             return *this;
   9.577         }
   9.578         Iterator operator++(int)
   9.579         {
   9.580             Iterator it(*this);
   9.581             operator++();
   9.582             return it;
   9.583         }
   9.584         Iterator& operator--()
   9.585         {
   9.586             if (pArray)
   9.587             {
   9.588                 if (CurIndex >= 0)
   9.589                     --CurIndex;
   9.590             }
   9.591             return *this;
   9.592         }
   9.593         Iterator operator--(int)
   9.594         {
   9.595             Iterator it(*this);
   9.596             operator--();
   9.597             return it;
   9.598         }
   9.599         Iterator operator+(int delta) const
   9.600         {
   9.601             return Iterator(pArray, CurIndex + delta);
   9.602         }
   9.603         Iterator operator-(int delta) const
   9.604         {
   9.605             return Iterator(pArray, CurIndex - delta);
   9.606         }
   9.607         SPInt operator-(const Iterator& right) const
   9.608         {
   9.609             OVR_ASSERT(pArray == right.pArray);
   9.610             return CurIndex - right.CurIndex;
   9.611         }
   9.612         ValueType& operator*() const    { OVR_ASSERT(pArray); return  (*pArray)[CurIndex]; }
   9.613         ValueType* operator->() const   { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
   9.614         ValueType* GetPtr() const       { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
   9.615 
   9.616         bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); }
   9.617 
   9.618         void Remove()
   9.619         {
   9.620             if (!IsFinished())
   9.621                 pArray->RemoveAt(CurIndex);
   9.622         }
   9.623 
   9.624         SPInt GetIndex() const { return CurIndex; }
   9.625     };
   9.626 
   9.627     Iterator Begin() { return Iterator(this); }
   9.628     Iterator End()   { return Iterator(this, (SPInt)GetSize()); }
   9.629     Iterator Last()  { return Iterator(this, (SPInt)GetSize() - 1); }
   9.630 
   9.631     class ConstIterator
   9.632     {
   9.633         const SelfType* pArray;
   9.634         SPInt           CurIndex;
   9.635 
   9.636     public:
   9.637         ConstIterator() : pArray(0), CurIndex(-1) {}
   9.638         ConstIterator(const SelfType* parr, SPInt idx = 0) : pArray(parr), CurIndex(idx) {}
   9.639 
   9.640         bool operator==(const ConstIterator& it) const { return pArray == it.pArray && CurIndex == it.CurIndex; }
   9.641         bool operator!=(const ConstIterator& it) const { return pArray != it.pArray || CurIndex != it.CurIndex; }
   9.642 
   9.643         ConstIterator& operator++()
   9.644         {
   9.645             if (pArray)
   9.646             {
   9.647                 if (CurIndex < (int)pArray->GetSize())
   9.648                     ++CurIndex;
   9.649             }
   9.650             return *this;
   9.651         }
   9.652         ConstIterator operator++(int)
   9.653         {
   9.654             ConstIterator it(*this);
   9.655             operator++();
   9.656             return it;
   9.657         }
   9.658         ConstIterator& operator--()
   9.659         {
   9.660             if (pArray)
   9.661             {
   9.662                 if (CurIndex >= 0)
   9.663                     --CurIndex;
   9.664             }
   9.665             return *this;
   9.666         }
   9.667         ConstIterator operator--(int)
   9.668         {
   9.669             ConstIterator it(*this);
   9.670             operator--();
   9.671             return it;
   9.672         }
   9.673         ConstIterator operator+(int delta) const
   9.674         {
   9.675             return ConstIterator(pArray, CurIndex + delta);
   9.676         }
   9.677         ConstIterator operator-(int delta) const
   9.678         {
   9.679             return ConstIterator(pArray, CurIndex - delta);
   9.680         }
   9.681         SPInt operator-(const ConstIterator& right) const
   9.682         {
   9.683             OVR_ASSERT(pArray == right.pArray);
   9.684             return CurIndex - right.CurIndex;
   9.685         }
   9.686         const ValueType& operator*() const  { OVR_ASSERT(pArray); return  (*pArray)[CurIndex]; }
   9.687         const ValueType* operator->() const { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
   9.688         const ValueType* GetPtr() const     { OVR_ASSERT(pArray); return &(*pArray)[CurIndex]; }
   9.689 
   9.690         bool IsFinished() const { return !pArray || CurIndex < 0 || CurIndex >= (int)pArray->GetSize(); }
   9.691 
   9.692         SPInt GetIndex()  const { return CurIndex; }
   9.693     };
   9.694     ConstIterator Begin() const { return ConstIterator(this); }
   9.695     ConstIterator End() const   { return ConstIterator(this, (SPInt)GetSize()); }
   9.696     ConstIterator Last() const  { return ConstIterator(this, (SPInt)GetSize() - 1); }
   9.697 
   9.698 protected:
   9.699     ArrayData   Data;
   9.700 };
   9.701 
   9.702 
   9.703 
   9.704 //-----------------------------------------------------------------------------------
   9.705 // ***** Array
   9.706 //
   9.707 // General purpose array for movable objects that require explicit 
   9.708 // construction/destruction.
   9.709 template<class T, class SizePolicy=ArrayDefaultPolicy>
   9.710 class Array : public ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> >
   9.711 {
   9.712 public:
   9.713     typedef T                                                           ValueType;
   9.714     typedef ContainerAllocator<T>                                       AllocatorType;
   9.715     typedef SizePolicy                                                  SizePolicyType;
   9.716     typedef Array<T, SizePolicy>                                        SelfType;
   9.717     typedef ArrayBase<ArrayData<T, ContainerAllocator<T>, SizePolicy> > BaseType;
   9.718 
   9.719     Array() : BaseType() {}
   9.720     Array(int size) : BaseType(size) {}
   9.721     Array(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
   9.722     Array(const SelfType& a) : BaseType(a) {}
   9.723     const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
   9.724 };
   9.725 
   9.726 // ***** ArrayPOD
   9.727 //
   9.728 // General purpose array for movable objects that DOES NOT require  
   9.729 // construction/destruction. Constructors and destructors are not called! 
   9.730 // Global heap is in use.
   9.731 template<class T, class SizePolicy=ArrayDefaultPolicy>
   9.732 class ArrayPOD : public ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> >
   9.733 {
   9.734 public:
   9.735     typedef T                                                               ValueType;
   9.736     typedef ContainerAllocator_POD<T>                                       AllocatorType;
   9.737     typedef SizePolicy                                                      SizePolicyType;
   9.738     typedef ArrayPOD<T, SizePolicy>                                         SelfType;
   9.739     typedef ArrayBase<ArrayData<T, ContainerAllocator_POD<T>, SizePolicy> > BaseType;
   9.740 
   9.741     ArrayPOD() : BaseType() {}
   9.742     ArrayPOD(int size) : BaseType(size) {}
   9.743     ArrayPOD(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
   9.744     ArrayPOD(const SelfType& a) : BaseType(a) {}
   9.745     const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
   9.746 };
   9.747 
   9.748 
   9.749 // ***** ArrayCPP
   9.750 //
   9.751 // General purpose, fully C++ compliant array. Can be used with non-movable data.
   9.752 // Global heap is in use.
   9.753 template<class T, class SizePolicy=ArrayDefaultPolicy>
   9.754 class ArrayCPP : public ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> >
   9.755 {
   9.756 public:
   9.757     typedef T                                                               ValueType;
   9.758     typedef ContainerAllocator_CPP<T>                                       AllocatorType;
   9.759     typedef SizePolicy                                                      SizePolicyType;
   9.760     typedef ArrayCPP<T, SizePolicy>                                         SelfType;
   9.761     typedef ArrayBase<ArrayData<T, ContainerAllocator_CPP<T>, SizePolicy> > BaseType;
   9.762 
   9.763     ArrayCPP() : BaseType() {}
   9.764     ArrayCPP(int size) : BaseType(size) {}
   9.765     ArrayCPP(const SizePolicyType& p) : BaseType() { SetSizePolicy(p); }
   9.766     ArrayCPP(const SelfType& a) : BaseType(a) {}
   9.767     const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
   9.768 };
   9.769 
   9.770 
   9.771 // ***** ArrayCC
   9.772 //
   9.773 // A modification of the array that uses the given default value to
   9.774 // construct the elements. The constructors and destructors are 
   9.775 // properly called, the objects must be movable.
   9.776 
   9.777 template<class T, class SizePolicy=ArrayDefaultPolicy>
   9.778 class ArrayCC : public ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> >
   9.779 {
   9.780 public:
   9.781     typedef T                                                               ValueType;
   9.782     typedef ContainerAllocator<T>                                           AllocatorType;
   9.783     typedef SizePolicy                                                      SizePolicyType;
   9.784     typedef ArrayCC<T, SizePolicy>                                          SelfType;
   9.785     typedef ArrayBase<ArrayDataCC<T, ContainerAllocator<T>, SizePolicy> >   BaseType;
   9.786 
   9.787     ArrayCC(const ValueType& defval) : BaseType(defval) {}
   9.788     ArrayCC(const ValueType& defval, int size) : BaseType(defval, size) {}
   9.789     ArrayCC(const ValueType& defval, const SizePolicyType& p) : BaseType(defval) { SetSizePolicy(p); }
   9.790     ArrayCC(const SelfType& a) : BaseType(a) {}
   9.791     const SelfType& operator=(const SelfType& a) { BaseType::operator=(a); return *this; }
   9.792 };
   9.793 
   9.794 } // OVR
   9.795 
   9.796 #endif
   9.797 \ No newline at end of file
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/libovr/Src/Kernel/OVR_Atomic.cpp	Sat Sep 14 16:14:59 2013 +0300
    10.3 @@ -0,0 +1,1 @@
    10.4 +/************************************************************************************
    10.5 
    10.6 Filename    :   OVR_Atomic.cpp
    10.7 Content     :   Contains atomic operations and inline fastest locking
    10.8                 functionality. Will contain #ifdefs for OS efficiency.
    10.9                 Have non-thread-safe implementation if not available.
   10.10 Created     :   September 19, 2012
   10.11 Notes       : 
   10.12 
   10.13 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   10.14 
   10.15 Use of this software is subject to the terms of the Oculus license
   10.16 agreement provided at the time of installation or download, or which
   10.17 otherwise accompanies this software in either electronic or hard copy form.
   10.18 
   10.19 ************************************************************************************/
   10.20 
   10.21 #include "OVR_Atomic.h"
   10.22 
   10.23 #ifdef OVR_ENABLE_THREADS
   10.24 
   10.25 // Include Windows 8-Metro compatible Synchronization API
   10.26 #if defined(OVR_OS_WIN32) && defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
   10.27 #include <synchapi.h>
   10.28 #endif
   10.29 
   10.30 
   10.31 namespace OVR {
   10.32 
   10.33 // ***** Windows Lock implementation
   10.34 
   10.35 #if defined(OVR_OS_WIN32)
   10.36 
   10.37 // ***** Standard Win32 Lock implementation
   10.38 
   10.39 // Constructors
   10.40 Lock::Lock(unsigned spinCount)
   10.41 {
   10.42 #if defined(NTDDI_WIN8) && (NTDDI_VERSION >= NTDDI_WIN8)
   10.43    // On Windows 8 we use InitializeCriticalSectionEx due to Metro-Compatibility
   10.44    InitializeCriticalSectionEx(&cs, spinCount,
   10.45                                OVR_DEBUG_SELECT(NULL, CRITICAL_SECTION_NO_DEBUG_INFO));
   10.46 #else
   10.47     // Spin count init critical section function prototype for Window NT
   10.48     typedef BOOL (WINAPI *Function_InitializeCriticalSectionAndSpinCount) 
   10.49                  (LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount);
   10.50 
   10.51 
   10.52     // Try to load function dynamically so that we don't require NT
   10.53     // On Windows NT we will use InitializeCriticalSectionAndSpinCount
   10.54     static  bool initTried = 0;
   10.55     static  Function_InitializeCriticalSectionAndSpinCount pInitFn = 0;
   10.56 
   10.57     if (!initTried)
   10.58     {
   10.59         HMODULE hmodule = ::LoadLibrary(OVR_STR("kernel32.dll"));
   10.60         pInitFn     = (Function_InitializeCriticalSectionAndSpinCount)
   10.61                       ::GetProcAddress(hmodule, "InitializeCriticalSectionAndSpinCount");
   10.62         initTried   = true;
   10.63     }
   10.64 
   10.65     // Initialize the critical section
   10.66     if (pInitFn)
   10.67         pInitFn(&cs, spinCount);
   10.68     else
   10.69         ::InitializeCriticalSection(&cs);
   10.70 #endif
   10.71    
   10.72 }
   10.73 
   10.74 
   10.75 Lock::~Lock()
   10.76 {
   10.77     DeleteCriticalSection(&cs);
   10.78 }
   10.79 
   10.80 
   10.81 #endif
   10.82 
   10.83 } // OVR
   10.84 
   10.85 #endif // OVR_ENABLE_THREADS
   10.86 \ No newline at end of file
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/libovr/Src/Kernel/OVR_Atomic.h	Sat Sep 14 16:14:59 2013 +0300
    11.3 @@ -0,0 +1,1 @@
    11.4 +/************************************************************************************
    11.5 
    11.6 PublicHeader:   OVR.h
    11.7 Filename    :   OVR_Atomic.h
    11.8 Content     :   Contains atomic operations and inline fastest locking
    11.9                 functionality. Will contain #ifdefs for OS efficiency.
   11.10                 Have non-thread-safe implementaion if not available.
   11.11 Created     :   September 19, 2012
   11.12 Notes       : 
   11.13 
   11.14 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   11.15 
   11.16 Use of this software is subject to the terms of the Oculus license
   11.17 agreement provided at the time of installation or download, or which
   11.18 otherwise accompanies this software in either electronic or hard copy form.
   11.19 
   11.20 ************************************************************************************/
   11.21 #ifndef OVR_Atomic_h
   11.22 #define OVR_Atomic_h
   11.23 
   11.24 #include "OVR_Types.h"
   11.25 
   11.26 // Include System thread functionality.
   11.27 #if defined(OVR_OS_WIN32)
   11.28 #include <windows.h>
   11.29 #else
   11.30 #include <pthread.h>
   11.31 #endif
   11.32 
   11.33 
   11.34 namespace OVR {
   11.35 
   11.36 
   11.37 // ****** Declared classes
   11.38 
   11.39 // If there is NO thread support we implement AtomicOps and
   11.40 // Lock objects as no-ops. The other classes are not defined.
   11.41 template<class C> class AtomicOps;
   11.42 template<class T> class AtomicInt;
   11.43 template<class T> class AtomicPtr;
   11.44 
   11.45 class   Lock;
   11.46 
   11.47 
   11.48 //-----------------------------------------------------------------------------------
   11.49 // ***** AtomicOps
   11.50 
   11.51 // Atomic operations are provided by the AtomicOps templates class,
   11.52 // implemented through system-specific AtomicOpsRaw specializations.
   11.53 // It provides several fundamental operations such as Exchange, ExchangeAdd
   11.54 // CompareAndSet, and Store_Release. Each function includes several memory
   11.55 // synchronization versions, important for multiprocessing CPUs with weak
   11.56 // memory consistency. The following memory fencing strategies are supported:
   11.57 //
   11.58 //  - NoSync.  No memory synchronization is done for atomic op.
   11.59 //  - Release. All other memory writes are completed before atomic op
   11.60 //             writes its results.
   11.61 //  - Acquire. Further memory reads are forced to wait until atomic op
   11.62 //             executes, guaranteeing that the right values will be seen.
   11.63 //  - Sync.    A combination of Release and Acquire.
   11.64 
   11.65 
   11.66 // *** AtomicOpsRaw
   11.67 
   11.68 // AtomicOpsRaw is a specialized template that provides atomic operations 
   11.69 // used by AtomicOps. This class has two fundamental qualities: (1) it
   11.70 // defines a type T of correct size, and (2) provides operations that work
   11.71 // atomically, such as Exchange_Sync and CompareAndSet_Release.
   11.72 
   11.73 // AtomicOpsRawBase class contains shared constants/classes for AtomicOpsRaw.
   11.74 // The primary thing is does is define sync class objects, whose destructor and
   11.75 // constructor provide places to insert appropriate synchronization calls, on 
   11.76 // systems where such calls are necessary. So far, the breakdown is as follows:
   11.77 // 
   11.78 //  - X86 systems don't need custom syncs, since their exchange/atomic
   11.79 //    instructions are implicitly synchronized.
   11.80 //  - PowerPC requires lwsync/isync instructions that can use this mechanism.
   11.81 //  - If some other systems require a mechanism where syncing type is associated
   11.82 //    with a particular instruction, the default implementation (which implements
   11.83 //    all Sync, Acquire, and Release modes in terms of NoSync and fence) may not
   11.84 //    work. Ii that case it will need to be #ifdef-ed conditionally.
   11.85 
   11.86 struct AtomicOpsRawBase
   11.87 {
   11.88 #if !defined(OVR_ENABLE_THREADS) || defined(OVR_CPU_X86) || defined(OVR_OS_WIN32) || defined(OVR_OS_IPHONE)
   11.89     // Need to have empty constructor to avoid class 'unused' variable warning.
   11.90     struct FullSync { inline FullSync() { } };
   11.91     struct AcquireSync { inline AcquireSync() { } };
   11.92     struct ReleaseSync { inline ReleaseSync() { } };
   11.93 
   11.94 #elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC)
   11.95     struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("isync\n"); } };
   11.96     struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("isync\n"); } };
   11.97     struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } };
   11.98 
   11.99 #elif defined(OVR_CPU_MIPS)
  11.100     struct FullSync { inline FullSync() { asm volatile("sync\n"); } ~FullSync() { asm volatile("sync\n"); } };
  11.101     struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("sync\n"); } };
  11.102     struct ReleaseSync { inline ReleaseSync() { asm volatile("sync\n"); } };
  11.103 
  11.104 #elif defined(OVR_CPU_ARM)
  11.105     struct FullSync { inline FullSync() { asm volatile("dmb\n"); } ~FullSync() { asm volatile("dmb\n"); } };
  11.106     struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("dmb\n"); } };
  11.107     struct ReleaseSync { inline ReleaseSync() { asm volatile("dmb\n"); } };
  11.108 
  11.109 
  11.110 #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4)
  11.111     // __sync functions are already full sync
  11.112     struct FullSync { inline FullSync() { } };
  11.113     struct AcquireSync { inline AcquireSync() { } };
  11.114     struct ReleaseSync { inline ReleaseSync() { } };
  11.115 #endif
  11.116 };
  11.117 
  11.118 
  11.119 // 4-Byte raw data atomic op implementation class.
  11.120 struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase
  11.121 {
  11.122 #if !defined(OVR_ENABLE_THREADS)
  11.123 
  11.124     // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl.
  11.125     typedef UInt32 T;   
  11.126 
  11.127     // *** Thread - Safe Atomic Versions.
  11.128 
  11.129 #elif defined(OVR_OS_WIN32)
  11.130 
  11.131     // Use special defined for VC6, where volatile is not used and
  11.132     // InterlockedCompareExchange is declared incorrectly.
  11.133     typedef LONG T;      
  11.134 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC < 1300)
  11.135     typedef T* InterlockTPtr;
  11.136     typedef LPVOID ET;
  11.137     typedef ET* InterlockETPtr;
  11.138 #else
  11.139     typedef volatile T* InterlockTPtr;
  11.140     typedef T ET;
  11.141     typedef InterlockTPtr InterlockETPtr;
  11.142 #endif
  11.143     inline static T     Exchange_NoSync(volatile T* p, T val)            { return InterlockedExchange((InterlockTPtr)p, val); }
  11.144     inline static T     ExchangeAdd_NoSync(volatile T* p, T val)         { return InterlockedExchangeAdd((InterlockTPtr)p, val); }
  11.145     inline static bool  CompareAndSet_NoSync(volatile T* p, T c, T val)  { return InterlockedCompareExchange((InterlockETPtr)p, (ET)val, (ET)c) == (ET)c; }
  11.146 
  11.147 #elif defined(OVR_CPU_PPC64) || defined(OVR_CPU_PPC)
  11.148     typedef UInt32 T;
  11.149     static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
  11.150     {
  11.151         UInt32 ret;
  11.152 
  11.153         asm volatile("1:\n\t"
  11.154                      "lwarx  %[r],0,%[i]\n\t"
  11.155                      "stwcx. %[j],0,%[i]\n\t"
  11.156                      "bne-   1b\n"
  11.157                      : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [j] "b" (j) : "cc", "memory");
  11.158 
  11.159         return ret;
  11.160     }
  11.161 
  11.162     static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
  11.163     {
  11.164         UInt32 dummy, ret;
  11.165 
  11.166         asm volatile("1:\n\t"
  11.167                      "lwarx  %[r],0,%[i]\n\t"
  11.168                      "add    %[o],%[r],%[j]\n\t"
  11.169                      "stwcx. %[o],0,%[i]\n\t"
  11.170                      "bne-   1b\n"
  11.171                      : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc", "memory");
  11.172 
  11.173         return ret;
  11.174     }
  11.175 
  11.176     static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
  11.177     {
  11.178         UInt32 ret;
  11.179 
  11.180         asm volatile("1:\n\t"
  11.181                      "lwarx  %[r],0,%[i]\n\t"
  11.182                      "cmpw   0,%[r],%[cmp]\n\t"
  11.183                      "mfcr   %[r]\n\t"
  11.184                      "bne-   2f\n\t"
  11.185                      "stwcx. %[val],0,%[i]\n\t"
  11.186                      "bne-   1b\n\t"
  11.187                      "2:\n"
  11.188                      : "+m" (*i), [r] "=&b" (ret) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc", "memory");
  11.189 
  11.190         return (ret & 0x20000000) ? 1 : 0;
  11.191     }
  11.192 
  11.193 #elif defined(OVR_CPU_MIPS)
  11.194     typedef UInt32 T;
  11.195 
  11.196     static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
  11.197     {
  11.198         UInt32 ret;
  11.199 
  11.200         asm volatile("1:\n\t"
  11.201                      "ll     %[r],0(%[i])\n\t"
  11.202                      "sc     %[j],0(%[i])\n\t"
  11.203                      "beq    %[j],$0,1b\n\t"
  11.204                      "nop    \n"
  11.205                      : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory");
  11.206 
  11.207         return ret;
  11.208     }
  11.209 
  11.210     static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
  11.211     {
  11.212         UInt32 ret;
  11.213 
  11.214         asm volatile("1:\n\t"
  11.215                      "ll     %[r],0(%[i])\n\t"
  11.216                      "addu   %[j],%[r],%[j]\n\t"
  11.217                      "sc     %[j],0(%[i])\n\t"
  11.218                      "beq    %[j],$0,1b\n\t"
  11.219                      "nop    \n"
  11.220                      : "+m" (*i), [r] "=&d" (ret) : [i] "d" (i), [j] "d" (j) : "cc", "memory");
  11.221 
  11.222         return ret;
  11.223     }
  11.224 
  11.225     static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
  11.226     {
  11.227         UInt32 ret, dummy;
  11.228 
  11.229         asm volatile("1:\n\t"
  11.230                      "move   %[r],$0\n\t"
  11.231                      "ll     %[o],0(%[i])\n\t"
  11.232                      "bne    %[o],%[c],2f\n\t"
  11.233                      "move   %[r],%[v]\n\t"
  11.234                      "sc     %[r],0(%[i])\n\t"
  11.235                      "beq    %[r],$0,1b\n\t"
  11.236                      "nop    \n\t"
  11.237                      "2:\n"
  11.238                      : "+m" (*i),[r] "=&d" (ret), [o] "=&d" (dummy) : [i] "d" (i), [c] "d" (c), [v] "d" (value)
  11.239                      : "cc", "memory");
  11.240 
  11.241         return ret;
  11.242     }
  11.243 
  11.244 #elif defined(OVR_CPU_ARM) && defined(OVR_CC_ARM)
  11.245     typedef UInt32 T;
  11.246 
  11.247     static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
  11.248     {
  11.249         for(;;)
  11.250         {
  11.251             T r = __ldrex(i);
  11.252             if (__strex(j, i) == 0)
  11.253                 return r;
  11.254         }
  11.255     }
  11.256     static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
  11.257     {
  11.258         for(;;)
  11.259         {
  11.260             T r = __ldrex(i);
  11.261             if (__strex(r + j, i) == 0)
  11.262                 return r;
  11.263         }
  11.264     }
  11.265 
  11.266     static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
  11.267     {
  11.268         for(;;)
  11.269         {
  11.270             T r = __ldrex(i);
  11.271             if (r != c)
  11.272                 return 0;
  11.273             if (__strex(value, i) == 0)
  11.274                 return 1;
  11.275         }
  11.276     }
  11.277 
  11.278 #elif defined(OVR_CPU_ARM)
  11.279     typedef UInt32 T;
  11.280 
  11.281     static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
  11.282     {
  11.283         UInt32 ret, dummy;
  11.284 
  11.285         asm volatile("1:\n\t"
  11.286             "ldrex  %[r],[%[i]]\n\t"
  11.287             "strex  %[t],%[j],[%[i]]\n\t"
  11.288             "cmp    %[t],#0\n\t"
  11.289             "bne    1b\n\t"
  11.290             : "+m" (*i), [r] "=&r" (ret), [t] "=&r" (dummy) : [i] "r" (i), [j] "r" (j) : "cc", "memory");
  11.291 
  11.292         return ret;
  11.293     }
  11.294 
  11.295     static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
  11.296     {
  11.297         UInt32 ret, dummy, test;
  11.298 
  11.299         asm volatile("1:\n\t"
  11.300             "ldrex  %[r],[%[i]]\n\t"
  11.301             "add    %[o],%[r],%[j]\n\t"
  11.302             "strex  %[t],%[o],[%[i]]\n\t"
  11.303             "cmp    %[t],#0\n\t"
  11.304             "bne    1b\n\t"
  11.305             : "+m" (*i), [r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test)  : [i] "r" (i), [j] "r" (j) : "cc", "memory");
  11.306 
  11.307         return ret;
  11.308     }
  11.309 
  11.310     static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
  11.311     {
  11.312         UInt32 ret = 1, dummy, test;
  11.313 
  11.314         asm volatile("1:\n\t"
  11.315             "ldrex  %[o],[%[i]]\n\t"
  11.316             "cmp    %[o],%[c]\n\t"
  11.317             "bne    2f\n\t"
  11.318             "strex  %[r],%[v],[%[i]]\n\t"
  11.319             "cmp    %[r],#0\n\t"
  11.320             "bne    1b\n\t"
  11.321             "2:\n"
  11.322             : "+m" (*i),[r] "=&r" (ret), [o] "=&r" (dummy), [t] "=&r" (test) : [i] "r" (i), [c] "r" (c), [v] "r" (value)
  11.323             : "cc", "memory");
  11.324 
  11.325         return !ret;
  11.326     }
  11.327 
  11.328 #elif defined(OVR_CPU_X86)
  11.329     typedef UInt32 T;
  11.330 
  11.331     static inline UInt32   Exchange_NoSync(volatile UInt32 *i, UInt32 j)
  11.332     {
  11.333         asm volatile("xchgl %1,%[i]\n"
  11.334                      : "+m" (*i), "=q" (j) : [i] "m" (*i), "1" (j) : "cc", "memory");
  11.335 
  11.336         return j;
  11.337     }
  11.338 
  11.339     static inline UInt32   ExchangeAdd_NoSync(volatile UInt32 *i, UInt32 j)
  11.340     {
  11.341         asm volatile("lock; xaddl %1,%[i]\n"
  11.342                      : "+m" (*i), "+q" (j) : [i] "m" (*i) : "cc", "memory");
  11.343 
  11.344         return j;
  11.345     }
  11.346 
  11.347     static inline bool     CompareAndSet_NoSync(volatile UInt32 *i, UInt32 c, UInt32 value)
  11.348     {
  11.349         UInt32 ret;
  11.350 
  11.351         asm volatile("lock; cmpxchgl %[v],%[i]\n"
  11.352                      : "+m" (*i), "=a" (ret) : [i] "m" (*i), "1" (c), [v] "q" (value) : "cc", "memory");
  11.353 
  11.354         return (ret == c);
  11.355     }
  11.356 
  11.357 #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
  11.358 
  11.359     typedef UInt32 T;
  11.360 
  11.361     static inline T   Exchange_NoSync(volatile T *i, T j)
  11.362     {
  11.363         T v;
  11.364         do {
  11.365             v = *i;
  11.366         } while (!__sync_bool_compare_and_swap(i, v, j));
  11.367         return v;
  11.368     }
  11.369 
  11.370     static inline T   ExchangeAdd_NoSync(volatile T *i, T j)
  11.371     {
  11.372         return __sync_fetch_and_add(i, j);
  11.373     }
  11.374 
  11.375     static inline bool     CompareAndSet_NoSync(volatile T *i, T c, T value)
  11.376     {
  11.377         return __sync_bool_compare_and_swap(i, c, value);
  11.378     }
  11.379 
  11.380 #endif // OS
  11.381 };
  11.382 
  11.383 
  11.384 // 8-Byte raw data data atomic op implementation class.
  11.385 // Currently implementation is provided only on systems with 64-bit pointers.
  11.386 struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase
  11.387 {    
  11.388 #if !defined(OVR_64BIT_POINTERS) || !defined(OVR_ENABLE_THREADS)
  11.389 
  11.390     // Provide a type for no-thread-support cases. Used by AtomicOpsRaw_DefImpl.
  11.391     typedef UInt64 T;
  11.392 
  11.393     // *** Thread - Safe OS specific versions.
  11.394 #elif defined(OVR_OS_WIN32)
  11.395 
  11.396     // This is only for 64-bit systems.
  11.397     typedef LONG64      T;
  11.398     typedef volatile T* InterlockTPtr;    
  11.399     inline static T     Exchange_NoSync(volatile T* p, T val)            { return InterlockedExchange64((InterlockTPtr)p, val); }
  11.400     inline static T     ExchangeAdd_NoSync(volatile T* p, T val)         { return InterlockedExchangeAdd64((InterlockTPtr)p, val); }
  11.401     inline static bool  CompareAndSet_NoSync(volatile T* p, T c, T val)  { return InterlockedCompareExchange64((InterlockTPtr)p, val, c) == c; }
  11.402 
  11.403 #elif defined(OVR_CPU_PPC64)
  11.404  
  11.405     typedef UInt64 T;
  11.406 
  11.407     static inline UInt64   Exchange_NoSync(volatile UInt64 *i, UInt64 j)
  11.408     {
  11.409         UInt64 dummy, ret;
  11.410 
  11.411         asm volatile("1:\n\t"
  11.412                      "ldarx  %[r],0,%[i]\n\t"
  11.413                      "mr     %[o],%[j]\n\t"
  11.414                      "stdcx. %[o],0,%[i]\n\t"
  11.415                      "bne-   1b\n"
  11.416                      : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc");
  11.417 
  11.418         return ret;
  11.419     }
  11.420 
  11.421     static inline UInt64   ExchangeAdd_NoSync(volatile UInt64 *i, UInt64 j)
  11.422     {
  11.423         UInt64 dummy, ret;
  11.424 
  11.425         asm volatile("1:\n\t"
  11.426                      "ldarx  %[r],0,%[i]\n\t"
  11.427                      "add    %[o],%[r],%[j]\n\t"
  11.428                      "stdcx. %[o],0,%[i]\n\t"
  11.429                      "bne-   1b\n"
  11.430                      : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [j] "b" (j) : "cc");
  11.431 
  11.432         return ret;
  11.433     }
  11.434 
  11.435     static inline bool     CompareAndSet_NoSync(volatile UInt64 *i, UInt64 c, UInt64 value)
  11.436     {
  11.437         UInt64 ret, dummy;
  11.438 
  11.439         asm volatile("1:\n\t"
  11.440                      "ldarx  %[r],0,%[i]\n\t"
  11.441                      "cmpw   0,%[r],%[cmp]\n\t"
  11.442                      "mfcr   %[r]\n\t"
  11.443                      "bne-   2f\n\t"
  11.444                      "stdcx. %[val],0,%[i]\n\t"
  11.445                      "bne-   1b\n\t"
  11.446                      "2:\n"
  11.447                      : "+m" (*i), [r] "=&b" (ret), [o] "=&r" (dummy) : [i] "b" (i), [cmp] "b" (c), [val] "b" (value) : "cc");
  11.448 
  11.449         return (ret & 0x20000000) ? 1 : 0;
  11.450     }
  11.451 
  11.452 #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4 && __GNUC_MINOR__ >= 1)
  11.453 
  11.454     typedef UInt64 T;
  11.455 
  11.456     static inline T   Exchange_NoSync(volatile T *i, T j)
  11.457     {
  11.458         T v;
  11.459         do {
  11.460             v = *i;
  11.461         } while (!__sync_bool_compare_and_swap(i, v, j));
  11.462         return v;
  11.463     }
  11.464 
  11.465     static inline T   ExchangeAdd_NoSync(volatile T *i, T j)
  11.466     {
  11.467         return __sync_fetch_and_add(i, j);
  11.468     }
  11.469 
  11.470     static inline bool     CompareAndSet_NoSync(volatile T *i, T c, T value)
  11.471     {
  11.472         return __sync_bool_compare_and_swap(i, c, value);
  11.473     }
  11.474 
  11.475 #endif // OS
  11.476 };
  11.477 
  11.478 
  11.479 // Default implementation for AtomicOpsRaw; provides implementation of mem-fenced
  11.480 // atomic operations where fencing is done with a sync object wrapped around a NoSync
  11.481 // operation implemented in the base class. If such implementation is not possible
  11.482 // on a given platform, #ifdefs can be used to disable it and then op functions can be
  11.483 // implemented individually in the appropriate AtomicOpsRaw<size> class.
  11.484 
  11.485 template<class O>
  11.486 struct AtomicOpsRaw_DefImpl : public O
  11.487 {
  11.488     typedef typename O::T O_T;
  11.489     typedef typename O::FullSync    O_FullSync;
  11.490     typedef typename O::AcquireSync O_AcquireSync;
  11.491     typedef typename O::ReleaseSync O_ReleaseSync;
  11.492 
  11.493     // If there is no thread support, provide the default implementation. In this case,
  11.494     // the base class (0) must still provide the T declaration.
  11.495 #ifndef OVR_ENABLE_THREADS
  11.496 
  11.497     // Atomic exchange of val with argument. Returns old val.
  11.498     inline static O_T   Exchange_NoSync(volatile O_T* p, O_T val)           { O_T old = *p; *p = val; return old; }
  11.499     // Adds a new val to argument; returns its old val.
  11.500     inline static O_T   ExchangeAdd_NoSync(volatile O_T* p, O_T val)        { O_T old = *p; *p += val; return old; }
  11.501     // Compares the argument data with 'c' val.
  11.502     // If succeeded, stores val int '*p' and returns true; otherwise returns false.
  11.503     inline static bool  CompareAndSet_NoSync(volatile O_T* p, O_T c, O_T val) { if (*p==c) { *p = val; return 1; } return 0; }
  11.504 
  11.505 #endif
  11.506 
  11.507     // If NoSync wrapped implementation may not be possible, it this block should be
  11.508     //  replaced with per-function implementation in O.
  11.509     // "AtomicOpsRaw_DefImpl<O>::" prefix in calls below.
  11.510     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); }
  11.511     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); }
  11.512     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); }  
  11.513     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); }
  11.514     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); }
  11.515     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); }
  11.516     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); }
  11.517     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); }
  11.518     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); }
  11.519 
  11.520     // Loads and stores with memory fence. These have only the relevant versions.
  11.521 #ifdef OVR_CPU_X86
  11.522     // On X86, Store_Release is implemented as exchange. Note that we can also
  11.523     // consider 'sfence' in the future, although it is not as compatible with older CPUs.
  11.524     inline static void  Store_Release(volatile O_T* p, O_T val)  { Exchange_Release(p, val); }
  11.525 #else
  11.526     inline static void  Store_Release(volatile O_T* p, O_T val)  { O_ReleaseSync sync; OVR_UNUSED(sync); *p = val; }
  11.527 #endif
  11.528     inline static O_T   Load_Acquire(const volatile O_T* p)      { O_AcquireSync sync; OVR_UNUSED(sync); return *p; }
  11.529 };
  11.530 
  11.531 
  11.532 template<int size>
  11.533 struct AtomicOpsRaw : public AtomicOpsRawBase { };
  11.534 
  11.535 template<>
  11.536 struct AtomicOpsRaw<4> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl>
  11.537 {   
  11.538     // Ensure that assigned type size is correct.
  11.539     AtomicOpsRaw()
  11.540     { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_4ByteImpl>::T) == 4); }
  11.541 };
  11.542 template<>
  11.543 struct AtomicOpsRaw<8> : public AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl>
  11.544 {
  11.545     AtomicOpsRaw()
  11.546     { OVR_COMPILER_ASSERT(sizeof(AtomicOpsRaw_DefImpl<AtomicOpsRaw_8ByteImpl>::T) == 8); }
  11.547 };
  11.548 
  11.549 
  11.550 // *** AtomicOps - implementation of atomic Ops for specified class
  11.551 
  11.552 // Implements atomic ops on a class, provided that the object is either
  11.553 // 4 or 8 bytes in size (depending on the AtomicOpsRaw specializations
  11.554 // available). Relies on AtomicOpsRaw for much of implementation.
  11.555 
  11.556 template<class C>
  11.557 class AtomicOps
  11.558 {
  11.559     typedef AtomicOpsRaw<sizeof(C)>       Ops;
  11.560     typedef typename Ops::T               T;
  11.561     typedef volatile typename Ops::T*     PT;
  11.562     // We cast through unions to (1) avoid pointer size compiler warnings
  11.563     // and (2) ensure that there are no problems with strict pointer aliasing.
  11.564     union C2T_union { C c; T t; };
  11.565 
  11.566 public:
  11.567     // General purpose implementation for standard syncs.    
  11.568     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; }
  11.569     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; }
  11.570     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; }
  11.571     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; }
  11.572     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; }
  11.573     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; }
  11.574     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; }
  11.575     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; }
  11.576     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); }
  11.577     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); }
  11.578     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); }
  11.579     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); }
  11.580     // Loads and stores with memory fence. These have only the relevant versions.    
  11.581     inline static void  Store_Release(volatile C* p, C val)             { C2T_union u; u.c = val; Ops::Store_Release((PT)p, u.t); }    
  11.582     inline static C     Load_Acquire(const volatile C* p)               { C2T_union u; u.t = Ops::Load_Acquire((PT)p); return u.c; }
  11.583 };
  11.584 
  11.585 
  11.586 
  11.587 // Atomic value base class - implements operations shared for integers and pointers.
  11.588 template<class T>
  11.589 class AtomicValueBase
  11.590 {
  11.591 protected:
  11.592     typedef AtomicOps<T> Ops;
  11.593 public:
  11.594 
  11.595     volatile T  Value;
  11.596 
  11.597     inline AtomicValueBase()                  { }
  11.598     explicit inline AtomicValueBase(T val)    { Ops::Store_Release(&Value, val); }
  11.599 
  11.600     // Most libraries (TBB and Joshua Scholar's) library do not do Load_Acquire
  11.601     // here, since most algorithms do not require atomic loads. Needs some research.    
  11.602     inline operator T() const { return Value; }
  11.603 
  11.604     // *** Standard Atomic inlines
  11.605     inline T     Exchange_Sync(T val)               { return Ops::Exchange_Sync(&Value,  val); }
  11.606     inline T     Exchange_Release(T val)            { return Ops::Exchange_Release(&Value, val); }
  11.607     inline T     Exchange_Acquire(T val)            { return Ops::Exchange_Acquire(&Value, val); }
  11.608     inline T     Exchange_NoSync(T val)             { return Ops::Exchange_NoSync(&Value, val); }
  11.609     inline bool  CompareAndSet_Sync(T c, T val)     { return Ops::CompareAndSet_Sync(&Value, c, val); }
  11.610     inline bool  CompareAndSet_Release(T c, T val)  { return Ops::CompareAndSet_Release(&Value, c, val); }
  11.611     inline bool  CompareAndSet_Acquire(T c, T val)  { return Ops::CompareAndSet_Relse(&Value, c, val); }
  11.612     inline bool  CompareAndSet_NoSync(T c, T val)   { return Ops::CompareAndSet_NoSync(&Value, c, val); }
  11.613     // Load & Store.
  11.614     inline void  Store_Release(T val)               { Ops::Store_Release(&Value, val); }
  11.615     inline T     Load_Acquire() const               { return Ops::Load_Acquire(&Value);  }
  11.616 };
  11.617 
  11.618 
  11.619 // ***** AtomicPtr - Atomic pointer template
  11.620 
  11.621 // This pointer class supports atomic assignments with release,
  11.622 // increment / decrement operations, and conditional compare + set.
  11.623 
  11.624 template<class T>
  11.625 class AtomicPtr : public AtomicValueBase<T*>
  11.626 {
  11.627     typedef typename AtomicValueBase<T*>::Ops Ops;
  11.628 
  11.629 public:
  11.630     // Initialize pointer value to 0 by default; use Store_Release only with explicit constructor.
  11.631     inline AtomicPtr() : AtomicValueBase<T*>()                     { this->Value = 0; }
  11.632     explicit inline AtomicPtr(T* val) : AtomicValueBase<T*>(val)   { }
  11.633         
  11.634     // Pointer access.
  11.635     inline T* operator -> () const     { return this->Load_Acquire(); }
  11.636 
  11.637     // It looks like it is convenient to have Load_Acquire characteristics
  11.638     // for this, since that is convenient for algorithms such as linked
  11.639     // list traversals that can be added to bu another thread.
  11.640     inline operator T* () const        { return this->Load_Acquire(); }
  11.641 
  11.642 
  11.643     // *** Standard Atomic inlines (applicable to pointers)
  11.644 
  11.645     // ExhangeAdd considers pointer size for pointers.
  11.646     template<class I>
  11.647     inline T*     ExchangeAdd_Sync(I incr)      { return Ops::ExchangeAdd_Sync(&this->Value, ((T*)0) + incr); }
  11.648     template<class I>
  11.649     inline T*     ExchangeAdd_Release(I incr)   { return Ops::ExchangeAdd_Release(&this->Value, ((T*)0) + incr); }
  11.650     template<class I>
  11.651     inline T*     ExchangeAdd_Acquire(I incr)   { return Ops::ExchangeAdd_Acquire(&this->Value, ((T*)0) + incr); }
  11.652     template<class I>
  11.653     inline T*     ExchangeAdd_NoSync(I incr)    { return Ops::ExchangeAdd_NoSync(&this->Value, ((T*)0) + incr); }
  11.654 
  11.655     // *** Atomic Operators
  11.656 
  11.657     inline T* operator = (T* val)  { this->Store_Release(val); return val; }
  11.658 
  11.659     template<class I>
  11.660     inline T* operator += (I val) { return ExchangeAdd_Sync(val) + val; }
  11.661     template<class I>
  11.662     inline T* operator -= (I val) { return operator += (-val); }
  11.663 
  11.664     inline T* operator ++ ()      { return ExchangeAdd_Sync(1) + 1; }
  11.665     inline T* operator -- ()      { return ExchangeAdd_Sync(-1) - 1; }
  11.666     inline T* operator ++ (int)   { return ExchangeAdd_Sync(1); }
  11.667     inline T* operator -- (int)   { return ExchangeAdd_Sync(-1); }
  11.668 };
  11.669 
  11.670 
  11.671 // ***** AtomicInt - Atomic integer template
  11.672 
  11.673 // Implements an atomic integer type; the exact type to use is provided 
  11.674 // as an argument. Supports atomic Acquire / Release semantics, atomic
  11.675 // arithmetic operations, and atomic conditional compare + set.
  11.676 
  11.677 template<class T>
  11.678 class AtomicInt : public AtomicValueBase<T>
  11.679 {
  11.680     typedef typename AtomicValueBase<T>::Ops Ops;
  11.681 
  11.682 public:
  11.683     inline AtomicInt() : AtomicValueBase<T>()                     { }
  11.684     explicit inline AtomicInt(T val) : AtomicValueBase<T>(val)    { }
  11.685 
  11.686 
  11.687     // *** Standard Atomic inlines (applicable to int)   
  11.688     inline T     ExchangeAdd_Sync(T val)            { return Ops::ExchangeAdd_Sync(&this->Value, val); }
  11.689     inline T     ExchangeAdd_Release(T val)         { return Ops::ExchangeAdd_Release(&this->Value, val); }
  11.690     inline T     ExchangeAdd_Acquire(T val)         { return Ops::ExchangeAdd_Acquire(&this->Value, val); }
  11.691     inline T     ExchangeAdd_NoSync(T val)          { return Ops::ExchangeAdd_NoSync(&this->Value, val); }
  11.692     // These increments could be more efficient because they don't return a value.
  11.693     inline void  Increment_Sync()                   { ExchangeAdd_Sync((T)1); }
  11.694     inline void  Increment_Release()                { ExchangeAdd_Release((T)1); }
  11.695     inline void  Increment_Acquire()                { ExchangeAdd_Acquire((T)1); }    
  11.696     inline void  Increment_NoSync()                 { ExchangeAdd_NoSync((T)1); }
  11.697 
  11.698     // *** Atomic Operators
  11.699 
  11.700     inline T operator = (T val)  { this->Store_Release(val); return val; }
  11.701     inline T operator += (T val) { return ExchangeAdd_Sync(val) + val; }
  11.702     inline T operator -= (T val) { return ExchangeAdd_Sync(0 - val) - val; }
  11.703 
  11.704     inline T operator ++ ()      { return ExchangeAdd_Sync((T)1) + 1; }
  11.705     inline T operator -- ()      { return ExchangeAdd_Sync(((T)0)-1) - 1; }
  11.706     inline T operator ++ (int)   { return ExchangeAdd_Sync((T)1); }
  11.707     inline T operator -- (int)   { return ExchangeAdd_Sync(((T)0)-1); }
  11.708 
  11.709     // More complex atomic operations. Leave it to compiler whether to optimize them or not.
  11.710     T operator &= (T arg)
  11.711     {
  11.712         T comp, newVal;
  11.713         do {
  11.714             comp   = this->Value;
  11.715             newVal = comp & arg;
  11.716         } while(!this->CompareAndSet_Sync(comp, newVal));
  11.717         return newVal;
  11.718     }
  11.719 
  11.720     T operator |= (T arg)
  11.721     {
  11.722         T comp, newVal;
  11.723         do {
  11.724             comp   = this->Value;
  11.725             newVal = comp | arg;
  11.726         } while(!this->CompareAndSet_Sync(comp, newVal));
  11.727         return newVal;
  11.728     }
  11.729 
  11.730     T operator ^= (T arg)
  11.731     {
  11.732         T comp, newVal;
  11.733         do {
  11.734             comp   = this->Value;
  11.735             newVal = comp ^ arg;
  11.736         } while(!this->CompareAndSet_Sync(comp, newVal));
  11.737         return newVal;
  11.738     }
  11.739 
  11.740     T operator *= (T arg)
  11.741     {
  11.742         T comp, newVal;
  11.743         do {
  11.744             comp   = this->Value;
  11.745             newVal = comp * arg;
  11.746         } while(!this->CompareAndSet_Sync(comp, newVal));
  11.747         return newVal;
  11.748     }
  11.749 
  11.750     T operator /= (T arg)
  11.751     {
  11.752         T comp, newVal;
  11.753         do {
  11.754             comp   = this->Value;
  11.755             newVal = comp / arg;
  11.756         } while(!CompareAndSet_Sync(comp, newVal));
  11.757         return newVal;
  11.758     }
  11.759 
  11.760     T operator >>= (unsigned bits)
  11.761     {
  11.762         T comp, newVal;
  11.763         do {
  11.764             comp   = this->Value;
  11.765             newVal = comp >> bits;
  11.766         } while(!CompareAndSet_Sync(comp, newVal));
  11.767         return newVal;
  11.768     }
  11.769 
  11.770     T operator <<= (unsigned bits)
  11.771     {
  11.772         T comp, newVal;
  11.773         do {
  11.774             comp   = this->Value;
  11.775             newVal = comp << bits;
  11.776         } while(!this->CompareAndSet_Sync(comp, newVal));
  11.777         return newVal;
  11.778     }
  11.779 };
  11.780 
  11.781 
  11.782 
  11.783 //-----------------------------------------------------------------------------------
  11.784 // ***** Lock
  11.785 
  11.786 // Lock is a simplest and most efficient mutual-exclusion lock class.
  11.787 // Unlike Mutex, it cannot be waited on.
  11.788 
  11.789 class Lock
  11.790 {
  11.791     // NOTE: Locks are not allocatable and they themselves should not allocate 
  11.792     // memory by standard means. This is the case because StandardAllocator
  11.793     // relies on this class.
  11.794     // Make 'delete' private. Don't do this for 'new' since it can be redefined.  
  11.795     void    operator delete(void*) {}
  11.796 
  11.797 
  11.798     // *** Lock implementation for various platforms.
  11.799     
  11.800 #if !defined(OVR_ENABLE_THREADS)
  11.801 
  11.802 public:
  11.803     // With no thread support, lock does nothing.
  11.804     inline Lock() { }
  11.805     inline Lock(unsigned) { }
  11.806     inline ~Lock() { }    
  11.807     inline void DoLock() { }
  11.808     inline void Unlock() { }
  11.809 
  11.810    // Windows.   
  11.811 #elif defined(OVR_OS_WIN32)
  11.812 
  11.813     CRITICAL_SECTION cs;
  11.814 public:   
  11.815     Lock(unsigned spinCount = 0);      
  11.816     ~Lock();
  11.817     // Locking functions.
  11.818     inline void DoLock()    { ::EnterCriticalSection(&cs); }
  11.819     inline void Unlock()    { ::LeaveCriticalSection(&cs); }
  11.820 
  11.821 #else
  11.822     pthread_mutex_t mutex;
  11.823 
  11.824 public:
  11.825     static pthread_mutexattr_t RecursiveAttr;
  11.826     static bool                RecursiveAttrInit;
  11.827 
  11.828     Lock (unsigned dummy = 0)
  11.829     {
  11.830         if (!RecursiveAttrInit)
  11.831         {
  11.832             pthread_mutexattr_init(&RecursiveAttr);
  11.833             pthread_mutexattr_settype(&RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
  11.834             RecursiveAttrInit = 1;
  11.835         }
  11.836         pthread_mutex_init(&mutex,&RecursiveAttr);
  11.837     }
  11.838     ~Lock ()                { pthread_mutex_destroy(&mutex); }
  11.839     inline void DoLock()    { pthread_mutex_lock(&mutex); }
  11.840     inline void Unlock()    { pthread_mutex_unlock(&mutex); }
  11.841 
  11.842 #endif // OVR_ENABLE_THREDS
  11.843 
  11.844 
  11.845 public:
  11.846     // Locker class, used for automatic locking
  11.847     class Locker
  11.848     {
  11.849     public:     
  11.850         Lock *pLock;
  11.851         inline Locker(Lock *plock)
  11.852         { pLock = plock; pLock->DoLock(); }
  11.853         inline ~Locker()
  11.854         { pLock->Unlock();  }
  11.855     };
  11.856 };
  11.857 
  11.858 
  11.859 
  11.860 } // OVR
  11.861 
  11.862 #endif
  11.863 \ No newline at end of file
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/libovr/Src/Kernel/OVR_Color.h	Sat Sep 14 16:14:59 2013 +0300
    12.3 @@ -0,0 +1,1 @@
    12.4 +/************************************************************************************
    12.5 
    12.6 PublicHeader:   OVR.h
    12.7 Filename    :   OVR_Color.h
    12.8 Content     :   Contains color struct.
    12.9 Created     :   February 7, 2013
   12.10 Notes       : 
   12.11 
   12.12 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   12.13 
   12.14 Use of this software is subject to the terms of the Oculus license
   12.15 agreement provided at the time of installation or download, or which
   12.16 otherwise accompanies this software in either electronic or hard copy form.
   12.17 
   12.18 ************************************************************************************/
   12.19 #ifndef OVR_Color_h
   12.20 #define OVR_Color_h
   12.21 
   12.22 #include "OVR_Types.h"
   12.23 
   12.24 namespace OVR {
   12.25 
   12.26 struct Color
   12.27 {
   12.28     UByte R,G,B,A;
   12.29 
   12.30     Color() {}
   12.31 
   12.32     // Constructs color by channel. Alpha is set to 0xFF (fully visible)
   12.33     // if not specified.
   12.34     Color(unsigned char r,unsigned char g,unsigned char b, unsigned char a = 0xFF)
   12.35         : R(r), G(g), B(b), A(a) { }
   12.36 
   12.37     // 0xAARRGGBB - Common HTML color Hex layout
   12.38     Color(unsigned c)
   12.39         : R((unsigned char)(c>>16)), G((unsigned char)(c>>8)),
   12.40         B((unsigned char)c), A((unsigned char)(c>>24)) { }
   12.41 
   12.42     bool operator==(const Color& b) const
   12.43     {
   12.44         return R == b.R && G == b.G && B == b.B && A == b.A;
   12.45     }
   12.46 
   12.47     void  GetRGBA(float *r, float *g, float *b, float* a) const
   12.48     {
   12.49         *r = R / 255.0f;
   12.50         *g = G / 255.0f;
   12.51         *b = B / 255.0f;
   12.52         *a = A / 255.0f;
   12.53     }
   12.54 };
   12.55 
   12.56 }
   12.57 
   12.58 #endif
   12.59 \ No newline at end of file
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/libovr/Src/Kernel/OVR_ContainerAllocator.h	Sat Sep 14 16:14:59 2013 +0300
    13.3 @@ -0,0 +1,1 @@
    13.4 +/************************************************************************************
    13.5 
    13.6 PublicHeader:   OVR.h
    13.7 Filename    :   OVR_ContainerAllocator.h
    13.8 Content     :   Template allocators and constructors for containers.
    13.9 Created     :   September 19, 2012
   13.10 Notes       : 
   13.11 
   13.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   13.13 
   13.14 Use of this software is subject to the terms of the Oculus license
   13.15 agreement provided at the time of installation or download, or which
   13.16 otherwise accompanies this software in either electronic or hard copy form.
   13.17 
   13.18 ************************************************************************************/
   13.19 
   13.20 #ifndef OVR_ContainerAllocator_h
   13.21 #define OVR_ContainerAllocator_h
   13.22 
   13.23 #include "OVR_Allocator.h"
   13.24 #include <string.h>
   13.25 
   13.26 
   13.27 namespace OVR {
   13.28 
   13.29 
   13.30 //-----------------------------------------------------------------------------------
   13.31 // ***** Container Allocator
   13.32 
   13.33 // ContainerAllocator serves as a template argument for allocations done by
   13.34 // containers, such as Array and Hash; replacing it could allow allocator
   13.35 // substitution in containers.
   13.36 
   13.37 class ContainerAllocatorBase
   13.38 {
   13.39 public:
   13.40     static void* Alloc(UPInt size)                { return OVR_ALLOC(size); }
   13.41     static void* Realloc(void* p, UPInt newSize)  { return OVR_REALLOC(p, newSize); }
   13.42     static void  Free(void *p)                    { OVR_FREE(p); }
   13.43 };
   13.44 
   13.45 
   13.46 
   13.47 //-----------------------------------------------------------------------------------
   13.48 // ***** Constructors, Destructors, Copiers
   13.49 
   13.50 // Plain Old Data - movable, no special constructors/destructor.
   13.51 template<class T> 
   13.52 class ConstructorPOD
   13.53 {
   13.54 public:
   13.55     static void Construct(void *) {}
   13.56     static void Construct(void *p, const T& source) 
   13.57     { 
   13.58         *(T*)p = source;
   13.59     }
   13.60 
   13.61     // Same as above, but allows for a different type of constructor.
   13.62     template <class S> 
   13.63     static void ConstructAlt(void *p, const S& source)
   13.64     {
   13.65         *(T*)p = source;
   13.66     }
   13.67 
   13.68     static void ConstructArray(void*, UPInt) {}
   13.69 
   13.70     static void ConstructArray(void* p, UPInt count, const T& source)
   13.71     {
   13.72         UByte *pdata = (UByte*)p;
   13.73         for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
   13.74             *(T*)pdata = source;
   13.75     }
   13.76 
   13.77     static void ConstructArray(void* p, UPInt count, const T* psource)
   13.78     {
   13.79         memcpy(p, psource, sizeof(T) * count);
   13.80     }
   13.81 
   13.82     static void Destruct(T*) {}
   13.83     static void DestructArray(T*, UPInt) {}
   13.84 
   13.85     static void CopyArrayForward(T* dst, const T* src, UPInt count)
   13.86     {
   13.87         memmove(dst, src, count * sizeof(T));
   13.88     }
   13.89 
   13.90     static void CopyArrayBackward(T* dst, const T* src, UPInt count)
   13.91     {
   13.92         memmove(dst, src, count * sizeof(T));
   13.93     }
   13.94 
   13.95     static bool IsMovable() { return true; }
   13.96 };
   13.97 
   13.98 
   13.99 //-----------------------------------------------------------------------------------
  13.100 // ***** ConstructorMov
  13.101 //
  13.102 // Correct C++ construction and destruction for movable objects
  13.103 template<class T> 
  13.104 class ConstructorMov
  13.105 {
  13.106 public:
  13.107     static void Construct(void* p) 
  13.108     { 
  13.109         OVR::Construct<T>(p);
  13.110     }
  13.111 
  13.112     static void Construct(void* p, const T& source) 
  13.113     { 
  13.114         OVR::Construct<T>(p, source);
  13.115     }
  13.116 
  13.117     // Same as above, but allows for a different type of constructor.
  13.118     template <class S> 
  13.119     static void ConstructAlt(void* p, const S& source)
  13.120     {
  13.121         OVR::ConstructAlt<T,S>(p, source);
  13.122     }
  13.123 
  13.124     static void ConstructArray(void* p, UPInt count)
  13.125     {
  13.126         UByte* pdata = (UByte*)p;
  13.127         for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
  13.128             Construct(pdata);
  13.129     }
  13.130 
  13.131     static void ConstructArray(void* p, UPInt count, const T& source)
  13.132     {
  13.133         UByte* pdata = (UByte*)p;
  13.134         for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
  13.135             Construct(pdata, source);
  13.136     }
  13.137 
  13.138     static void ConstructArray(void* p, UPInt count, const T* psource)
  13.139     {
  13.140         UByte* pdata = (UByte*)p;
  13.141         for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
  13.142             Construct(pdata, *psource++);
  13.143     }
  13.144 
  13.145     static void Destruct(T* p)
  13.146     {
  13.147         p->~T();
  13.148         OVR_UNUSED(p); // Suppress silly MSVC warning
  13.149     }
  13.150 
  13.151     static void DestructArray(T* p, UPInt count)
  13.152     {   
  13.153         p += count - 1;
  13.154         for (UPInt i=0; i<count; ++i, --p)
  13.155             p->~T();
  13.156     }
  13.157 
  13.158     static void CopyArrayForward(T* dst, const T* src, UPInt count)
  13.159     {
  13.160         memmove(dst, src, count * sizeof(T));
  13.161     }
  13.162 
  13.163     static void CopyArrayBackward(T* dst, const T* src, UPInt count)
  13.164     {
  13.165         memmove(dst, src, count * sizeof(T));
  13.166     }
  13.167 
  13.168     static bool IsMovable() { return true; }
  13.169 };
  13.170 
  13.171 
  13.172 //-----------------------------------------------------------------------------------
  13.173 // ***** ConstructorCPP
  13.174 //
  13.175 // Correct C++ construction and destruction for movable objects
  13.176 template<class T> 
  13.177 class ConstructorCPP
  13.178 {
  13.179 public:
  13.180     static void Construct(void* p) 
  13.181     { 
  13.182         OVR::Construct<T>(p);        
  13.183     }
  13.184 
  13.185     static void Construct(void* p, const T& source) 
  13.186     { 
  13.187         OVR::Construct<T>(p, source);        
  13.188     }
  13.189 
  13.190     // Same as above, but allows for a different type of constructor.
  13.191     template <class S> 
  13.192     static void ConstructAlt(void* p, const S& source)
  13.193     {
  13.194         OVR::ConstructAlt<T,S>(p, source);        
  13.195     }
  13.196 
  13.197     static void ConstructArray(void* p, UPInt count)
  13.198     {
  13.199         UByte* pdata = (UByte*)p;
  13.200         for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
  13.201             Construct(pdata);
  13.202     }
  13.203 
  13.204     static void ConstructArray(void* p, UPInt count, const T& source)
  13.205     {
  13.206         UByte* pdata = (UByte*)p;
  13.207         for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
  13.208             Construct(pdata, source);
  13.209     }
  13.210 
  13.211     static void ConstructArray(void* p, UPInt count, const T* psource)
  13.212     {
  13.213         UByte* pdata = (UByte*)p;
  13.214         for (UPInt i=0; i< count; ++i, pdata += sizeof(T))
  13.215             Construct(pdata, *psource++);
  13.216     }
  13.217 
  13.218     static void Destruct(T* p)
  13.219     {
  13.220         p->~T();
  13.221         OVR_UNUSED(p); // Suppress silly MSVC warning
  13.222     }
  13.223 
  13.224     static void DestructArray(T* p, UPInt count)
  13.225     {   
  13.226         p += count - 1;
  13.227         for (UPInt i=0; i<count; ++i, --p)
  13.228             p->~T();
  13.229     }
  13.230 
  13.231     static void CopyArrayForward(T* dst, const T* src, UPInt count)
  13.232     {
  13.233         for(UPInt i = 0; i < count; ++i)
  13.234             dst[i] = src[i];
  13.235     }
  13.236 
  13.237     static void CopyArrayBackward(T* dst, const T* src, UPInt count)
  13.238     {
  13.239         for(UPInt i = count; i; --i)
  13.240             dst[i-1] = src[i-1];
  13.241     }
  13.242 
  13.243     static bool IsMovable() { return false; }
  13.244 };
  13.245 
  13.246 
  13.247 //-----------------------------------------------------------------------------------
  13.248 // ***** Container Allocator with movement policy
  13.249 //
  13.250 // Simple wraps as specialized allocators
  13.251 template<class T> struct ContainerAllocator_POD : ContainerAllocatorBase, ConstructorPOD<T> {};
  13.252 template<class T> struct ContainerAllocator     : ContainerAllocatorBase, ConstructorMov<T> {};
  13.253 template<class T> struct ContainerAllocator_CPP : ContainerAllocatorBase, ConstructorCPP<T> {};
  13.254 
  13.255 
  13.256 } // OVR
  13.257 
  13.258 
  13.259 #endif
  13.260 \ No newline at end of file
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/libovr/Src/Kernel/OVR_File.cpp	Sat Sep 14 16:14:59 2013 +0300
    14.3 @@ -0,0 +1,1 @@
    14.4 +/**************************************************************************
    14.5 
    14.6 Filename    :   OVR_File.cpp
    14.7 Content     :   File wrapper class implementation (Win32)
    14.8 
    14.9 Created     :   April 5, 1999
   14.10 Authors     :   Michael Antonov
   14.11 
   14.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   14.13 
   14.14 Use of this software is subject to the terms of the Oculus license
   14.15 agreement provided at the time of installation or download, or which
   14.16 otherwise accompanies this software in either electronic or hard copy form.
   14.17 
   14.18 **************************************************************************/
   14.19 
   14.20 #define  GFILE_CXX
   14.21 
   14.22 // Standard C library (Captain Obvious guarantees!)
   14.23 #include <stdio.h>
   14.24 
   14.25 #include "OVR_File.h"
   14.26 
   14.27 namespace OVR {
   14.28 
   14.29 // Buffered file adds buffering to an existing file
   14.30 // FILEBUFFER_SIZE defines the size of internal buffer, while
   14.31 // FILEBUFFER_TOLERANCE controls the amount of data we'll effectively try to buffer
   14.32 #define FILEBUFFER_SIZE         (8192-8)
   14.33 #define FILEBUFFER_TOLERANCE    4096
   14.34 
   14.35 // ** Constructor/Destructor
   14.36 
   14.37 // Hidden constructor
   14.38 // Not supposed to be used
   14.39 BufferedFile::BufferedFile() : DelegatedFile(0)
   14.40 {
   14.41     pBuffer     = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE);
   14.42     BufferMode  = NoBuffer;
   14.43     FilePos     = 0;
   14.44     Pos         = 0;
   14.45     DataSize    = 0;
   14.46 }
   14.47 
   14.48 // Takes another file as source
   14.49 BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile)
   14.50 {
   14.51     pBuffer     = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE);
   14.52     BufferMode  = NoBuffer;
   14.53     FilePos     = pfile->LTell();
   14.54     Pos         = 0;
   14.55     DataSize    = 0;
   14.56 }
   14.57 
   14.58 
   14.59 // Destructor
   14.60 BufferedFile::~BufferedFile()
   14.61 {
   14.62     // Flush in case there's data
   14.63     if (pFile)
   14.64         FlushBuffer();
   14.65     // Get rid of buffer
   14.66     if (pBuffer)
   14.67         OVR_FREE(pBuffer);
   14.68 }
   14.69 
   14.70 /*
   14.71 bool    BufferedFile::VCopy(const Object &source)
   14.72 {
   14.73     if (!DelegatedFile::VCopy(source))
   14.74         return 0;
   14.75 
   14.76     // Data members
   14.77     BufferedFile *psource = (BufferedFile*)&source;
   14.78 
   14.79     // Buffer & the mode it's in
   14.80     pBuffer         = psource->pBuffer;
   14.81     BufferMode      = psource->BufferMode;
   14.82     Pos             = psource->Pos;
   14.83     DataSize        = psource->DataSize;
   14.84     return 1;
   14.85 }
   14.86 */
   14.87 
   14.88 // Initializes buffering to a certain mode
   14.89 bool    BufferedFile::SetBufferMode(BufferModeType mode)
   14.90 {
   14.91     if (!pBuffer)
   14.92         return false;
   14.93     if (mode == BufferMode)
   14.94         return true;
   14.95      
   14.96     FlushBuffer();
   14.97 
   14.98     // Can't set write mode if we can't write
   14.99     if ((mode==WriteBuffer) && (!pFile || !pFile->IsWritable()) )
  14.100         return 0;
  14.101 
  14.102     // And SetMode
  14.103     BufferMode = mode;
  14.104     Pos        = 0;
  14.105     DataSize   = 0;
  14.106     return 1;
  14.107 }
  14.108 
  14.109 // Flushes buffer
  14.110 void    BufferedFile::FlushBuffer()
  14.111 {
  14.112     switch(BufferMode)
  14.113     {
  14.114         case WriteBuffer:
  14.115             // Write data in buffer
  14.116             FilePos += pFile->Write(pBuffer,Pos);
  14.117             Pos = 0;
  14.118             break;
  14.119 
  14.120         case ReadBuffer:
  14.121             // Seek back & reset buffer data
  14.122             if ((DataSize-Pos)>0)
  14.123                 FilePos = pFile->LSeek(-(int)(DataSize-Pos), Seek_Cur);
  14.124             DataSize = 0;
  14.125             Pos      = 0;
  14.126             break;
  14.127         default:
  14.128             // not handled!
  14.129             break;
  14.130     }
  14.131 }
  14.132 
  14.133 // Reloads data for ReadBuffer
  14.134 void    BufferedFile::LoadBuffer()
  14.135 {
  14.136     if (BufferMode == ReadBuffer)
  14.137     {
  14.138         // We should only reload once all of pre-loaded buffer is consumed.
  14.139         OVR_ASSERT(Pos == DataSize);
  14.140 
  14.141         // WARNING: Right now LoadBuffer() assumes the buffer's empty
  14.142         int sz   = pFile->Read(pBuffer,FILEBUFFER_SIZE);
  14.143         DataSize = sz<0 ? 0 : (unsigned)sz;
  14.144         Pos      = 0;
  14.145         FilePos  += DataSize;
  14.146     }
  14.147 }
  14.148 
  14.149 
  14.150 // ** Overridden functions
  14.151 
  14.152 // We override all the functions that can possibly
  14.153 // require buffer mode switch, flush, or extra calculations
  14.154 
  14.155 // Tell() requires buffer adjustment
  14.156 int     BufferedFile::Tell()
  14.157 {
  14.158     if (BufferMode == ReadBuffer)
  14.159         return int (FilePos - DataSize + Pos);
  14.160 
  14.161     int pos = pFile->Tell();
  14.162     // Adjust position based on buffer mode & data
  14.163     if (pos!=-1)
  14.164     {
  14.165         OVR_ASSERT(BufferMode != ReadBuffer);
  14.166         if (BufferMode == WriteBuffer)
  14.167             pos += Pos;
  14.168     }
  14.169     return pos;
  14.170 }
  14.171 
  14.172 SInt64  BufferedFile::LTell()
  14.173 {
  14.174     if (BufferMode == ReadBuffer)
  14.175         return FilePos - DataSize + Pos;
  14.176 
  14.177     SInt64 pos = pFile->LTell();
  14.178     if (pos!=-1)
  14.179     {
  14.180         OVR_ASSERT(BufferMode != ReadBuffer);
  14.181         if (BufferMode == WriteBuffer)
  14.182             pos += Pos;
  14.183     }
  14.184     return pos;
  14.185 }
  14.186 
  14.187 int     BufferedFile::GetLength()
  14.188 {
  14.189     int len = pFile->GetLength();
  14.190     // If writing through buffer, file length may actually be bigger
  14.191     if ((len!=-1) && (BufferMode==WriteBuffer))
  14.192     {
  14.193         int currPos = pFile->Tell() + Pos;
  14.194         if (currPos>len)
  14.195             len = currPos;
  14.196     }
  14.197     return len;
  14.198 }
  14.199 SInt64  BufferedFile::LGetLength()
  14.200 {
  14.201     SInt64 len = pFile->LGetLength();
  14.202     // If writing through buffer, file length may actually be bigger
  14.203     if ((len!=-1) && (BufferMode==WriteBuffer))
  14.204     {
  14.205         SInt64 currPos = pFile->LTell() + Pos;
  14.206         if (currPos>len)
  14.207             len = currPos;
  14.208     }
  14.209     return len;
  14.210 }
  14.211 
  14.212 /*
  14.213 bool    BufferedFile::Stat(FileStats *pfs)
  14.214 {
  14.215     // Have to fix up length is stat
  14.216     if (pFile->Stat(pfs))
  14.217     {
  14.218         if (BufferMode==WriteBuffer)
  14.219         {
  14.220             SInt64 currPos = pFile->LTell() + Pos;
  14.221             if (currPos > pfs->Size)
  14.222             {
  14.223                 pfs->Size   = currPos;
  14.224                 // ??
  14.225                 pfs->Blocks = (pfs->Size+511) >> 9;
  14.226             }
  14.227         }
  14.228         return 1;
  14.229     }
  14.230     return 0;
  14.231 }
  14.232 */
  14.233 
  14.234 int     BufferedFile::Write(const UByte *psourceBuffer, int numBytes)
  14.235 {
  14.236     if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer))
  14.237     {
  14.238         // If not data space in buffer, flush
  14.239         if ((FILEBUFFER_SIZE-(int)Pos)<numBytes)
  14.240         {
  14.241             FlushBuffer();
  14.242             // If bigger then tolerance, just write directly
  14.243             if (numBytes>FILEBUFFER_TOLERANCE)
  14.244             {
  14.245                 int sz = pFile->Write(psourceBuffer,numBytes);
  14.246                 if (sz > 0)
  14.247                     FilePos += sz;
  14.248                 return sz;
  14.249             }
  14.250         }
  14.251 
  14.252         // Enough space in buffer.. so copy to it
  14.253         memcpy(pBuffer+Pos, psourceBuffer, numBytes);
  14.254         Pos += numBytes;
  14.255         return numBytes;
  14.256     }
  14.257     int sz = pFile->Write(psourceBuffer,numBytes);
  14.258     if (sz > 0)
  14.259         FilePos += sz;
  14.260     return sz;
  14.261 }
  14.262 
  14.263 int     BufferedFile::Read(UByte *pdestBuffer, int numBytes)
  14.264 {
  14.265     if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer))
  14.266     {
  14.267         // Data in buffer... copy it
  14.268         if ((int)(DataSize-Pos) >= numBytes)
  14.269         {
  14.270             memcpy(pdestBuffer, pBuffer+Pos, numBytes);
  14.271             Pos += numBytes;
  14.272             return numBytes;
  14.273         }
  14.274 
  14.275         // Not enough data in buffer, copy buffer
  14.276         int     readBytes = DataSize-Pos;
  14.277         memcpy(pdestBuffer, pBuffer+Pos, readBytes);
  14.278         numBytes    -= readBytes;
  14.279         pdestBuffer += readBytes;
  14.280         Pos = DataSize;
  14.281 
  14.282         // Don't reload buffer if more then tolerance
  14.283         // (No major advantage, and we don't want to write a loop)
  14.284         if (numBytes>FILEBUFFER_TOLERANCE)
  14.285         {
  14.286             numBytes = pFile->Read(pdestBuffer,numBytes);
  14.287             if (numBytes > 0)
  14.288             {
  14.289                 FilePos += numBytes;
  14.290                 Pos = DataSize = 0;
  14.291             }
  14.292             return readBytes + ((numBytes==-1) ? 0 : numBytes);
  14.293         }
  14.294 
  14.295         // Reload the buffer
  14.296         // WARNING: Right now LoadBuffer() assumes the buffer's empty
  14.297         LoadBuffer();
  14.298         if ((int)(DataSize-Pos) < numBytes)
  14.299             numBytes = (int)DataSize-Pos;
  14.300 
  14.301         memcpy(pdestBuffer, pBuffer+Pos, numBytes);
  14.302         Pos += numBytes;
  14.303         return numBytes + readBytes;
  14.304         
  14.305         /*
  14.306         // Alternative Read implementation. The one above is probably better
  14.307         // due to FILEBUFFER_TOLERANCE.
  14.308         int     total = 0;
  14.309 
  14.310         do {
  14.311             int     bufferBytes = (int)(DataSize-Pos);
  14.312             int     copyBytes = (bufferBytes > numBytes) ? numBytes : bufferBytes;
  14.313 
  14.314             memcpy(pdestBuffer, pBuffer+Pos, copyBytes);
  14.315             numBytes    -= copyBytes;
  14.316             pdestBuffer += copyBytes;
  14.317             Pos         += copyBytes;
  14.318             total       += copyBytes;
  14.319 
  14.320             if (numBytes == 0)
  14.321                 break;
  14.322             LoadBuffer();
  14.323 
  14.324         } while (DataSize > 0);
  14.325 
  14.326         return total;
  14.327         */     
  14.328     }
  14.329     int sz = pFile->Read(pdestBuffer,numBytes);
  14.330     if (sz > 0)
  14.331         FilePos += sz;
  14.332     return sz;
  14.333 }
  14.334 
  14.335 
  14.336 int     BufferedFile::SkipBytes(int numBytes)
  14.337 {
  14.338     int skippedBytes = 0;
  14.339 
  14.340     // Special case for skipping a little data in read buffer
  14.341     if (BufferMode==ReadBuffer)
  14.342     {
  14.343         skippedBytes = (((int)DataSize-(int)Pos) >= numBytes) ? numBytes : (DataSize-Pos);
  14.344         Pos          += skippedBytes;
  14.345         numBytes     -= skippedBytes;
  14.346     }
  14.347 
  14.348     if (numBytes)
  14.349     {
  14.350         numBytes = pFile->SkipBytes(numBytes);
  14.351         // Make sure we return the actual number skipped, or error
  14.352         if (numBytes!=-1)
  14.353         {
  14.354             skippedBytes += numBytes;
  14.355             FilePos += numBytes;
  14.356             Pos = DataSize = 0;
  14.357         }
  14.358         else if (skippedBytes <= 0)
  14.359             skippedBytes = -1;
  14.360     }
  14.361     return skippedBytes;
  14.362 }
  14.363 
  14.364 int     BufferedFile::BytesAvailable()
  14.365 {
  14.366     int available = pFile->BytesAvailable();
  14.367     // Adjust available size based on buffers
  14.368     switch(BufferMode)
  14.369     {
  14.370         case ReadBuffer:
  14.371             available += DataSize-Pos;
  14.372             break;
  14.373         case WriteBuffer:
  14.374             available -= Pos;
  14.375             if (available<0)
  14.376                 available= 0;
  14.377             break;
  14.378         default:
  14.379             break;
  14.380     }
  14.381     return available;
  14.382 }
  14.383 
  14.384 bool    BufferedFile::Flush()
  14.385 {
  14.386     FlushBuffer();
  14.387     return pFile->Flush();
  14.388 }
  14.389 
  14.390 // Seeking could be optimized better..
  14.391 int     BufferedFile::Seek(int offset, int origin)
  14.392 {    
  14.393     if (BufferMode == ReadBuffer)
  14.394     {
  14.395         if (origin == Seek_Cur)
  14.396         {
  14.397             // Seek can fall either before or after Pos in the buffer,
  14.398             // but it must be within bounds.
  14.399             if (((unsigned(offset) + Pos)) <= DataSize)
  14.400             {
  14.401                 Pos += offset;
  14.402                 return int (FilePos - DataSize + Pos);
  14.403             }
  14.404 
  14.405             // Lightweight buffer "Flush". We do this to avoid an extra seek
  14.406             // back operation which would take place if we called FlushBuffer directly.
  14.407             origin = Seek_Set;
  14.408             OVR_ASSERT(((FilePos - DataSize + Pos) + (UInt64)offset) < ~(UInt64)0);
  14.409             offset = (int)(FilePos - DataSize + Pos) + offset;
  14.410             Pos = DataSize = 0;
  14.411         }
  14.412         else if (origin == Seek_Set)
  14.413         {
  14.414             if (((unsigned)offset - (FilePos-DataSize)) <= DataSize)
  14.415             {
  14.416                 OVR_ASSERT((FilePos-DataSize) < ~(UInt64)0);
  14.417                 Pos = (unsigned)offset - (unsigned)(FilePos-DataSize);
  14.418                 return offset;
  14.419             }
  14.420             Pos = DataSize = 0;
  14.421         }
  14.422         else
  14.423         {
  14.424             FlushBuffer();
  14.425         }
  14.426     }
  14.427     else
  14.428     {
  14.429         FlushBuffer();
  14.430     }    
  14.431 
  14.432     /*
  14.433     // Old Seek Logic
  14.434     if (origin == Seek_Cur && offset + Pos < DataSize)
  14.435     {
  14.436         //OVR_ASSERT((FilePos - DataSize) >= (FilePos - DataSize + Pos + offset));
  14.437         Pos += offset;
  14.438         OVR_ASSERT(int (Pos) >= 0);
  14.439         return int (FilePos - DataSize + Pos);
  14.440     }
  14.441     else if (origin == Seek_Set && unsigned(offset) >= FilePos - DataSize && unsigned(offset) < FilePos)
  14.442     {
  14.443         Pos = unsigned(offset - FilePos + DataSize);
  14.444         OVR_ASSERT(int (Pos) >= 0);
  14.445         return int (FilePos - DataSize + Pos);
  14.446     }   
  14.447     
  14.448     FlushBuffer();
  14.449     */
  14.450 
  14.451 
  14.452     FilePos = pFile->Seek(offset,origin);
  14.453     return int (FilePos);
  14.454 }
  14.455 
  14.456 SInt64  BufferedFile::LSeek(SInt64 offset, int origin)
  14.457 {
  14.458     if (BufferMode == ReadBuffer)
  14.459     {
  14.460         if (origin == Seek_Cur)
  14.461         {
  14.462             // Seek can fall either before or after Pos in the buffer,
  14.463             // but it must be within bounds.
  14.464             if (((unsigned(offset) + Pos)) <= DataSize)
  14.465             {
  14.466                 Pos += (unsigned)offset;
  14.467                 return SInt64(FilePos - DataSize + Pos);
  14.468             }
  14.469 
  14.470             // Lightweight buffer "Flush". We do this to avoid an extra seek
  14.471             // back operation which would take place if we called FlushBuffer directly.
  14.472             origin = Seek_Set;            
  14.473             offset = (SInt64)(FilePos - DataSize + Pos) + offset;
  14.474             Pos = DataSize = 0;
  14.475         }
  14.476         else if (origin == Seek_Set)
  14.477         {
  14.478             if (((UInt64)offset - (FilePos-DataSize)) <= DataSize)
  14.479             {                
  14.480                 Pos = (unsigned)((UInt64)offset - (FilePos-DataSize));
  14.481                 return offset;
  14.482             }
  14.483             Pos = DataSize = 0;
  14.484         }
  14.485         else
  14.486         {
  14.487             FlushBuffer();
  14.488         }
  14.489     }
  14.490     else
  14.491     {
  14.492         FlushBuffer();
  14.493     }
  14.494 
  14.495 /*
  14.496     OVR_ASSERT(BufferMode != NoBuffer);
  14.497 
  14.498     if (origin == Seek_Cur && offset + Pos < DataSize)
  14.499     {
  14.500         Pos += int (offset);
  14.501         return FilePos - DataSize + Pos;
  14.502     }
  14.503     else if (origin == Seek_Set && offset >= SInt64(FilePos - DataSize) && offset < SInt64(FilePos))
  14.504     {
  14.505         Pos = unsigned(offset - FilePos + DataSize);
  14.506         return FilePos - DataSize + Pos;
  14.507     }
  14.508 
  14.509     FlushBuffer();
  14.510     */
  14.511 
  14.512     FilePos = pFile->LSeek(offset,origin);
  14.513     return FilePos;
  14.514 }
  14.515 
  14.516 int     BufferedFile::CopyFromStream(File *pstream, int byteSize)
  14.517 {
  14.518     // We can't rely on overridden Write()
  14.519     // because delegation doesn't override virtual pointers
  14.520     // So, just re-implement
  14.521     UByte   buff[0x4000];
  14.522     int     count = 0;
  14.523     int     szRequest, szRead, szWritten;
  14.524 
  14.525     while(byteSize)
  14.526     {
  14.527         szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
  14.528 
  14.529         szRead    = pstream->Read(buff,szRequest);
  14.530         szWritten = 0;
  14.531         if (szRead > 0)
  14.532             szWritten = Write(buff,szRead);
  14.533 
  14.534         count   +=szWritten;
  14.535         byteSize-=szWritten;
  14.536         if (szWritten < szRequest)
  14.537             break;
  14.538     }
  14.539     return count;
  14.540 }
  14.541 
  14.542 // Closing files
  14.543 bool    BufferedFile::Close()
  14.544 {
  14.545     switch(BufferMode)
  14.546     {
  14.547         case WriteBuffer:
  14.548             FlushBuffer();
  14.549             break;
  14.550         case ReadBuffer:
  14.551             // No need to seek back on close
  14.552             BufferMode = NoBuffer;
  14.553             break;
  14.554         default:
  14.555             break;
  14.556     }
  14.557     return pFile->Close();
  14.558 }
  14.559 
  14.560 
  14.561 // ***** Global path helpers
  14.562 
  14.563 // Find trailing short filename in a path.
  14.564 const char* OVR_CDECL GetShortFilename(const char* purl)
  14.565 {    
  14.566     UPInt len = OVR_strlen(purl);
  14.567     for (UPInt i=len; i>0; i--) 
  14.568         if (purl[i]=='\\' || purl[i]=='/')
  14.569             return purl+i+1;
  14.570     return purl;
  14.571 }
  14.572 
  14.573 } // OVR
  14.574 
  14.575 \ No newline at end of file
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/libovr/Src/Kernel/OVR_File.h	Sat Sep 14 16:14:59 2013 +0300
    15.3 @@ -0,0 +1,1 @@
    15.4 +/************************************************************************************
    15.5 
    15.6 PublicHeader:   Kernel
    15.7 Filename    :   OVR_File.h
    15.8 Content     :   Header for all internal file management - functions and structures
    15.9                 to be inherited by OS specific subclasses.
   15.10 Created     :   September 19, 2012
   15.11 Notes       : 
   15.12 
   15.13 Notes       :   errno may not be preserved across use of BaseFile member functions
   15.14             :   Directories cannot be deleted while files opened from them are in use
   15.15                 (For the GetFullName function)
   15.16 
   15.17 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   15.18 
   15.19 Use of this software is subject to the terms of the Oculus license
   15.20 agreement provided at the time of installation or download, or which
   15.21 otherwise accompanies this software in either electronic or hard copy form.
   15.22 
   15.23 ************************************************************************************/
   15.24 
   15.25 #ifndef OVR_File_h
   15.26 #define OVR_File_h
   15.27 
   15.28 #include "OVR_RefCount.h"
   15.29 #include "OVR_Std.h"
   15.30 #include "OVR_Alg.h"
   15.31 
   15.32 #include <stdio.h>
   15.33 #include "OVR_String.h"
   15.34 
   15.35 namespace OVR {
   15.36 
   15.37 // ***** Declared classes
   15.38 class   FileConstants;
   15.39 class   File;
   15.40 class   DelegatedFile;
   15.41 class   BufferedFile;
   15.42 
   15.43 
   15.44 // ***** Flags for File & Directory accesses
   15.45 
   15.46 class FileConstants
   15.47 {
   15.48 public:
   15.49 
   15.50     // *** File open flags
   15.51     enum OpenFlags
   15.52     {
   15.53         Open_Read       = 1,
   15.54         Open_Write      = 2,
   15.55         Open_ReadWrite  = 3,
   15.56 
   15.57         // Opens file and truncates it to zero length
   15.58         // - file must have write permission
   15.59         // - when used with Create, it opens an existing 
   15.60         //   file and empties it or creates a new file
   15.61         Open_Truncate   = 4,
   15.62 
   15.63         // Creates and opens new file 
   15.64         // - does not erase contents if file already
   15.65         //   exists unless combined with Truncate
   15.66         Open_Create     = 8,
   15.67 
   15.68          // Returns an error value if the file already exists
   15.69         Open_CreateOnly = 24,
   15.70 
   15.71         // Open file with buffering
   15.72         Open_Buffered    = 32
   15.73     };
   15.74 
   15.75     // *** File Mode flags
   15.76     enum Modes
   15.77     {
   15.78         Mode_Read       = 0444,
   15.79         Mode_Write      = 0222,
   15.80         Mode_Execute    = 0111,
   15.81 
   15.82         Mode_ReadWrite  = 0666
   15.83     };
   15.84 
   15.85     // *** Seek operations
   15.86     enum SeekOps
   15.87     {
   15.88         Seek_Set        = 0,
   15.89         Seek_Cur        = 1,
   15.90         Seek_End        = 2
   15.91     };
   15.92 
   15.93     // *** Errors
   15.94     enum Errors
   15.95     {
   15.96         Error_FileNotFound  = 0x1001,
   15.97         Error_Access        = 0x1002,
   15.98         Error_IOError       = 0x1003,
   15.99         Error_DiskFull      = 0x1004
  15.100     };
  15.101 };
  15.102 
  15.103 
  15.104 //-----------------------------------------------------------------------------------
  15.105 // ***** File Class
  15.106 
  15.107 // The pure virtual base random-access file
  15.108 // This is a base class to all files
  15.109 
  15.110 class File : public RefCountBase<File>, public FileConstants
  15.111 {   
  15.112 public:
  15.113     File() { }
  15.114     // ** Location Information
  15.115 
  15.116     // Returns a file name path relative to the 'reference' directory
  15.117     // This is often a path that was used to create a file
  15.118     // (this is not a global path, global path can be obtained with help of directory)
  15.119     virtual const char* GetFilePath() = 0;
  15.120                                                                                         
  15.121 
  15.122     // ** File Information
  15.123 
  15.124     // Return 1 if file's usable (open)
  15.125     virtual bool        IsValid() = 0;
  15.126     // Return 1 if file's writable, otherwise 0                                         
  15.127     virtual bool        IsWritable() = 0;
  15.128                                                                                         
  15.129     // Return position
  15.130     virtual int         Tell() = 0;
  15.131     virtual SInt64      LTell() = 0;
  15.132     
  15.133     // File size                                                                        
  15.134     virtual int         GetLength() = 0;
  15.135     virtual SInt64      LGetLength() = 0;
  15.136                                                                                         
  15.137     // Returns file stats                                                               
  15.138     // 0 for failure                                                                    
  15.139     //virtual bool      Stat(FileStats *pfs) = 0;
  15.140                                                                                         
  15.141     // Return errno-based error code                                                    
  15.142     // Useful if any other function failed                                              
  15.143     virtual int         GetErrorCode() = 0;
  15.144                                                                                         
  15.145                                                                                         
  15.146     // ** Stream implementation & I/O
  15.147 
  15.148     // Blocking write, will write in the given number of bytes to the stream
  15.149     // Returns : -1 for error
  15.150     //           Otherwise number of bytes read 
  15.151     virtual int         Write(const UByte *pbufer, int numBytes) = 0;
  15.152     // Blocking read, will read in the given number of bytes or less from the stream
  15.153     // Returns : -1 for error
  15.154     //           Otherwise number of bytes read,
  15.155     //           if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed
  15.156     virtual int         Read(UByte *pbufer, int numBytes) = 0;
  15.157 
  15.158     // Skips (ignores) a given # of bytes
  15.159     // Same return values as Read
  15.160     virtual int         SkipBytes(int numBytes) = 0;
  15.161         
  15.162     // Returns the number of bytes available to read from a stream without blocking
  15.163     // For a file, this should generally be number of bytes to the end
  15.164     virtual int         BytesAvailable() = 0;
  15.165 
  15.166     // Causes any implementation's buffered data to be delivered to destination
  15.167     // Return 0 for error
  15.168     virtual bool        Flush() = 0;
  15.169                                                                                             
  15.170 
  15.171     // Need to provide a more optimized implementation that doe snot necessarily involve a lot of seeking
  15.172     inline bool         IsEOF() { return !BytesAvailable(); }
  15.173     
  15.174 
  15.175     // Seeking                                                                              
  15.176     // Returns new position, -1 for error                                                   
  15.177     virtual int         Seek(int offset, int origin=Seek_Set) = 0;
  15.178     virtual SInt64      LSeek(SInt64 offset, int origin=Seek_Set) = 0;
  15.179     // Seek simplification
  15.180     int                 SeekToBegin()           {return Seek(0); }
  15.181     int                 SeekToEnd()             {return Seek(0,Seek_End); }
  15.182     int                 Skip(int numBytes)     {return Seek(numBytes,Seek_Cur); }
  15.183                         
  15.184 
  15.185     // Appends other file data from a stream
  15.186     // Return -1 for error, else # of bytes written
  15.187     virtual int         CopyFromStream(File *pstream, int byteSize) = 0;
  15.188 
  15.189     // Closes the file
  15.190     // After close, file cannot be accessed 
  15.191     virtual bool        Close() = 0;
  15.192 
  15.193 
  15.194     // ***** Inlines for convenient primitive type serialization
  15.195 
  15.196     // Read/Write helpers
  15.197 private:
  15.198     UInt64  PRead64()           { UInt64 v = 0; Read((UByte*)&v, 8); return v; }
  15.199     UInt32  PRead32()           { UInt32 v = 0; Read((UByte*)&v, 4); return v; }
  15.200     UInt16  PRead16()           { UInt16 v = 0; Read((UByte*)&v, 2); return v; }
  15.201     UByte   PRead8()            { UByte  v = 0; Read((UByte*)&v, 1); return v; }
  15.202     void    PWrite64(UInt64 v)  { Write((UByte*)&v, 8); }
  15.203     void    PWrite32(UInt32 v)  { Write((UByte*)&v, 4); }
  15.204     void    PWrite16(UInt16 v)  { Write((UByte*)&v, 2); }
  15.205     void    PWrite8(UByte v)    { Write((UByte*)&v, 1); }
  15.206 
  15.207 public:
  15.208 
  15.209     // Writing primitive types - Little Endian
  15.210     inline void    WriteUByte(UByte v)         { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v));     }
  15.211     inline void    WriteSByte(SByte v)         { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v));     }
  15.212     inline void    WriteUInt8(UByte v)         { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v));     }
  15.213     inline void    WriteSInt8(SByte v)         { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v));     }
  15.214     inline void    WriteUInt16(UInt16 v)       { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v));   }
  15.215     inline void    WriteSInt16(SInt16 v)       { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v));   }
  15.216     inline void    WriteUInt32(UInt32 v)       { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v));   }
  15.217     inline void    WriteSInt32(SInt32 v)       { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v));   }
  15.218     inline void    WriteUInt64(UInt64 v)       { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v));   }
  15.219     inline void    WriteSInt64(SInt64 v)       { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v));   }
  15.220     inline void    WriteFloat(float v)         { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 4); } 
  15.221     inline void    WriteDouble(double v)       { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 8); }
  15.222     // Writing primitive types - Big Endian
  15.223     inline void    WriteUByteBE(UByte v)       { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v));     }
  15.224     inline void    WriteSByteBE(SByte v)       { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v));     }
  15.225     inline void    WriteUInt8BE(UInt16 v)      { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v));     }
  15.226     inline void    WriteSInt8BE(SInt16 v)      { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v));     }
  15.227     inline void    WriteUInt16BE(UInt16 v)     { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v));   }
  15.228     inline void    WriteSInt16BE(UInt16 v)     { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v));   }
  15.229     inline void    WriteUInt32BE(UInt32 v)     { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v));   }
  15.230     inline void    WriteSInt32BE(UInt32 v)     { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v));   }
  15.231     inline void    WriteUInt64BE(UInt64 v)     { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v));   }
  15.232     inline void    WriteSInt64BE(UInt64 v)     { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v));   }
  15.233     inline void    WriteFloatBE(float v)       { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 4); }
  15.234     inline void    WriteDoubleBE(double v)     { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 8); }
  15.235         
  15.236     // Reading primitive types - Little Endian
  15.237     inline UByte   ReadUByte()                 { return (UByte)Alg::ByteUtil::LEToSystem(PRead8());    }
  15.238     inline SByte   ReadSByte()                 { return (SByte)Alg::ByteUtil::LEToSystem(PRead8());    }
  15.239     inline UByte   ReadUInt8()                 { return (UByte)Alg::ByteUtil::LEToSystem(PRead8());    }
  15.240     inline SByte   ReadSInt8()                 { return (SByte)Alg::ByteUtil::LEToSystem(PRead8());    }
  15.241     inline UInt16  ReadUInt16()                { return (UInt16)Alg::ByteUtil::LEToSystem(PRead16());  }
  15.242     inline SInt16  ReadSInt16()                { return (SInt16)Alg::ByteUtil::LEToSystem(PRead16());  }
  15.243     inline UInt32  ReadUInt32()                { return (UInt32)Alg::ByteUtil::LEToSystem(PRead32());  }
  15.244     inline SInt32  ReadSInt32()                { return (SInt32)Alg::ByteUtil::LEToSystem(PRead32());  }
  15.245     inline UInt64  ReadUInt64()                { return (UInt64)Alg::ByteUtil::LEToSystem(PRead64());  }
  15.246     inline SInt64  ReadSInt64()                { return (SInt64)Alg::ByteUtil::LEToSystem(PRead64());  }
  15.247     inline float   ReadFloat()                 { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::LEToSystem(v); }
  15.248     inline double  ReadDouble()                { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::LEToSystem(v); }
  15.249     // Reading primitive types - Big Endian
  15.250     inline UByte   ReadUByteBE()               { return (UByte)Alg::ByteUtil::BEToSystem(PRead8());    }
  15.251     inline SByte   ReadSByteBE()               { return (SByte)Alg::ByteUtil::BEToSystem(PRead8());    }
  15.252     inline UByte   ReadUInt8BE()               { return (UByte)Alg::ByteUtil::BEToSystem(PRead8());    }
  15.253     inline SByte   ReadSInt8BE()               { return (SByte)Alg::ByteUtil::BEToSystem(PRead8());    }
  15.254     inline UInt16  ReadUInt16BE()              { return (UInt16)Alg::ByteUtil::BEToSystem(PRead16());  }
  15.255     inline SInt16  ReadSInt16BE()              { return (SInt16)Alg::ByteUtil::BEToSystem(PRead16());  }
  15.256     inline UInt32  ReadUInt32BE()              { return (UInt32)Alg::ByteUtil::BEToSystem(PRead32());  }
  15.257     inline SInt32  ReadSInt32BE()              { return (SInt32)Alg::ByteUtil::BEToSystem(PRead32());  }
  15.258     inline UInt64  ReadUInt64BE()              { return (UInt64)Alg::ByteUtil::BEToSystem(PRead64());  }
  15.259     inline SInt64  ReadSInt64BE()              { return (SInt64)Alg::ByteUtil::BEToSystem(PRead64());  }
  15.260     inline float   ReadFloatBE()               { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::BEToSystem(v); }
  15.261     inline double  ReadDoubleBE()              { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::BEToSystem(v); }
  15.262 };
  15.263 
  15.264 
  15.265 // *** Delegated File
  15.266 
  15.267 class DelegatedFile : public File
  15.268 {
  15.269 protected:
  15.270     // Delegating file pointer
  15.271     Ptr<File>     pFile;
  15.272 
  15.273     // Hidden default constructor
  15.274     DelegatedFile() : pFile(0)                             { }
  15.275     DelegatedFile(const DelegatedFile &source) : File()    { OVR_UNUSED(source); }
  15.276 public:
  15.277     // Constructors
  15.278     DelegatedFile(File *pfile) : pFile(pfile)     { }
  15.279 
  15.280     // ** Location Information  
  15.281     virtual const char* GetFilePath()                               { return pFile->GetFilePath(); }    
  15.282 
  15.283     // ** File Information                                                      
  15.284     virtual bool        IsValid()                                   { return pFile && pFile->IsValid(); }   
  15.285     virtual bool        IsWritable()                                { return pFile->IsWritable(); }
  15.286 //  virtual bool        IsRecoverable()                             { return pFile->IsRecoverable(); }          
  15.287                                                                     
  15.288     virtual int         Tell()                                      { return pFile->Tell(); }
  15.289     virtual SInt64      LTell()                                     { return pFile->LTell(); }
  15.290     
  15.291     virtual int         GetLength()                                 { return pFile->GetLength(); }
  15.292     virtual SInt64      LGetLength()                                { return pFile->LGetLength(); }
  15.293     
  15.294     //virtual bool      Stat(FileStats *pfs)                        { return pFile->Stat(pfs); }
  15.295     
  15.296     virtual int         GetErrorCode()                              { return pFile->GetErrorCode(); }
  15.297     
  15.298     // ** Stream implementation & I/O
  15.299     virtual int         Write(const UByte *pbuffer, int numBytes)   { return pFile->Write(pbuffer,numBytes); }  
  15.300     virtual int         Read(UByte *pbuffer, int numBytes)          { return pFile->Read(pbuffer,numBytes); }   
  15.301     
  15.302     virtual int         SkipBytes(int numBytes)                     { return pFile->SkipBytes(numBytes); }      
  15.303     
  15.304     virtual int         BytesAvailable()                            { return pFile->BytesAvailable(); } 
  15.305     
  15.306     virtual bool        Flush()                                     { return pFile->Flush(); }
  15.307                                                                     
  15.308     // Seeking                                                      
  15.309     virtual int         Seek(int offset, int origin=Seek_Set)       { return pFile->Seek(offset,origin); }
  15.310     virtual SInt64      LSeek(SInt64 offset, int origin=Seek_Set)   { return pFile->LSeek(offset,origin); }
  15.311 
  15.312     virtual int         CopyFromStream(File *pstream, int byteSize) { return pFile->CopyFromStream(pstream,byteSize); }
  15.313                         
  15.314     // Closing the file 
  15.315     virtual bool        Close()                                     { return pFile->Close(); }    
  15.316 };
  15.317 
  15.318 
  15.319 //-----------------------------------------------------------------------------------
  15.320 // ***** Buffered File
  15.321 
  15.322 // This file class adds buffering to an existing file
  15.323 // Buffered file never fails by itself; if there's not
  15.324 // enough memory for buffer, no buffer's used
  15.325 
  15.326 class BufferedFile : public DelegatedFile
  15.327 {   
  15.328 protected:  
  15.329     enum BufferModeType
  15.330     {
  15.331         NoBuffer,
  15.332         ReadBuffer,
  15.333         WriteBuffer
  15.334     };
  15.335 
  15.336     // Buffer & the mode it's in
  15.337     UByte*          pBuffer;
  15.338     BufferModeType  BufferMode;
  15.339     // Position in buffer
  15.340     unsigned        Pos;
  15.341     // Data in buffer if reading
  15.342     unsigned        DataSize;
  15.343     // Underlying file position 
  15.344     UInt64          FilePos;
  15.345 
  15.346     // Initializes buffering to a certain mode
  15.347     bool    SetBufferMode(BufferModeType mode);
  15.348     // Flushes buffer
  15.349     // WriteBuffer - write data to disk, ReadBuffer - reset buffer & fix file position  
  15.350     void    FlushBuffer();
  15.351     // Loads data into ReadBuffer
  15.352     // WARNING: Right now LoadBuffer() assumes the buffer's empty
  15.353     void    LoadBuffer();
  15.354 
  15.355     // Hidden constructor
  15.356     BufferedFile();
  15.357     inline BufferedFile(const BufferedFile &source) : DelegatedFile() { OVR_UNUSED(source); }
  15.358 public:
  15.359 
  15.360     // Constructor
  15.361     // - takes another file as source
  15.362     BufferedFile(File *pfile);
  15.363     ~BufferedFile();
  15.364     
  15.365     
  15.366     // ** Overridden functions
  15.367 
  15.368     // We override all the functions that can possibly
  15.369     // require buffer mode switch, flush, or extra calculations
  15.370     virtual int         Tell();
  15.371     virtual SInt64      LTell();
  15.372 
  15.373     virtual int         GetLength();
  15.374     virtual SInt64      LGetLength();
  15.375 
  15.376 //  virtual bool        Stat(GFileStats *pfs);  
  15.377 
  15.378     virtual int         Write(const UByte *pbufer, int numBytes);
  15.379     virtual int         Read(UByte *pbufer, int numBytes);
  15.380 
  15.381     virtual int         SkipBytes(int numBytes);
  15.382 
  15.383     virtual int         BytesAvailable();
  15.384 
  15.385     virtual bool        Flush();
  15.386 
  15.387     virtual int         Seek(int offset, int origin=Seek_Set);
  15.388     virtual SInt64      LSeek(SInt64 offset, int origin=Seek_Set);
  15.389 
  15.390     virtual int         CopyFromStream(File *pstream, int byteSize);
  15.391     
  15.392     virtual bool        Close();    
  15.393 };                          
  15.394 
  15.395 
  15.396 //-----------------------------------------------------------------------------------
  15.397 // ***** Memory File
  15.398 
  15.399 class MemoryFile : public File
  15.400 {
  15.401 public:
  15.402 
  15.403     const char* GetFilePath()       { return FilePath.ToCStr(); }
  15.404 
  15.405     bool        IsValid()           { return Valid; }
  15.406     bool        IsWritable()        { return false; }
  15.407 
  15.408     bool        Flush()             { return true; }
  15.409     int         GetErrorCode()      { return 0; }
  15.410 
  15.411     int         Tell()              { return FileIndex; }
  15.412     SInt64      LTell()             { return (SInt64) FileIndex; }
  15.413 
  15.414     int         GetLength()         { return FileSize; }
  15.415     SInt64      LGetLength()        { return (SInt64) FileSize; }
  15.416 
  15.417     bool        Close()
  15.418     {
  15.419         Valid = false;
  15.420         return false;
  15.421     }
  15.422 
  15.423     int         CopyFromStream(File *pstream, int byteSize)
  15.424     {   OVR_UNUSED2(pstream, byteSize);
  15.425         return 0;
  15.426     }
  15.427 
  15.428     int         Write(const UByte *pbuffer, int numBytes)
  15.429     {   OVR_UNUSED2(pbuffer, numBytes);
  15.430         return 0;
  15.431     }
  15.432 
  15.433     int         Read(UByte *pbufer, int numBytes)
  15.434     {
  15.435         if (FileIndex + numBytes > FileSize)
  15.436         {
  15.437             numBytes = FileSize - FileIndex;
  15.438         }
  15.439 
  15.440         if (numBytes > 0)
  15.441         {
  15.442             ::memcpy (pbufer, &FileData [FileIndex], numBytes);
  15.443 
  15.444             FileIndex += numBytes;
  15.445         }
  15.446 
  15.447         return numBytes;
  15.448     }
  15.449 
  15.450     int         SkipBytes(int numBytes)
  15.451     {
  15.452         if (FileIndex + numBytes > FileSize)
  15.453         {
  15.454             numBytes = FileSize - FileIndex;
  15.455         }
  15.456 
  15.457         FileIndex += numBytes;
  15.458 
  15.459         return numBytes;
  15.460     }
  15.461 
  15.462     int         BytesAvailable()
  15.463     {
  15.464         return (FileSize - FileIndex);
  15.465     }
  15.466 
  15.467     int         Seek(int offset, int origin = Seek_Set)
  15.468     {
  15.469         switch (origin)
  15.470         {
  15.471         case Seek_Set : FileIndex  = offset;               break;
  15.472         case Seek_Cur : FileIndex += offset;               break;
  15.473         case Seek_End : FileIndex  = FileSize - offset;  break;
  15.474         }
  15.475 
  15.476         return FileIndex;
  15.477     }
  15.478 
  15.479     SInt64      LSeek(SInt64 offset, int origin = Seek_Set)
  15.480     {
  15.481         return (SInt64) Seek((int) offset, origin);
  15.482     }
  15.483 
  15.484 public:
  15.485 
  15.486     MemoryFile (const String& fileName, const UByte *pBuffer, int buffSize)
  15.487         : FilePath(fileName)
  15.488     {
  15.489         FileData  = pBuffer;
  15.490         FileSize  = buffSize;
  15.491         FileIndex = 0;
  15.492         Valid     = (!fileName.IsEmpty() && pBuffer && buffSize > 0) ? true : false;
  15.493     }
  15.494 
  15.495     // pfileName should be encoded as UTF-8 to support international file names.
  15.496     MemoryFile (const char* pfileName, const UByte *pBuffer, int buffSize)
  15.497         : FilePath(pfileName)
  15.498     {
  15.499         FileData  = pBuffer;
  15.500         FileSize  = buffSize;
  15.501         FileIndex = 0;
  15.502         Valid     = (pfileName && pBuffer && buffSize > 0) ? true : false;
  15.503     }
  15.504 private:
  15.505 
  15.506     String       FilePath;
  15.507     const UByte *FileData;
  15.508     int          FileSize;
  15.509     int          FileIndex;
  15.510     bool         Valid;
  15.511 };
  15.512 
  15.513 
  15.514 // ***** Global path helpers
  15.515 
  15.516 // Find trailing short filename in a path.
  15.517 const char* OVR_CDECL GetShortFilename(const char* purl);
  15.518 
  15.519 } // OVR
  15.520 
  15.521 #endif
  15.522 \ No newline at end of file
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/libovr/Src/Kernel/OVR_FileFILE.cpp	Sat Sep 14 16:14:59 2013 +0300
    16.3 @@ -0,0 +1,1 @@
    16.4 +/**************************************************************************
    16.5 
    16.6 Filename    :   OVR_FileFILE.cpp
    16.7 Content     :   File wrapper class implementation (Win32)
    16.8 
    16.9 Created     :   April 5, 1999
   16.10 Authors     :   Michael Antonov
   16.11 
   16.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   16.13 
   16.14 Use of this software is subject to the terms of the Oculus license
   16.15 agreement provided at the time of installation or download, or which
   16.16 otherwise accompanies this software in either electronic or hard copy form.
   16.17 
   16.18 **************************************************************************/
   16.19 
   16.20 #define  GFILE_CXX
   16.21 
   16.22 #include "OVR_Types.h"
   16.23 #include "OVR_Log.h"
   16.24 
   16.25 // Standard C library (Captain Obvious guarantees!)
   16.26 #include <stdio.h>
   16.27 #ifndef OVR_OS_WINCE
   16.28 #include <sys/stat.h>
   16.29 #endif
   16.30 
   16.31 #include "OVR_SysFile.h"
   16.32 
   16.33 #ifndef OVR_OS_WINCE
   16.34 #include <errno.h>
   16.35 #endif
   16.36 
   16.37 namespace OVR {
   16.38 
   16.39 // ***** File interface
   16.40 
   16.41 // ***** FILEFile - C streams file
   16.42 
   16.43 static int SFerror ()
   16.44 {
   16.45     if (errno == ENOENT)
   16.46         return FileConstants::Error_FileNotFound;
   16.47     else if (errno == EACCES || errno == EPERM)
   16.48         return FileConstants::Error_Access;
   16.49     else if (errno == ENOSPC)
   16.50         return FileConstants::Error_DiskFull;
   16.51     else
   16.52         return FileConstants::Error_IOError;
   16.53 };
   16.54 
   16.55 #ifdef OVR_OS_WIN32
   16.56 #include "windows.h"
   16.57 // A simple helper class to disable/enable system error mode, if necessary
   16.58 // Disabling happens conditionally only if a drive name is involved
   16.59 class SysErrorModeDisabler
   16.60 {
   16.61     BOOL    Disabled;
   16.62     UINT    OldMode;
   16.63 public:
   16.64     SysErrorModeDisabler(const char* pfileName)
   16.65     {
   16.66         if (pfileName && (pfileName[0]!=0) && pfileName[1]==':')
   16.67         {
   16.68             Disabled = 1;
   16.69             OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
   16.70         }
   16.71         else
   16.72             Disabled = 0;
   16.73     }
   16.74 
   16.75     ~SysErrorModeDisabler()
   16.76     {
   16.77         if (Disabled) ::SetErrorMode(OldMode);
   16.78     }
   16.79 };
   16.80 #else
   16.81 class SysErrorModeDisabler
   16.82 {
   16.83 public:
   16.84     SysErrorModeDisabler(const char* pfileName) { }
   16.85 };
   16.86 #endif // OVR_OS_WIN32
   16.87 
   16.88 
   16.89 // This macro enables verification of I/O results after seeks against a pre-loaded
   16.90 // full file buffer copy. This is generally not necessary, but can been used to debug
   16.91 // memory corruptions; we've seen this fail due to EAX2/DirectSound corrupting memory
   16.92 // under FMOD with XP64 (32-bit) and Realtek HA Audio driver.
   16.93 //#define GFILE_VERIFY_SEEK_ERRORS
   16.94 
   16.95 
   16.96 // This is the simplest possible file implementation, it wraps around the descriptor
   16.97 // This file is delegated to by SysFile.
   16.98 
   16.99 class FILEFile : public File
  16.100 {
  16.101 protected:
  16.102 
  16.103     // Allocated filename
  16.104     String      FileName;
  16.105 
  16.106     // File handle & open mode
  16.107     bool        Opened;
  16.108     FILE*       fs;
  16.109     int         OpenFlags;
  16.110     // Error code for last request
  16.111     int         ErrorCode;
  16.112 
  16.113     int         LastOp;
  16.114 
  16.115 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  16.116     UByte*      pFileTestBuffer;
  16.117     unsigned    FileTestLength;
  16.118     unsigned    TestPos; // File pointer position during tests.
  16.119 #endif
  16.120 
  16.121 public:
  16.122 
  16.123     FILEFile()
  16.124     {
  16.125         Opened = 0; FileName = "";
  16.126 
  16.127 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  16.128         pFileTestBuffer =0;
  16.129         FileTestLength  =0;
  16.130         TestPos         =0;
  16.131 #endif
  16.132     }
  16.133     // Initialize file by opening it
  16.134     FILEFile(const String& fileName, int flags, int Mode);
  16.135     // The 'pfileName' should be encoded as UTF-8 to support international file names.
  16.136     FILEFile(const char* pfileName, int flags, int Mode);
  16.137 
  16.138     ~FILEFile()
  16.139     {
  16.140         if (Opened)
  16.141             Close();
  16.142     }
  16.143 
  16.144     virtual const char* GetFilePath();
  16.145 
  16.146     // ** File Information
  16.147     virtual bool        IsValid();
  16.148     virtual bool        IsWritable();
  16.149 
  16.150     // Return position / file size
  16.151     virtual int         Tell();
  16.152     virtual SInt64      LTell();
  16.153     virtual int         GetLength();
  16.154     virtual SInt64      LGetLength();
  16.155 
  16.156 //  virtual bool        Stat(FileStats *pfs);
  16.157     virtual int         GetErrorCode();
  16.158 
  16.159     // ** Stream implementation & I/O
  16.160     virtual int         Write(const UByte *pbuffer, int numBytes);
  16.161     virtual int         Read(UByte *pbuffer, int numBytes);
  16.162     virtual int         SkipBytes(int numBytes);
  16.163     virtual int         BytesAvailable();
  16.164     virtual bool        Flush();
  16.165     virtual int         Seek(int offset, int origin);
  16.166     virtual SInt64      LSeek(SInt64 offset, int origin);
  16.167     
  16.168     virtual int         CopyFromStream(File *pStream, int byteSize);
  16.169     virtual bool        Close();    
  16.170 private:
  16.171     void                init();
  16.172 };
  16.173 
  16.174 
  16.175 // Initialize file by opening it
  16.176 FILEFile::FILEFile(const String& fileName, int flags, int mode)
  16.177   : FileName(fileName), OpenFlags(flags)
  16.178 {
  16.179     OVR_UNUSED(mode);
  16.180     init();
  16.181 }
  16.182 
  16.183 // The 'pfileName' should be encoded as UTF-8 to support international file names.
  16.184 FILEFile::FILEFile(const char* pfileName, int flags, int mode)
  16.185   : FileName(pfileName), OpenFlags(flags)
  16.186 {
  16.187     OVR_UNUSED(mode);
  16.188     init();
  16.189 }
  16.190 
  16.191 void FILEFile::init()
  16.192 {
  16.193     // Open mode for file's open
  16.194     const char *omode = "rb";
  16.195 
  16.196     if (OpenFlags & Open_Truncate)
  16.197     {
  16.198         if (OpenFlags & Open_Read)
  16.199             omode = "w+b";
  16.200         else
  16.201             omode = "wb";
  16.202     }
  16.203     else if (OpenFlags & Open_Create)
  16.204     {
  16.205         if (OpenFlags & Open_Read)
  16.206             omode = "a+b";
  16.207         else
  16.208             omode = "ab";
  16.209     }
  16.210     else if (OpenFlags & Open_Write)
  16.211         omode = "r+b";
  16.212 
  16.213 #ifdef OVR_OS_WIN32
  16.214     SysErrorModeDisabler disabler(FileName.ToCStr());
  16.215 #endif
  16.216 
  16.217 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
  16.218     wchar_t womode[16];
  16.219     wchar_t *pwFileName = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(FileName.ToCStr())+1) * sizeof(wchar_t));
  16.220     UTF8Util::DecodeString(pwFileName, FileName.ToCStr());
  16.221     OVR_ASSERT(strlen(omode) < sizeof(womode)/sizeof(womode[0]));
  16.222     UTF8Util::DecodeString(womode, omode);
  16.223     _wfopen_s(&fs, pwFileName, womode);
  16.224     OVR_FREE(pwFileName);
  16.225 #else
  16.226     fs = fopen(FileName.ToCStr(), omode);
  16.227 #endif
  16.228     if (fs)
  16.229         rewind (fs);
  16.230     Opened = (fs != NULL);
  16.231     // Set error code
  16.232     if (!Opened)
  16.233         ErrorCode = SFerror();
  16.234     else
  16.235     {
  16.236         // If we are testing file seek correctness, pre-load the entire file so
  16.237         // that we can do comparison tests later.
  16.238 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS        
  16.239         TestPos         = 0;
  16.240         fseek(fs, 0, SEEK_END);
  16.241         FileTestLength  = ftell(fs);
  16.242         fseek(fs, 0, SEEK_SET);
  16.243         pFileTestBuffer = (UByte*)OVR_ALLOC(FileTestLength);
  16.244         if (pFileTestBuffer)
  16.245         {
  16.246             OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength));
  16.247             Seek(0, Seek_Set);
  16.248         }        
  16.249 #endif
  16.250 
  16.251         ErrorCode = 0;
  16.252     }
  16.253     LastOp = 0;
  16.254 }
  16.255 
  16.256 
  16.257 const char* FILEFile::GetFilePath()
  16.258 {
  16.259     return FileName.ToCStr();
  16.260 }
  16.261 
  16.262 
  16.263 // ** File Information
  16.264 bool    FILEFile::IsValid()
  16.265 {
  16.266     return Opened;
  16.267 }
  16.268 bool    FILEFile::IsWritable()
  16.269 {
  16.270     return IsValid() && (OpenFlags&Open_Write);
  16.271 }
  16.272 /*
  16.273 bool    FILEFile::IsRecoverable()
  16.274 {
  16.275     return IsValid() && ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC);
  16.276 }
  16.277 */
  16.278 
  16.279 // Return position / file size
  16.280 int     FILEFile::Tell()
  16.281 {
  16.282     int pos = (int)ftell (fs);
  16.283     if (pos < 0)
  16.284         ErrorCode = SFerror();
  16.285     return pos;
  16.286 }
  16.287 
  16.288 SInt64  FILEFile::LTell()
  16.289 {
  16.290     SInt64 pos = ftell(fs);
  16.291     if (pos < 0)
  16.292         ErrorCode = SFerror();
  16.293     return pos;
  16.294 }
  16.295 
  16.296 int     FILEFile::GetLength()
  16.297 {
  16.298     int pos = Tell();
  16.299     if (pos >= 0)
  16.300     {
  16.301         Seek (0, Seek_End);
  16.302         int size = Tell();
  16.303         Seek (pos, Seek_Set);
  16.304         return size;
  16.305     }
  16.306     return -1;
  16.307 }
  16.308 SInt64  FILEFile::LGetLength()
  16.309 {
  16.310     SInt64 pos = LTell();
  16.311     if (pos >= 0)
  16.312     {
  16.313         LSeek (0, Seek_End);
  16.314         SInt64 size = LTell();
  16.315         LSeek (pos, Seek_Set);
  16.316         return size;
  16.317     }
  16.318     return -1;
  16.319 }
  16.320 
  16.321 int     FILEFile::GetErrorCode()
  16.322 {
  16.323     return ErrorCode;
  16.324 }
  16.325 
  16.326 // ** Stream implementation & I/O
  16.327 int     FILEFile::Write(const UByte *pbuffer, int numBytes)
  16.328 {
  16.329     if (LastOp && LastOp != Open_Write)
  16.330         fflush(fs);
  16.331     LastOp = Open_Write;
  16.332     int written = (int) fwrite(pbuffer, 1, numBytes, fs);
  16.333     if (written < numBytes)
  16.334         ErrorCode = SFerror();
  16.335 
  16.336 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  16.337     if (written > 0)
  16.338         TestPos += written;
  16.339 #endif
  16.340 
  16.341     return written;
  16.342 }
  16.343 
  16.344 int     FILEFile::Read(UByte *pbuffer, int numBytes)
  16.345 {
  16.346     if (LastOp && LastOp != Open_Read)
  16.347         fflush(fs);
  16.348     LastOp = Open_Read;
  16.349     int read = (int) fread(pbuffer, 1, numBytes, fs);
  16.350     if (read < numBytes)
  16.351         ErrorCode = SFerror();
  16.352 
  16.353 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  16.354     if (read > 0)
  16.355     {
  16.356         // Read-in data must match our pre-loaded buffer data!
  16.357         UByte* pcompareBuffer = pFileTestBuffer + TestPos;
  16.358         for (int i=0; i< read; i++)
  16.359         {
  16.360             OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]);
  16.361         }
  16.362 
  16.363         //OVR_ASSERT(!memcmp(pFileTestBuffer + TestPos, pbuffer, read));
  16.364         TestPos += read;
  16.365         OVR_ASSERT(ftell(fs) == (int)TestPos);
  16.366     }
  16.367 #endif
  16.368 
  16.369     return read;
  16.370 }
  16.371 
  16.372 // Seeks ahead to skip bytes
  16.373 int     FILEFile::SkipBytes(int numBytes)
  16.374 {
  16.375     SInt64 pos    = LTell();
  16.376     SInt64 newPos = LSeek(numBytes, Seek_Cur);
  16.377 
  16.378     // Return -1 for major error
  16.379     if ((pos==-1) || (newPos==-1))
  16.380     {
  16.381         return -1;
  16.382     }
  16.383     //ErrorCode = ((NewPos-Pos)<numBytes) ? errno : 0;
  16.384 
  16.385     return int (newPos-(int)pos);
  16.386 }
  16.387 
  16.388 // Return # of bytes till EOF
  16.389 int     FILEFile::BytesAvailable()
  16.390 {
  16.391     SInt64 pos    = LTell();
  16.392     SInt64 endPos = LGetLength();
  16.393 
  16.394     // Return -1 for major error
  16.395     if ((pos==-1) || (endPos==-1))
  16.396     {
  16.397         ErrorCode = SFerror();
  16.398         return 0;
  16.399     }
  16.400     else
  16.401         ErrorCode = 0;
  16.402 
  16.403     return int (endPos-(int)pos);
  16.404 }
  16.405 
  16.406 // Flush file contents
  16.407 bool    FILEFile::Flush()
  16.408 {
  16.409     return !fflush(fs);
  16.410 }
  16.411 
  16.412 int     FILEFile::Seek(int offset, int origin)
  16.413 {
  16.414     int newOrigin = 0;
  16.415     switch(origin)
  16.416     {
  16.417     case Seek_Set: newOrigin = SEEK_SET; break;
  16.418     case Seek_Cur: newOrigin = SEEK_CUR; break;
  16.419     case Seek_End: newOrigin = SEEK_END; break;
  16.420     }
  16.421 
  16.422     if (newOrigin == SEEK_SET && offset == Tell())
  16.423         return Tell();
  16.424 
  16.425     if (fseek (fs, offset, newOrigin))
  16.426     {
  16.427 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  16.428         OVR_ASSERT(0);
  16.429 #endif
  16.430         return -1;
  16.431     }
  16.432     
  16.433 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  16.434     // Track file position after seeks for read verification later.
  16.435     switch(origin)
  16.436     {
  16.437     case Seek_Set:  TestPos = offset;       break;
  16.438     case Seek_Cur:  TestPos += offset;      break;    
  16.439     case Seek_End:  TestPos = FileTestLength + offset; break;
  16.440     }
  16.441     OVR_ASSERT((int)TestPos == Tell());
  16.442 #endif
  16.443 
  16.444     return (int)Tell();
  16.445 }
  16.446 
  16.447 SInt64  FILEFile::LSeek(SInt64 offset, int origin)
  16.448 {
  16.449     return Seek((int)offset,origin);
  16.450 }
  16.451 
  16.452 int FILEFile::CopyFromStream(File *pstream, int byteSize)
  16.453 {
  16.454     UByte   buff[0x4000];
  16.455     int     count = 0;
  16.456     int     szRequest, szRead, szWritten;
  16.457 
  16.458     while (byteSize)
  16.459     {
  16.460         szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
  16.461 
  16.462         szRead    = pstream->Read(buff, szRequest);
  16.463         szWritten = 0;
  16.464         if (szRead > 0)
  16.465             szWritten = Write(buff, szRead);
  16.466 
  16.467         count    += szWritten;
  16.468         byteSize -= szWritten;
  16.469         if (szWritten < szRequest)
  16.470             break;
  16.471     }
  16.472     return count;
  16.473 }
  16.474 
  16.475 
  16.476 bool FILEFile::Close()
  16.477 {
  16.478 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  16.479     if (pFileTestBuffer)
  16.480     {
  16.481         OVR_FREE(pFileTestBuffer);
  16.482         pFileTestBuffer = 0;
  16.483         FileTestLength  = 0;
  16.484     }
  16.485 #endif
  16.486 
  16.487     bool closeRet = !fclose(fs);
  16.488 
  16.489     if (!closeRet)
  16.490     {
  16.491         ErrorCode = SFerror();
  16.492         return 0;
  16.493     }
  16.494     else
  16.495     {
  16.496         Opened    = 0;
  16.497         fs        = 0;
  16.498         ErrorCode = 0;
  16.499     }
  16.500 
  16.501     // Handle safe truncate
  16.502     /*
  16.503     if ((OpenFlags & OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
  16.504     {
  16.505         // Delete original file (if it existed)
  16.506         DWORD oldAttributes = FileUtilWin32::GetFileAttributes(FileName);
  16.507         if (oldAttributes!=0xFFFFFFFF)
  16.508             if (!FileUtilWin32::DeleteFile(FileName))
  16.509             {
  16.510                 // Try to remove the readonly attribute
  16.511                 FileUtilWin32::SetFileAttributes(FileName, oldAttributes & (~FILE_ATTRIBUTE_READONLY) );
  16.512                 // And delete the file again
  16.513                 if (!FileUtilWin32::DeleteFile(FileName))
  16.514                     return 0;
  16.515             }
  16.516 
  16.517         // Rename temp file to real filename
  16.518         if (!FileUtilWin32::MoveFile(TempName, FileName))
  16.519         {
  16.520             //ErrorCode = errno;
  16.521             return 0;
  16.522         }
  16.523     }
  16.524     */
  16.525     return 1;
  16.526 }
  16.527 
  16.528 /*
  16.529 bool    FILEFile::CloseCancel()
  16.530 {
  16.531     bool closeRet = (bool)::CloseHandle(fd);
  16.532 
  16.533     if (!closeRet)
  16.534     {
  16.535         //ErrorCode = errno;
  16.536         return 0;
  16.537     }
  16.538     else
  16.539     {
  16.540         Opened    = 0;
  16.541         fd        = INVALID_HANDLE_VALUE;
  16.542         ErrorCode = 0;
  16.543     }
  16.544 
  16.545     // Handle safe truncate (delete tmp file, leave original unchanged)
  16.546     if ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
  16.547         if (!FileUtilWin32::DeleteFile(TempName))
  16.548         {
  16.549             //ErrorCode = errno;
  16.550             return 0;
  16.551         }
  16.552     return 1;
  16.553 }
  16.554 */
  16.555 
  16.556 File *FileFILEOpen(const String& path, int flags, int mode)
  16.557 {
  16.558     return new FILEFile(path, flags, mode);
  16.559 }
  16.560 
  16.561 // Helper function: obtain file information time.
  16.562 bool    SysFile::GetFileStat(FileStat* pfileStat, const String& path)
  16.563 {
  16.564 #if defined(OVR_OS_WIN32)
  16.565     // 64-bit implementation on Windows.
  16.566     struct __stat64 fileStat;
  16.567     // Stat returns 0 for success.
  16.568     wchar_t *pwpath = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(path.ToCStr())+1)*sizeof(wchar_t));
  16.569     UTF8Util::DecodeString(pwpath, path.ToCStr());
  16.570 
  16.571     int ret = _wstat64(pwpath, &fileStat);
  16.572     OVR_FREE(pwpath);
  16.573     if (ret) return false;
  16.574 #else
  16.575     struct stat fileStat;
  16.576     // Stat returns 0 for success.
  16.577     if (stat(path, &fileStat) != 0)
  16.578         return false;
  16.579 #endif
  16.580     pfileStat->AccessTime = fileStat.st_atime;
  16.581     pfileStat->ModifyTime = fileStat.st_mtime;
  16.582     pfileStat->FileSize   = fileStat.st_size;
  16.583     return true;
  16.584 }
  16.585 
  16.586 } // Scaleform
  16.587 \ No newline at end of file
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/libovr/Src/Kernel/OVR_Hash.h	Sat Sep 14 16:14:59 2013 +0300
    17.3 @@ -0,0 +1,1 @@
    17.4 +/************************************************************************************
    17.5 
    17.6 PublicHeader:   None
    17.7 Filename    :   OVR_Hash.h
    17.8 Content     :   Template hash-table/set implementation
    17.9 Created     :   September 19, 2012
   17.10 Notes       : 
   17.11 
   17.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   17.13 
   17.14 Use of this software is subject to the terms of the Oculus license
   17.15 agreement provided at the time of installation or download, or which
   17.16 otherwise accompanies this software in either electronic or hard copy form.
   17.17 
   17.18 ************************************************************************************/
   17.19 
   17.20 #ifndef OVR_Hash_h
   17.21 #define OVR_Hash_h
   17.22 
   17.23 #include "OVR_ContainerAllocator.h"
   17.24 #include "OVR_Alg.h"
   17.25 
   17.26 // 'new' operator is redefined/used in this file.
   17.27 #undef new
   17.28 
   17.29 namespace OVR {
   17.30 
   17.31 //-----------------------------------------------------------------------------------
   17.32 // ***** Hash Table Implementation
   17.33 
   17.34 // HastSet and Hash.
   17.35 //
   17.36 // Hash table, linear probing, internal chaining.  One  interesting/nice thing
   17.37 // about this implementation is that the table itself is a flat chunk of memory
   17.38 // containing no pointers, only relative indices. If the key and value types
   17.39 // of the Hash contain no pointers, then the Hash can be serialized using raw IO.
   17.40 //
   17.41 // Never shrinks, unless you explicitly Clear() it.  Expands on
   17.42 // demand, though.  For best results, if you know roughly how big your
   17.43 // table will be, default it to that size when you create it.
   17.44 //
   17.45 // Key usability feature:
   17.46 //
   17.47 //   1. Allows node hash values to either be cached or not.
   17.48 //
   17.49 //   2. Allows for alternative keys with methods such as GetAlt(). Handy
   17.50 //      if you need to search nodes by their components; no need to create
   17.51 //      temporary nodes.
   17.52 //
   17.53 
   17.54 
   17.55 // *** Hash functors:
   17.56 //
   17.57 //  IdentityHash  - use when the key is already a good hash
   17.58 //  HFixedSizeHash - general hash based on object's in-memory representation.
   17.59 
   17.60 
   17.61 // Hash is just the input value; can use this for integer-indexed hash tables.
   17.62 template<class C>
   17.63 class IdentityHash
   17.64 {
   17.65 public:
   17.66     UPInt operator()(const C& data) const
   17.67     { return (UPInt) data; }
   17.68 };
   17.69 
   17.70 // Computes a hash of an object's representation.
   17.71 template<class C>
   17.72 class FixedSizeHash
   17.73 {
   17.74 public:
   17.75     // Alternative: "sdbm" hash function, suggested at same web page
   17.76     // above, http::/www.cs.yorku.ca/~oz/hash.html
   17.77     // This is somewhat slower then Bernstein, but it works way better than the above
   17.78     // hash function for hashing large numbers of 32-bit ints.
   17.79     static OVR_FORCE_INLINE UPInt SDBM_Hash(const void* data_in, UPInt size, UPInt seed = 5381)     
   17.80     {
   17.81         const UByte* data = (const UByte*) data_in;
   17.82         UPInt        h = seed;
   17.83         while (size > 0)
   17.84         {
   17.85             size--;
   17.86             h = (h << 16) + (h << 6) - h + (UPInt)data[size];
   17.87         }   
   17.88         return h;
   17.89     }
   17.90 
   17.91     UPInt operator()(const C& data) const
   17.92     {
   17.93         unsigned char*  p = (unsigned char*) &data;
   17.94         int size = sizeof(C);
   17.95 
   17.96         return SDBM_Hash(p, size);
   17.97     }
   17.98 };
   17.99 
  17.100 
  17.101 
  17.102 // *** HashsetEntry Entry types. 
  17.103 
  17.104 // Compact hash table Entry type that re-computes hash keys during hash traversal.
  17.105 // Good to use if the hash function is cheap or the hash value is already cached in C.
  17.106 template<class C, class HashF>
  17.107 class HashsetEntry
  17.108 {
  17.109 public:
  17.110     // Internal chaining for collisions.
  17.111     SPInt       NextInChain;
  17.112     C           Value;
  17.113 
  17.114     HashsetEntry()
  17.115         : NextInChain(-2) { }
  17.116     HashsetEntry(const HashsetEntry& e)
  17.117         : NextInChain(e.NextInChain), Value(e.Value) { }
  17.118     HashsetEntry(const C& key, SPInt next)
  17.119         : NextInChain(next), Value(key) { }
  17.120 
  17.121     bool    IsEmpty() const          { return NextInChain == -2;  }
  17.122     bool    IsEndOfChain() const     { return NextInChain == -1;  }
  17.123 
  17.124     // Cached hash value access - can be optimized bu storing hash locally.
  17.125     // Mask value only needs to be used if SetCachedHash is not implemented.
  17.126     UPInt   GetCachedHash(UPInt maskValue) const  { return HashF()(Value) & maskValue; }
  17.127     void    SetCachedHash(UPInt)                  {}
  17.128 
  17.129     void    Clear()
  17.130     {        
  17.131         Value.~C(); // placement delete
  17.132         NextInChain = -2;
  17.133     }
  17.134     // Free is only used from dtor of hash; Clear is used during regular operations:
  17.135     // assignment, hash reallocations, value reassignments, so on.
  17.136     void    Free() { Clear(); }
  17.137 };
  17.138 
  17.139 // Hash table Entry type that caches the Entry hash value for nodes, so that it
  17.140 // does not need to be re-computed during access.
  17.141 template<class C, class HashF>
  17.142 class HashsetCachedEntry
  17.143 {
  17.144 public:
  17.145     // Internal chaining for collisions.
  17.146     SPInt       NextInChain;
  17.147     UPInt       HashValue;
  17.148     C           Value;
  17.149 
  17.150     HashsetCachedEntry()
  17.151         : NextInChain(-2) { }
  17.152     HashsetCachedEntry(const HashsetCachedEntry& e)
  17.153         : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { }
  17.154     HashsetCachedEntry(const C& key, SPInt next)
  17.155         : NextInChain(next), Value(key) { }
  17.156 
  17.157     bool    IsEmpty() const          { return NextInChain == -2;  }
  17.158     bool    IsEndOfChain() const     { return NextInChain == -1;  }
  17.159 
  17.160     // Cached hash value access - can be optimized bu storing hash locally.
  17.161     // Mask value only needs to be used if SetCachedHash is not implemented.
  17.162     UPInt   GetCachedHash(UPInt maskValue) const  { OVR_UNUSED(maskValue); return HashValue; }
  17.163     void    SetCachedHash(UPInt hashValue)        { HashValue = hashValue; }
  17.164 
  17.165     void    Clear()
  17.166     {
  17.167         Value.~C();
  17.168         NextInChain = -2;
  17.169     }
  17.170     // Free is only used from dtor of hash; Clear is used during regular operations:
  17.171     // assignment, hash reallocations, value reassignments, so on.
  17.172     void    Free() { Clear(); }
  17.173 };
  17.174 
  17.175 
  17.176 //-----------------------------------------------------------------------------------
  17.177 // *** HashSet implementation - relies on either cached or regular entries.
  17.178 //
  17.179 // Use: Entry = HashsetCachedEntry<C, HashF> if hashes are expensive to
  17.180 //              compute and thus need caching in entries.
  17.181 //      Entry = HashsetEntry<C, HashF> if hashes are already externally cached.
  17.182 //
  17.183 template<class C, class HashF = FixedSizeHash<C>,
  17.184          class AltHashF = HashF, 
  17.185          class Allocator = ContainerAllocator<C>,
  17.186          class Entry = HashsetCachedEntry<C, HashF> >
  17.187 class HashSetBase
  17.188 {
  17.189     enum { HashMinSize = 8 };
  17.190 
  17.191 public:
  17.192     OVR_MEMORY_REDEFINE_NEW(HashSetBase)
  17.193 
  17.194     typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry>    SelfType;
  17.195 
  17.196     HashSetBase() : pTable(NULL)                       {   }
  17.197     HashSetBase(int sizeHint) : pTable(NULL)           { SetCapacity(this, sizeHint);  }
  17.198     HashSetBase(const SelfType& src) : pTable(NULL)    { Assign(this, src); }
  17.199 
  17.200     ~HashSetBase()                                     
  17.201     { 
  17.202         if (pTable)
  17.203         {
  17.204             // Delete the entries.
  17.205             for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++)
  17.206             {
  17.207                 Entry*  e = &E(i);
  17.208                 if (!e->IsEmpty())             
  17.209                     e->Free();
  17.210             }            
  17.211 
  17.212             Allocator::Free(pTable);
  17.213             pTable = NULL;
  17.214         }
  17.215     }
  17.216 
  17.217 
  17.218     void Assign(const SelfType& src)
  17.219     {
  17.220         Clear();
  17.221         if (src.IsEmpty() == false)
  17.222         {
  17.223             SetCapacity(src.GetSize());
  17.224 
  17.225             for (ConstIterator it = src.Begin(); it != src.End(); ++it)
  17.226             {
  17.227                 Add(*it);
  17.228             }
  17.229         }
  17.230     }
  17.231 
  17.232 
  17.233     // Remove all entries from the HashSet table.
  17.234     void Clear() 
  17.235     {
  17.236         if (pTable)
  17.237         {
  17.238             // Delete the entries.
  17.239             for (UPInt i = 0, n = pTable->SizeMask; i <= n; i++)
  17.240             {
  17.241                 Entry*  e = &E(i);
  17.242                 if (!e->IsEmpty())             
  17.243                     e->Clear();
  17.244             }            
  17.245                 
  17.246             Allocator::Free(pTable);
  17.247             pTable = NULL;
  17.248         }
  17.249     }
  17.250 
  17.251     // Returns true if the HashSet is empty.
  17.252     bool IsEmpty() const
  17.253     {
  17.254         return pTable == NULL || pTable->EntryCount == 0;
  17.255     }
  17.256 
  17.257 
  17.258     // Set a new or existing value under the key, to the value.
  17.259     // Pass a different class of 'key' so that assignment reference object
  17.260     // can be passed instead of the actual object.
  17.261     template<class CRef>
  17.262     void Set(const CRef& key)
  17.263     {
  17.264         UPInt  hashValue = HashF()(key);
  17.265         SPInt  index     = (SPInt)-1;
  17.266 
  17.267         if (pTable != NULL)
  17.268             index = findIndexCore(key, hashValue & pTable->SizeMask);
  17.269 
  17.270         if (index >= 0)
  17.271         {            
  17.272             E(index).Value = key;
  17.273         }
  17.274         else
  17.275         {
  17.276             // Entry under key doesn't exist.
  17.277             add(key, hashValue);
  17.278         }
  17.279     }
  17.280 
  17.281     template<class CRef>
  17.282     inline void Add(const CRef& key)
  17.283     {
  17.284         UPInt hashValue = HashF()(key);
  17.285         add(key, hashValue);
  17.286     }
  17.287 
  17.288     // Remove by alternative key.
  17.289     template<class K>
  17.290     void RemoveAlt(const K& key)
  17.291     {   
  17.292         if (pTable == NULL)
  17.293             return;
  17.294 
  17.295         UPInt   hashValue = AltHashF()(key);
  17.296         SPInt   index     = hashValue & pTable->SizeMask;
  17.297 
  17.298         Entry*  e = &E(index);
  17.299 
  17.300         // If empty node or occupied by collider, we have nothing to remove.
  17.301         if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != (UPInt)index))
  17.302             return;        
  17.303 
  17.304         // Save index
  17.305         SPInt   naturalIndex = index;
  17.306         SPInt   prevIndex    = -1;
  17.307 
  17.308         while ((e->GetCachedHash(pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key))
  17.309         {
  17.310             // Keep looking through the chain.
  17.311             prevIndex   = index;
  17.312             index       = e->NextInChain;
  17.313             if (index == -1)
  17.314                 return; // End of chain, item not found
  17.315             e = &E(index);
  17.316         }
  17.317 
  17.318         // Found it - our item is at index
  17.319         if (naturalIndex == index)
  17.320         {
  17.321             // If we have a follower, move it to us
  17.322             if (!e->IsEndOfChain())
  17.323             {               
  17.324                 Entry*  enext = &E(e->NextInChain);
  17.325                 e->Clear();
  17.326                 new (e) Entry(*enext);
  17.327                 // Point us to the follower's cell that will be cleared
  17.328                 e = enext;
  17.329             }
  17.330         }
  17.331         else
  17.332         {
  17.333             // We are not at natural index, so deal with the prev items next index
  17.334             E(prevIndex).NextInChain = e->NextInChain;
  17.335         }
  17.336 
  17.337         // Clear us, of the follower cell that was moved.
  17.338         e->Clear();
  17.339         pTable->EntryCount --;
  17.340         // Should we check the size to condense hash? ...
  17.341     }
  17.342 
  17.343     // Remove by main key.
  17.344     template<class CRef>
  17.345     void Remove(const CRef& key)
  17.346     {
  17.347         RemoveAlt(key);
  17.348     }
  17.349 
  17.350     // Retrieve the pointer to a value under the given key.
  17.351     //  - If there's no value under the key, then return NULL.    
  17.352     //  - If there is a value, return the pointer.    
  17.353     template<class K>
  17.354     C* Get(const K& key)
  17.355     {
  17.356         SPInt   index = findIndex(key);
  17.357         if (index >= 0)        
  17.358             return &E(index).Value;        
  17.359         return 0;
  17.360     }   
  17.361 
  17.362     template<class K>
  17.363     const C* Get(const K& key) const
  17.364     {
  17.365         SPInt   index = findIndex(key);
  17.366         if (index >= 0)        
  17.367             return &E(index).Value;        
  17.368         return 0;
  17.369     }
  17.370 
  17.371     // Alternative key versions of Get. Used by Hash.
  17.372     template<class K>
  17.373     const C* GetAlt(const K& key) const
  17.374     {
  17.375         SPInt   index = findIndexAlt(key);
  17.376         if (index >= 0)        
  17.377             return &E(index).Value;
  17.378         return 0;
  17.379     }
  17.380 
  17.381     template<class K>
  17.382     C* GetAlt(const K& key)
  17.383     {
  17.384         SPInt   index = findIndexAlt(key);
  17.385         if (index >= 0)        
  17.386             return &E(index).Value;
  17.387         return 0;
  17.388     }   
  17.389 
  17.390     template<class K>
  17.391     bool GetAlt(const K& key, C* pval) const
  17.392     {
  17.393         SPInt   index = findIndexAlt(key);
  17.394         if (index >= 0)
  17.395         {
  17.396             if (pval)
  17.397                 *pval = E(index).Value;
  17.398             return true;
  17.399         }
  17.400         return false;
  17.401     }
  17.402 
  17.403 
  17.404     UPInt GetSize() const
  17.405     {
  17.406         return pTable == NULL ? 0 : (UPInt)pTable->EntryCount;
  17.407     }
  17.408 
  17.409 
  17.410     // Resize the HashSet table to fit one more Entry.  Often this
  17.411     // doesn't involve any action.
  17.412     void CheckExpand()
  17.413     {
  17.414         if (pTable == NULL)
  17.415         {
  17.416             // Initial creation of table.  Make a minimum-sized table.
  17.417             setRawCapacity(HashMinSize);
  17.418         }
  17.419         else if (pTable->EntryCount * 5 > (pTable->SizeMask + 1) * 4)
  17.420         {
  17.421             // pTable is more than 5/4 ths full.  Expand.
  17.422             setRawCapacity((pTable->SizeMask + 1) * 2);
  17.423         }
  17.424     }
  17.425 
  17.426     // Hint the bucket count to >= n.
  17.427     void Resize(UPInt n)    
  17.428     {
  17.429         // Not really sure what this means in relation to
  17.430         // STLport's hash_map... they say they "increase the
  17.431         // bucket count to at least n" -- but does that mean
  17.432         // their real capacity after Resize(n) is more like
  17.433         // n*2 (since they do linked-list chaining within
  17.434         // buckets?).
  17.435         SetCapacity(n);
  17.436     }
  17.437 
  17.438     // Size the HashSet so that it can comfortably contain the given
  17.439     // number of elements.  If the HashSet already contains more
  17.440     // elements than newSize, then this may be a no-op.
  17.441     void SetCapacity(UPInt newSize)
  17.442     {
  17.443         UPInt newRawSize = (newSize * 5) / 4;
  17.444         if (newRawSize <= GetSize())
  17.445             return;
  17.446         setRawCapacity(newRawSize);
  17.447     }
  17.448 
  17.449     // Disable inappropriate 'operator ->' warning on MSVC6.
  17.450 #ifdef OVR_CC_MSVC
  17.451 #if (OVR_CC_MSVC < 1300)
  17.452 # pragma warning(disable : 4284)
  17.453 #endif
  17.454 #endif
  17.455 
  17.456     // Iterator API, like STL.
  17.457     struct ConstIterator
  17.458     {   
  17.459         const C&    operator * () const
  17.460         {            
  17.461             OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask);
  17.462             return pHash->E(Index).Value;
  17.463         }
  17.464 
  17.465         const C*    operator -> () const
  17.466         {
  17.467             OVR_ASSERT(Index >= 0 && Index <= (SPInt)pHash->pTable->SizeMask);
  17.468             return &pHash->E(Index).Value;
  17.469         }
  17.470 
  17.471         void    operator ++ ()
  17.472         {
  17.473             // Find next non-empty Entry.
  17.474             if (Index <= (SPInt)pHash->pTable->SizeMask)
  17.475             {
  17.476                 Index++;
  17.477                 while ((UPInt)Index <= pHash->pTable->SizeMask &&
  17.478                     pHash->E(Index).IsEmpty())
  17.479                 {
  17.480                     Index++;
  17.481                 }
  17.482             }
  17.483         }
  17.484 
  17.485         bool    operator == (const ConstIterator& it) const
  17.486         {
  17.487             if (IsEnd() && it.IsEnd())
  17.488             {
  17.489                 return true;
  17.490             }
  17.491             else
  17.492             {
  17.493                 return (pHash == it.pHash) && (Index == it.Index);
  17.494             }
  17.495         }
  17.496 
  17.497         bool    operator != (const ConstIterator& it) const
  17.498         {
  17.499             return ! (*this == it);
  17.500         }
  17.501 
  17.502 
  17.503         bool    IsEnd() const
  17.504         {
  17.505             return (pHash == NULL) || 
  17.506                 (pHash->pTable == NULL) || 
  17.507                 (Index > (SPInt)pHash->pTable->SizeMask);
  17.508         }
  17.509 
  17.510         ConstIterator()
  17.511             : pHash(NULL), Index(0)
  17.512         { }
  17.513 
  17.514     public:
  17.515         // Constructor was intentionally made public to allow create
  17.516         // iterator with arbitrary index.
  17.517         ConstIterator(const SelfType* h, SPInt index)
  17.518             : pHash(h), Index(index)
  17.519         { }
  17.520 
  17.521         const SelfType* GetContainer() const
  17.522         {
  17.523             return pHash;
  17.524         }
  17.525         SPInt GetIndex() const
  17.526         {
  17.527             return Index;
  17.528         }
  17.529 
  17.530     protected:
  17.531         friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
  17.532 
  17.533         const SelfType* pHash;
  17.534         SPInt           Index;
  17.535     };
  17.536 
  17.537     friend struct ConstIterator;
  17.538 
  17.539 
  17.540     // Non-const Iterator; Get most of it from ConstIterator.
  17.541     struct Iterator : public ConstIterator
  17.542     {      
  17.543         // Allow non-const access to entries.
  17.544         C&  operator*() const
  17.545         {            
  17.546             OVR_ASSERT(ConstIterator::Index >= 0 && ConstIterator::Index <= (SPInt)ConstIterator::pHash->pTable->SizeMask);
  17.547             return const_cast<SelfType*>(ConstIterator::pHash)->E(ConstIterator::Index).Value;
  17.548         }    
  17.549 
  17.550         C*  operator->() const 
  17.551         {
  17.552             return &(operator*());
  17.553         }
  17.554 
  17.555         Iterator()
  17.556             : ConstIterator(NULL, 0)
  17.557         { }
  17.558 
  17.559         // Removes current element from Hash
  17.560         void Remove()
  17.561         {
  17.562             RemoveAlt(operator*());
  17.563         }
  17.564 
  17.565         template <class K>
  17.566         void RemoveAlt(const K& key)
  17.567         {
  17.568             SelfType*   phash = const_cast<SelfType*>(ConstIterator::pHash);
  17.569             //Entry*      ee = &phash->E(ConstIterator::Index);
  17.570             //const C&    key = ee->Value;
  17.571 
  17.572             UPInt       hashValue = AltHashF()(key);
  17.573             SPInt       index     = hashValue & phash->pTable->SizeMask;
  17.574 
  17.575             Entry*      e = &phash->E(index);
  17.576 
  17.577             // If empty node or occupied by collider, we have nothing to remove.
  17.578             if (e->IsEmpty() || (e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)index))
  17.579                 return;        
  17.580 
  17.581             // Save index
  17.582             SPInt   naturalIndex = index;
  17.583             SPInt   prevIndex    = -1;
  17.584 
  17.585             while ((e->GetCachedHash(phash->pTable->SizeMask) != (UPInt)naturalIndex) || !(e->Value == key))
  17.586             {
  17.587                 // Keep looking through the chain.
  17.588                 prevIndex   = index;
  17.589                 index       = e->NextInChain;
  17.590                 if (index == -1)
  17.591                     return; // End of chain, item not found
  17.592                 e = &phash->E(index);
  17.593             }
  17.594 
  17.595             if (index == (SPInt)ConstIterator::Index)
  17.596             {
  17.597                 // Found it - our item is at index
  17.598                 if (naturalIndex == index)
  17.599                 {
  17.600                     // If we have a follower, move it to us
  17.601                     if (!e->IsEndOfChain())
  17.602                     {               
  17.603                         Entry*  enext = &phash->E(e->NextInChain);
  17.604                         e->Clear();
  17.605                         new (e) Entry(*enext);
  17.606                         // Point us to the follower's cell that will be cleared
  17.607                         e = enext;
  17.608                         --ConstIterator::Index;
  17.609                     }
  17.610                 }
  17.611                 else
  17.612                 {
  17.613                     // We are not at natural index, so deal with the prev items next index
  17.614                     phash->E(prevIndex).NextInChain = e->NextInChain;
  17.615                 }
  17.616 
  17.617                 // Clear us, of the follower cell that was moved.
  17.618                 e->Clear();
  17.619                 phash->pTable->EntryCount --;
  17.620             }
  17.621             else 
  17.622                 OVR_ASSERT(0); //?
  17.623         }
  17.624 
  17.625     private:
  17.626         friend class HashSetBase<C, HashF, AltHashF, Allocator, Entry>;
  17.627 
  17.628         Iterator(SelfType* h, SPInt i0)
  17.629             : ConstIterator(h, i0)
  17.630         { }
  17.631     };
  17.632 
  17.633     friend struct Iterator;
  17.634 
  17.635     Iterator    Begin()
  17.636     {
  17.637         if (pTable == 0)
  17.638             return Iterator(NULL, 0);
  17.639 
  17.640         // Scan till we hit the First valid Entry.
  17.641         UPInt  i0 = 0;
  17.642         while (i0 <= pTable->SizeMask && E(i0).IsEmpty())
  17.643         {
  17.644             i0++;
  17.645         }
  17.646         return Iterator(this, i0);
  17.647     }
  17.648     Iterator        End()           { return Iterator(NULL, 0); }
  17.649 
  17.650     ConstIterator   Begin() const   { return const_cast<SelfType*>(this)->Begin();     }
  17.651     ConstIterator   End() const     { return const_cast<SelfType*>(this)->End();   }
  17.652 
  17.653     template<class K>
  17.654     Iterator Find(const K& key)
  17.655     {
  17.656         SPInt index = findIndex(key);
  17.657         if (index >= 0)        
  17.658             return Iterator(this, index);        
  17.659         return Iterator(NULL, 0);
  17.660     }
  17.661 
  17.662     template<class K>
  17.663     Iterator FindAlt(const K& key)
  17.664     {
  17.665         SPInt index = findIndexAlt(key);
  17.666         if (index >= 0)        
  17.667             return Iterator(this, index);        
  17.668         return Iterator(NULL, 0);
  17.669     }
  17.670 
  17.671     template<class K>
  17.672     ConstIterator Find(const K& key) const       { return const_cast<SelfType*>(this)->Find(key); }
  17.673 
  17.674     template<class K>
  17.675     ConstIterator FindAlt(const K& key) const    { return const_cast<SelfType*>(this)->FindAlt(key); }
  17.676 
  17.677 private:
  17.678     // Find the index of the matching Entry.  If no match, then return -1.
  17.679     template<class K>
  17.680     SPInt findIndex(const K& key) const
  17.681     {
  17.682         if (pTable == NULL)
  17.683             return -1;
  17.684         UPInt hashValue = HashF()(key) & pTable->SizeMask;
  17.685         return findIndexCore(key, hashValue);
  17.686     }
  17.687 
  17.688     template<class K>
  17.689     SPInt findIndexAlt(const K& key) const
  17.690     {
  17.691         if (pTable == NULL)
  17.692             return -1;
  17.693         UPInt hashValue = AltHashF()(key) & pTable->SizeMask;
  17.694         return findIndexCore(key, hashValue);
  17.695     }
  17.696 
  17.697     // Find the index of the matching Entry.  If no match, then return -1.
  17.698     template<class K>
  17.699     SPInt findIndexCore(const K& key, UPInt hashValue) const
  17.700     {
  17.701         // Table must exist.
  17.702         OVR_ASSERT(pTable != 0);
  17.703         // Hash key must be 'and-ed' by the caller.
  17.704         OVR_ASSERT((hashValue & ~pTable->SizeMask) == 0);
  17.705 
  17.706         UPInt           index = hashValue;
  17.707         const Entry*    e     = &E(index);
  17.708 
  17.709         // If empty or occupied by a collider, not found.
  17.710         if (e->IsEmpty() || (e->GetCachedHash(pTable->SizeMask) != index))
  17.711             return -1;
  17.712 
  17.713         while(1)
  17.714         {
  17.715             OVR_ASSERT(e->GetCachedHash(pTable->SizeMask) == hashValue);
  17.716 
  17.717             if (e->GetCachedHash(pTable->SizeMask) == hashValue && e->Value == key)
  17.718             {
  17.719                 // Found it.
  17.720                 return index;
  17.721             }
  17.722             // Values can not be equal at this point.
  17.723             // That would mean that the hash key for the same value differs.
  17.724             OVR_ASSERT(!(e->Value == key));
  17.725 
  17.726             // Keep looking through the chain.
  17.727             index = e->NextInChain;
  17.728             if (index == (UPInt)-1)
  17.729                 break; // end of chain
  17.730 
  17.731             e = &E(index);
  17.732             OVR_ASSERT(!e->IsEmpty());
  17.733         }
  17.734         return -1;
  17.735     }
  17.736 
  17.737 
  17.738     // Add a new value to the HashSet table, under the specified key.
  17.739     template<class CRef>
  17.740     void add(const CRef& key, UPInt hashValue)
  17.741     {
  17.742         CheckExpand();
  17.743         hashValue &= pTable->SizeMask;
  17.744 
  17.745         pTable->EntryCount++;
  17.746 
  17.747         SPInt   index        = hashValue;
  17.748         Entry*  naturalEntry = &(E(index));
  17.749 
  17.750         if (naturalEntry->IsEmpty())
  17.751         {
  17.752             // Put the new Entry in.
  17.753             new (naturalEntry) Entry(key, -1);
  17.754         }
  17.755         else
  17.756         {
  17.757             // Find a blank spot.
  17.758             SPInt blankIndex = index;
  17.759             do {
  17.760                 blankIndex = (blankIndex + 1) & pTable->SizeMask;
  17.761             } while(!E(blankIndex).IsEmpty());
  17.762 
  17.763             Entry*  blankEntry = &E(blankIndex);
  17.764 
  17.765             if (naturalEntry->GetCachedHash(pTable->SizeMask) == (UPInt)index)
  17.766             {
  17.767                 // Collision.  Link into this chain.
  17.768 
  17.769                 // Move existing list head.
  17.770                 new (blankEntry) Entry(*naturalEntry);    // placement new, copy ctor
  17.771 
  17.772                 // Put the new info in the natural Entry.
  17.773                 naturalEntry->Value       = key;
  17.774                 naturalEntry->NextInChain = blankIndex;
  17.775             }
  17.776             else
  17.777             {
  17.778                 // Existing Entry does not naturally
  17.779                 // belong in this slot.  Existing
  17.780                 // Entry must be moved.
  17.781 
  17.782                 // Find natural location of collided element (i.e. root of chain)
  17.783                 SPInt collidedIndex = naturalEntry->GetCachedHash(pTable->SizeMask);
  17.784                 OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask);
  17.785                 for (;;)
  17.786                 {
  17.787                     Entry*  e = &E(collidedIndex);
  17.788                     if (e->NextInChain == index)
  17.789                     {
  17.790                         // Here's where we need to splice.
  17.791                         new (blankEntry) Entry(*naturalEntry);
  17.792                         e->NextInChain = blankIndex;
  17.793                         break;
  17.794                     }
  17.795                     collidedIndex = e->NextInChain;
  17.796                     OVR_ASSERT(collidedIndex >= 0 && collidedIndex <= (SPInt)pTable->SizeMask);
  17.797                 }
  17.798 
  17.799                 // Put the new data in the natural Entry.
  17.800                 naturalEntry->Value       = key;
  17.801                 naturalEntry->NextInChain = -1;                
  17.802             }            
  17.803         }
  17.804 
  17.805         // Record hash value: has effect only if cached node is used.
  17.806         naturalEntry->SetCachedHash(hashValue);
  17.807     }
  17.808 
  17.809     // Index access helpers.
  17.810     Entry& E(UPInt index)
  17.811     {
  17.812         // Must have pTable and access needs to be within bounds.
  17.813         OVR_ASSERT(index <= pTable->SizeMask);
  17.814         return *(((Entry*) (pTable + 1)) + index);
  17.815     }
  17.816     const Entry& E(UPInt index) const
  17.817     {        
  17.818         OVR_ASSERT(index <= pTable->SizeMask);
  17.819         return *(((Entry*) (pTable + 1)) + index);
  17.820     }
  17.821 
  17.822 
  17.823     // Resize the HashSet table to the given size (Rehash the
  17.824     // contents of the current table).  The arg is the number of
  17.825     // HashSet table entries, not the number of elements we should
  17.826     // actually contain (which will be less than this).
  17.827     void    setRawCapacity(UPInt newSize)    
  17.828     {
  17.829         if (newSize == 0)
  17.830         {
  17.831             // Special case.
  17.832             Clear();
  17.833             return;
  17.834         }
  17.835 
  17.836         // Minimum size; don't incur rehashing cost when expanding
  17.837         // very small tables. Not that we perform this check before 
  17.838         // 'log2f' call to avoid fp exception with newSize == 1.
  17.839         if (newSize < HashMinSize)        
  17.840             newSize = HashMinSize;       
  17.841         else
  17.842         {
  17.843             // Force newSize to be a power of two.
  17.844             int bits = Alg::UpperBit(newSize-1) + 1; // Chop( Log2f((float)(newSize-1)) + 1);
  17.845             OVR_ASSERT((UPInt(1) << bits) >= newSize);
  17.846             newSize = UPInt(1) << bits;
  17.847         }
  17.848 
  17.849         SelfType  newHash;
  17.850         newHash.pTable = (TableType*)
  17.851             Allocator::Alloc(                
  17.852                 sizeof(TableType) + sizeof(Entry) * newSize);
  17.853         // Need to do something on alloc failure!
  17.854         OVR_ASSERT(newHash.pTable);
  17.855 
  17.856         newHash.pTable->EntryCount = 0;
  17.857         newHash.pTable->SizeMask = newSize - 1;
  17.858         UPInt i, n;
  17.859 
  17.860         // Mark all entries as empty.
  17.861         for (i = 0; i < newSize; i++)
  17.862             newHash.E(i).NextInChain = -2;
  17.863 
  17.864         // Copy stuff to newHash
  17.865         if (pTable)
  17.866         {            
  17.867             for (i = 0, n = pTable->SizeMask; i <= n; i++)
  17.868             {
  17.869                 Entry*  e = &E(i);
  17.870                 if (e->IsEmpty() == false)
  17.871                 {
  17.872                     // Insert old Entry into new HashSet.
  17.873                     newHash.Add(e->Value);
  17.874                     // placement delete of old element
  17.875                     e->Clear();
  17.876                 }
  17.877             }
  17.878 
  17.879             // Delete our old data buffer.
  17.880             Allocator::Free(pTable);
  17.881         }
  17.882 
  17.883         // Steal newHash's data.
  17.884         pTable = newHash.pTable;
  17.885         newHash.pTable = NULL;
  17.886     }
  17.887 
  17.888     struct TableType
  17.889     {
  17.890         UPInt EntryCount;
  17.891         UPInt SizeMask;
  17.892         // Entry array follows this structure
  17.893         // in memory.
  17.894     };
  17.895     TableType*  pTable;
  17.896 };
  17.897 
  17.898 
  17.899 
  17.900 //-----------------------------------------------------------------------------------
  17.901 template<class C, class HashF = FixedSizeHash<C>,
  17.902          class AltHashF = HashF, 
  17.903          class Allocator = ContainerAllocator<C>,
  17.904          class Entry = HashsetCachedEntry<C, HashF> >
  17.905 class HashSet : public HashSetBase<C, HashF, AltHashF, Allocator, Entry>
  17.906 {
  17.907 public:
  17.908     typedef HashSetBase<C, HashF, AltHashF, Allocator, Entry> BaseType;
  17.909     typedef HashSet<C, HashF, AltHashF, Allocator, Entry>     SelfType;
  17.910 
  17.911     HashSet()                                      {   }
  17.912     HashSet(int sizeHint) : BaseType(sizeHint)     {   }
  17.913     HashSet(const SelfType& src) : BaseType(src)   {   }
  17.914     ~HashSet()                                     {   }
  17.915 
  17.916     void operator = (const SelfType& src)   { BaseType::Assign(src); }
  17.917 
  17.918     // Set a new or existing value under the key, to the value.
  17.919     // Pass a different class of 'key' so that assignment reference object
  17.920     // can be passed instead of the actual object.
  17.921     template<class CRef>
  17.922     void Set(const CRef& key)
  17.923     {
  17.924         BaseType::Set(key);
  17.925     }
  17.926 
  17.927     template<class CRef>
  17.928     inline void Add(const CRef& key)
  17.929     {
  17.930         BaseType::Add(key);
  17.931     }
  17.932 
  17.933     // Hint the bucket count to >= n.
  17.934     void Resize(UPInt n)    
  17.935     {
  17.936         BaseType::SetCapacity(n);
  17.937     }
  17.938 
  17.939     // Size the HashSet so that it can comfortably contain the given
  17.940     // number of elements.  If the HashSet already contains more
  17.941     // elements than newSize, then this may be a no-op.
  17.942     void SetCapacity(UPInt newSize)
  17.943     {
  17.944         BaseType::SetCapacity(newSize);
  17.945     }
  17.946 
  17.947 };
  17.948 
  17.949 // HashSet with uncached hash code; declared for convenience.
  17.950 template<class C, class HashF = FixedSizeHash<C>,
  17.951                   class AltHashF = HashF,
  17.952                   class Allocator = ContainerAllocator<C> >
  17.953 class HashSetUncached : public HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> >
  17.954 {
  17.955 public:
  17.956     
  17.957     typedef HashSetUncached<C, HashF, AltHashF, Allocator>                  SelfType;
  17.958     typedef HashSet<C, HashF, AltHashF, Allocator, HashsetEntry<C, HashF> > BaseType;
  17.959 
  17.960     // Delegated constructors.
  17.961     HashSetUncached()                                        { }
  17.962     HashSetUncached(int sizeHint) : BaseType(sizeHint)       { }
  17.963     HashSetUncached(const SelfType& src) : BaseType(src)     { }
  17.964     ~HashSetUncached()                                       { }
  17.965     
  17.966     void    operator = (const SelfType& src)
  17.967     {
  17.968         BaseType::operator = (src);
  17.969     }
  17.970 };
  17.971 
  17.972 
  17.973 //-----------------------------------------------------------------------------------
  17.974 // ***** Hash hash table implementation
  17.975 
  17.976 // Node for Hash - necessary so that Hash can delegate its implementation
  17.977 // to HashSet.
  17.978 template<class C, class U, class HashF>
  17.979 struct HashNode
  17.980 {
  17.981     typedef HashNode<C, U, HashF>   SelfType;
  17.982     typedef C                       FirstType;
  17.983     typedef U                       SecondType;
  17.984 
  17.985     C   First;
  17.986     U   Second;
  17.987 
  17.988     // NodeRef is used to allow passing of elements into HashSet
  17.989     // without using a temporary object.
  17.990     struct NodeRef
  17.991     {
  17.992         const C*   pFirst;
  17.993         const U*   pSecond;
  17.994 
  17.995         NodeRef(const C& f, const U& s) : pFirst(&f), pSecond(&s) { }
  17.996         NodeRef(const NodeRef& src)     : pFirst(src.pFirst), pSecond(src.pSecond) { }
  17.997 
  17.998         // Enable computation of ghash_node_hashf.
  17.999         inline UPInt GetHash() const            { return HashF()(*pFirst); } 
 17.1000         // Necessary conversion to allow HashNode::operator == to work.
 17.1001         operator const C& () const              { return *pFirst; }
 17.1002     };
 17.1003 
 17.1004     // Note: No default constructor is necessary.
 17.1005      HashNode(const HashNode& src) : First(src.First), Second(src.Second)    { }
 17.1006      HashNode(const NodeRef& src) : First(*src.pFirst), Second(*src.pSecond)  { }
 17.1007     void operator = (const NodeRef& src)  { First  = *src.pFirst; Second = *src.pSecond; }
 17.1008 
 17.1009     template<class K>
 17.1010     bool operator == (const K& src) const   { return (First == src); }
 17.1011 
 17.1012     template<class K>
 17.1013     static UPInt CalcHash(const K& data)   { return HashF()(data); }
 17.1014     inline UPInt GetHash() const           { return HashF()(First); }
 17.1015 
 17.1016     // Hash functors used with this node. A separate functor is used for alternative
 17.1017     // key lookup so that it does not need to access the '.First' element.    
 17.1018     struct NodeHashF
 17.1019     {    
 17.1020         template<class K>
 17.1021         UPInt operator()(const K& data) const { return data.GetHash(); } 
 17.1022     };    
 17.1023     struct NodeAltHashF
 17.1024     {
 17.1025         template<class K>
 17.1026         UPInt operator()(const K& data) const { return HashNode<C,U,HashF>::CalcHash(data); }
 17.1027     };
 17.1028 };
 17.1029 
 17.1030 
 17.1031 
 17.1032 // **** Extra hashset_entry types to allow NodeRef construction.
 17.1033 
 17.1034 // The big difference between the below types and the ones used in hash_set is that
 17.1035 // these allow initializing the node with 'typename C::NodeRef& keyRef', which
 17.1036 // is critical to avoid temporary node allocation on stack when using placement new.
 17.1037 
 17.1038 // Compact hash table Entry type that re-computes hash keys during hash traversal.
 17.1039 // Good to use if the hash function is cheap or the hash value is already cached in C.
 17.1040 template<class C, class HashF>
 17.1041 class HashsetNodeEntry
 17.1042 {
 17.1043 public:
 17.1044     // Internal chaining for collisions.
 17.1045     SPInt NextInChain;
 17.1046     C     Value;
 17.1047 
 17.1048     HashsetNodeEntry()
 17.1049         : NextInChain(-2) { }
 17.1050     HashsetNodeEntry(const HashsetNodeEntry& e)
 17.1051         : NextInChain(e.NextInChain), Value(e.Value) { }
 17.1052     HashsetNodeEntry(const C& key, SPInt next)
 17.1053         : NextInChain(next), Value(key) { }    
 17.1054     HashsetNodeEntry(const typename C::NodeRef& keyRef, SPInt next)
 17.1055         : NextInChain(next), Value(keyRef) { }
 17.1056 
 17.1057     bool    IsEmpty() const             { return NextInChain == -2;  }
 17.1058     bool    IsEndOfChain() const        { return NextInChain == -1;  }
 17.1059     UPInt   GetCachedHash(UPInt maskValue) const  { return HashF()(Value) & maskValue; }
 17.1060     void    SetCachedHash(UPInt hashValue)        { OVR_UNUSED(hashValue); }
 17.1061 
 17.1062     void    Clear()
 17.1063     {        
 17.1064         Value.~C(); // placement delete
 17.1065         NextInChain = -2;
 17.1066     }
 17.1067     // Free is only used from dtor of hash; Clear is used during regular operations:
 17.1068     // assignment, hash reallocations, value reassignments, so on.
 17.1069     void    Free() { Clear(); }
 17.1070 };
 17.1071 
 17.1072 // Hash table Entry type that caches the Entry hash value for nodes, so that it
 17.1073 // does not need to be re-computed during access.
 17.1074 template<class C, class HashF>
 17.1075 class HashsetCachedNodeEntry
 17.1076 {
 17.1077 public:
 17.1078     // Internal chaining for collisions.
 17.1079     SPInt NextInChain;
 17.1080     UPInt HashValue;
 17.1081     C     Value;
 17.1082 
 17.1083     HashsetCachedNodeEntry()
 17.1084         : NextInChain(-2) { }
 17.1085     HashsetCachedNodeEntry(const HashsetCachedNodeEntry& e)
 17.1086         : NextInChain(e.NextInChain), HashValue(e.HashValue), Value(e.Value) { }
 17.1087     HashsetCachedNodeEntry(const C& key, SPInt next)
 17.1088         : NextInChain(next), Value(key) { }
 17.1089     HashsetCachedNodeEntry(const typename C::NodeRef& keyRef, SPInt next)
 17.1090         : NextInChain(next), Value(keyRef) { }
 17.1091 
 17.1092     bool    IsEmpty() const            { return NextInChain == -2;  }
 17.1093     bool    IsEndOfChain() const       { return NextInChain == -1;  }
 17.1094     UPInt   GetCachedHash(UPInt maskValue) const  { OVR_UNUSED(maskValue); return HashValue; }
 17.1095     void    SetCachedHash(UPInt hashValue)        { HashValue = hashValue; }
 17.1096 
 17.1097     void    Clear()
 17.1098     {
 17.1099         Value.~C();
 17.1100         NextInChain = -2;
 17.1101     }
 17.1102     // Free is only used from dtor of hash; Clear is used during regular operations:
 17.1103     // assignment, hash reallocations, value reassignments, so on.
 17.1104     void    Free() { Clear(); }
 17.1105 };
 17.1106 
 17.1107 
 17.1108 //-----------------------------------------------------------------------------------
 17.1109 template<class C, class U,
 17.1110          class HashF = FixedSizeHash<C>,
 17.1111          class Allocator = ContainerAllocator<C>,
 17.1112          class HashNode = OVR::HashNode<C,U,HashF>,
 17.1113          class Entry = HashsetCachedNodeEntry<HashNode, typename HashNode::NodeHashF>,
 17.1114          class Container =  HashSet<HashNode, typename HashNode::NodeHashF,
 17.1115              typename HashNode::NodeAltHashF, Allocator,
 17.1116              Entry> >
 17.1117 class Hash
 17.1118 {
 17.1119 public:
 17.1120     OVR_MEMORY_REDEFINE_NEW(Hash)
 17.1121 
 17.1122     // Types used for hash_set.
 17.1123     typedef U                                                           ValueType;
 17.1124     typedef Hash<C, U, HashF, Allocator, HashNode, Entry, Container>    SelfType;
 17.1125 
 17.1126     // Actual hash table itself, implemented as hash_set.
 17.1127     Container   mHash;
 17.1128 
 17.1129 public:
 17.1130     Hash()     {  }
 17.1131     Hash(int sizeHint) : mHash(sizeHint)                        { }
 17.1132     Hash(const SelfType& src) : mHash(src.mHash)                { }
 17.1133     ~Hash()                                                     { }
 17.1134 
 17.1135     void    operator = (const SelfType& src)    { mHash = src.mHash; }
 17.1136 
 17.1137     // Remove all entries from the Hash table.
 17.1138     inline void    Clear() { mHash.Clear(); }
 17.1139     // Returns true if the Hash is empty.
 17.1140     inline bool    IsEmpty() const { return mHash.IsEmpty(); }
 17.1141 
 17.1142     // Access (set).
 17.1143     inline void    Set(const C& key, const U& value)
 17.1144     {
 17.1145         typename HashNode::NodeRef e(key, value);
 17.1146         mHash.Set(e);
 17.1147     }
 17.1148     inline void    Add(const C& key, const U& value)
 17.1149     {
 17.1150         typename HashNode::NodeRef e(key, value);
 17.1151         mHash.Add(e);
 17.1152     }
 17.1153 
 17.1154     // Removes an element by clearing its Entry.
 17.1155     inline void     Remove(const C& key)
 17.1156     {   
 17.1157         mHash.RemoveAlt(key);
 17.1158     }
 17.1159     template<class K>
 17.1160     inline void     RemoveAlt(const K& key)
 17.1161     {   
 17.1162         mHash.RemoveAlt(key);
 17.1163     }
 17.1164 
 17.1165     // Retrieve the value under the given key.    
 17.1166     //  - If there's no value under the key, then return false and leave *pvalue alone.
 17.1167     //  - If there is a value, return true, and Set *Pvalue to the Entry's value.
 17.1168     //  - If value == NULL, return true or false according to the presence of the key.    
 17.1169     bool    Get(const C& key, U* pvalue) const   
 17.1170     {
 17.1171         const HashNode* p = mHash.GetAlt(key);
 17.1172         if (p)
 17.1173         {
 17.1174             if (pvalue)
 17.1175                 *pvalue = p->Second;
 17.1176             return true;
 17.1177         }
 17.1178         return false;
 17.1179     }
 17.1180 
 17.1181     template<class K>
 17.1182     bool    GetAlt(const K& key, U* pvalue) const   
 17.1183     {
 17.1184         const HashNode* p = mHash.GetAlt(key);
 17.1185         if (p)
 17.1186         {
 17.1187             if (pvalue)
 17.1188                 *pvalue = p->Second;
 17.1189             return true;
 17.1190         }
 17.1191         return false;
 17.1192     }
 17.1193 
 17.1194     // Retrieve the pointer to a value under the given key.    
 17.1195     //  - If there's no value under the key, then return NULL.    
 17.1196     //  - If there is a value, return the pointer.    
 17.1197     inline U*  Get(const C& key)
 17.1198     {
 17.1199         HashNode* p = mHash.GetAlt(key);
 17.1200         return p ? &p->Second : 0;
 17.1201     }
 17.1202     inline const U* Get(const C& key) const
 17.1203     {
 17.1204         const HashNode* p = mHash.GetAlt(key);
 17.1205         return p ? &p->Second : 0;
 17.1206     }
 17.1207 
 17.1208     template<class K>
 17.1209     inline U*  GetAlt(const K& key)
 17.1210     {
 17.1211         HashNode* p = mHash.GetAlt(key);
 17.1212         return p ? &p->Second : 0;
 17.1213     }
 17.1214     template<class K>
 17.1215     inline const U* GetAlt(const K& key) const
 17.1216     {
 17.1217         const HashNode* p = mHash.GetAlt(key);
 17.1218         return p ? &p->Second : 0;
 17.1219     }
 17.1220 
 17.1221     // Sizing methods - delegate to Hash.
 17.1222     inline UPInt   GetSize() const              { return mHash.GetSize(); }    
 17.1223     inline void    Resize(UPInt n)              { mHash.Resize(n); }
 17.1224     inline void    SetCapacity(UPInt newSize)   { mHash.SetCapacity(newSize); }
 17.1225 
 17.1226     // Iterator API, like STL.
 17.1227     typedef typename Container::ConstIterator   ConstIterator;
 17.1228     typedef typename Container::Iterator        Iterator;
 17.1229 
 17.1230     inline Iterator        Begin()              { return mHash.Begin(); }
 17.1231     inline Iterator        End()                { return mHash.End(); }
 17.1232     inline ConstIterator   Begin() const        { return mHash.Begin(); }
 17.1233     inline ConstIterator   End() const          { return mHash.End();   }
 17.1234 
 17.1235     Iterator        Find(const C& key)          { return mHash.FindAlt(key);  }
 17.1236     ConstIterator   Find(const C& key) const    { return mHash.FindAlt(key);  }
 17.1237 
 17.1238     template<class K>
 17.1239     Iterator        FindAlt(const K& key)       { return mHash.FindAlt(key);  }
 17.1240     template<class K>
 17.1241     ConstIterator   FindAlt(const K& key) const { return mHash.FindAlt(key);  }
 17.1242 };
 17.1243 
 17.1244 
 17.1245 
 17.1246 // Hash with uncached hash code; declared for convenience.
 17.1247 template<class C, class U, class HashF = FixedSizeHash<C>, class Allocator = ContainerAllocator<C> >
 17.1248 class HashUncached
 17.1249     : public Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>,
 17.1250                    HashsetNodeEntry<HashNode<C,U,HashF>, typename HashNode<C,U,HashF>::NodeHashF> >
 17.1251 {
 17.1252 public:
 17.1253     typedef HashUncached<C, U, HashF, Allocator>                SelfType;
 17.1254     typedef Hash<C, U, HashF, Allocator, HashNode<C,U,HashF>,
 17.1255                  HashsetNodeEntry<HashNode<C,U,HashF>,
 17.1256                  typename HashNode<C,U,HashF>::NodeHashF> >     BaseType;
 17.1257 
 17.1258     // Delegated constructors.
 17.1259     HashUncached()                                        { }
 17.1260     HashUncached(int sizeHint) : BaseType(sizeHint)       { }
 17.1261     HashUncached(const SelfType& src) : BaseType(src)     { }
 17.1262     ~HashUncached()                                       { }
 17.1263     void operator = (const SelfType& src)                 { BaseType::operator = (src); }
 17.1264 };
 17.1265 
 17.1266 
 17.1267 
 17.1268 // And identity hash in which keys serve as hash value. Can be uncached,
 17.1269 // since hash computation is assumed cheap.
 17.1270 template<class C, class U, class Allocator = ContainerAllocator<C>, class HashF = IdentityHash<C> >
 17.1271 class HashIdentity
 17.1272     : public HashUncached<C, U, HashF, Allocator>
 17.1273 {
 17.1274 public:
 17.1275     typedef HashIdentity<C, U, Allocator, HashF> SelfType;
 17.1276     typedef HashUncached<C, U, HashF, Allocator> BaseType;
 17.1277 
 17.1278     // Delegated constructors.
 17.1279     HashIdentity()                                        { }
 17.1280     HashIdentity(int sizeHint) : BaseType(sizeHint)       { }
 17.1281     HashIdentity(const SelfType& src) : BaseType(src)     { }
 17.1282     ~HashIdentity()                                       { }
 17.1283     void operator = (const SelfType& src)                 { BaseType::operator = (src); }
 17.1284 };
 17.1285 
 17.1286 
 17.1287 } // OVR
 17.1288 
 17.1289 
 17.1290 #ifdef OVR_DEFINE_NEW
 17.1291 #define new OVR_DEFINE_NEW
 17.1292 #endif
 17.1293 
 17.1294 #endif
 17.1295 \ No newline at end of file
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/libovr/Src/Kernel/OVR_KeyCodes.h	Sat Sep 14 16:14:59 2013 +0300
    18.3 @@ -0,0 +1,1 @@
    18.4 +/************************************************************************************
    18.5 
    18.6 PublicHeader:   OVR.h
    18.7 Filename    :   OVR_KeyCodes.h
    18.8 Content     :   Common keyboard constants
    18.9 Created     :   September 19, 2012
   18.10 
   18.11 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   18.12 
   18.13 Use of this software is subject to the terms of the Oculus license
   18.14 agreement provided at the time of installation or download, or which
   18.15 otherwise accompanies this software in either electronic or hard copy form.
   18.16 
   18.17 ************************************************************************************/
   18.18 
   18.19 #ifndef OVR_KeyCodes_h
   18.20 #define OVR_KeyCodes_h
   18.21 
   18.22 namespace OVR {
   18.23 
   18.24 //-----------------------------------------------------------------------------------
   18.25 // ***** KeyCode
   18.26 
   18.27 // KeyCode enumeration defines platform-independent keyboard key constants.
   18.28 // Note that Key_A through Key_Z are mapped to capital ascii constants.
   18.29 
   18.30 enum KeyCode
   18.31 {
   18.32     // Key_None indicates that no key was specified.
   18.33     Key_None            = 0, 
   18.34 
   18.35     // A through Z and numbers 0 through 9.
   18.36     Key_A               = 65,
   18.37     Key_B,
   18.38     Key_C,
   18.39     Key_D,
   18.40     Key_E,
   18.41     Key_F,
   18.42     Key_G,
   18.43     Key_H,
   18.44     Key_I,
   18.45     Key_J,
   18.46     Key_K,
   18.47     Key_L,
   18.48     Key_M,
   18.49     Key_N,
   18.50     Key_O,
   18.51     Key_P,
   18.52     Key_Q,
   18.53     Key_R,
   18.54     Key_S,
   18.55     Key_T,
   18.56     Key_U,
   18.57     Key_V,
   18.58     Key_W,
   18.59     Key_X,
   18.60     Key_Y,
   18.61     Key_Z,
   18.62     Key_Num0            = 48,
   18.63     Key_Num1,
   18.64     Key_Num2,
   18.65     Key_Num3,
   18.66     Key_Num4,
   18.67     Key_Num5,
   18.68     Key_Num6,
   18.69     Key_Num7,
   18.70     Key_Num8,
   18.71     Key_Num9,
   18.72 
   18.73     // Numeric keypad.
   18.74     Key_KP_0            = 0xa0,
   18.75     Key_KP_1,
   18.76     Key_KP_2,
   18.77     Key_KP_3,
   18.78     Key_KP_4,
   18.79     Key_KP_5,
   18.80     Key_KP_6,
   18.81     Key_KP_7,
   18.82     Key_KP_8,
   18.83     Key_KP_9,
   18.84     Key_KP_Multiply,
   18.85     Key_KP_Add,
   18.86     Key_KP_Enter,
   18.87     Key_KP_Subtract,
   18.88     Key_KP_Decimal,
   18.89     Key_KP_Divide,
   18.90     
   18.91     // Function keys.
   18.92     Key_F1              = 0xb0,
   18.93     Key_F2,
   18.94     Key_F3,
   18.95     Key_F4,
   18.96     Key_F5,
   18.97     Key_F6,
   18.98     Key_F7,
   18.99     Key_F8,
  18.100     Key_F9,
  18.101     Key_F10,
  18.102     Key_F11,
  18.103     Key_F12,
  18.104     Key_F13,
  18.105     Key_F14,
  18.106     Key_F15,
  18.107     
  18.108     // Other keys.
  18.109     Key_Backspace       = 8,
  18.110     Key_Tab,
  18.111     Key_Clear           = 12,
  18.112     Key_Return,
  18.113     Key_Shift           = 16,
  18.114     Key_Control,
  18.115     Key_Alt,
  18.116     Key_Pause,
  18.117     Key_CapsLock        = 20, // Toggle
  18.118     Key_Escape          = 27,
  18.119     Key_Space           = 32,
  18.120     Key_Quote           = 39,
  18.121     Key_PageUp          = 0xc0,
  18.122     Key_PageDown,
  18.123     Key_End,
  18.124     Key_Home,
  18.125     Key_Left,
  18.126     Key_Up,
  18.127     Key_Right,
  18.128     Key_Down,
  18.129     Key_Insert,
  18.130     Key_Delete,
  18.131     Key_Help,
  18.132     
  18.133     Key_Comma           = 44,
  18.134     Key_Minus,
  18.135     Key_Slash           = 47,
  18.136     Key_Period,
  18.137     Key_NumLock         = 144, // Toggle
  18.138     Key_ScrollLock      = 145, // Toggle
  18.139     
  18.140     Key_Semicolon       = 59,
  18.141     Key_Equal           = 61,
  18.142     Key_Bar             = 192,
  18.143     Key_BracketLeft     = 91,
  18.144     Key_Backslash,
  18.145     Key_BracketRight,
  18.146 
  18.147     Key_OEM_AX          = 0xE1,  //  'AX' key on Japanese AX keyboard
  18.148     Key_OEM_102         = 0xE2,  //  "<>" or "\|" on RT 102-key keyboard.
  18.149     Key_ICO_HELP        = 0xE3,  //  Help key on ICO
  18.150     Key_ICO_00          = 0xE4,  //  00 key on ICO
  18.151 
  18.152     Key_Meta,
  18.153 
  18.154     // Total number of keys.
  18.155     Key_CodeCount
  18.156 };
  18.157 
  18.158 
  18.159 //-----------------------------------------------------------------------------------
  18.160 
  18.161 class KeyModifiers 
  18.162 {
  18.163 public:
  18.164     enum
  18.165     {
  18.166         Key_ShiftPressed    = 0x01,
  18.167         Key_CtrlPressed     = 0x02,
  18.168         Key_AltPressed      = 0x04,
  18.169         Key_MetaPressed     = 0x08,
  18.170         Key_CapsToggled     = 0x10,
  18.171         Key_NumToggled      = 0x20,
  18.172         Key_ScrollToggled   = 0x40,
  18.173 
  18.174         Initialized_Bit     = 0x80,
  18.175         Initialized_Mask    = 0xFF
  18.176     };
  18.177     unsigned char States;
  18.178 
  18.179     KeyModifiers() : States(0) { }
  18.180         KeyModifiers(unsigned char st) : States((unsigned char)(st | Initialized_Bit)) { }
  18.181 
  18.182     void Reset() { States = 0; }
  18.183 
  18.184     bool IsShiftPressed() const { return (States & Key_ShiftPressed) != 0; }
  18.185     bool IsCtrlPressed() const  { return (States & Key_CtrlPressed) != 0; }
  18.186     bool IsAltPressed() const   { return (States & Key_AltPressed) != 0; }
  18.187     bool IsMetaPressed() const  { return (States & Key_MetaPressed) != 0; }
  18.188     bool IsCapsToggled() const  { return (States & Key_CapsToggled) != 0; }
  18.189     bool IsNumToggled() const   { return (States & Key_NumToggled) != 0; }
  18.190     bool IsScrollToggled() const{ return (States & Key_ScrollToggled) != 0; }
  18.191 
  18.192     void SetShiftPressed(bool v = true)  { (v) ? States |= Key_ShiftPressed : States &= ~Key_ShiftPressed; }
  18.193     void SetCtrlPressed(bool v = true)   { (v) ? States |= Key_CtrlPressed  : States &= ~Key_CtrlPressed; }
  18.194     void SetAltPressed(bool v = true)    { (v) ? States |= Key_AltPressed   : States &= ~Key_AltPressed; }
  18.195     void SetMetaPressed(bool v = true)   { (v) ? States |= Key_MetaPressed  : States &= ~Key_MetaPressed; }
  18.196     void SetCapsToggled(bool v = true)   { (v) ? States |= Key_CapsToggled  : States &= ~Key_CapsToggled; }
  18.197     void SetNumToggled(bool v = true)    { (v) ? States |= Key_NumToggled   : States &= ~Key_NumToggled; }
  18.198     void SetScrollToggled(bool v = true) { (v) ? States |= Key_ScrollToggled: States &= ~Key_ScrollToggled; }
  18.199 
  18.200     bool IsInitialized() const { return (States & Initialized_Mask) != 0; }
  18.201 };
  18.202 
  18.203 
  18.204 //-----------------------------------------------------------------------------------
  18.205 
  18.206 /*
  18.207 enum PadKeyCode
  18.208 {
  18.209     Pad_None, // Indicates absence of key code.
  18.210     Pad_Back,
  18.211     Pad_Start,
  18.212     Pad_A,
  18.213     Pad_B,
  18.214     Pad_X,
  18.215     Pad_Y,
  18.216     Pad_R1,  // RightShoulder;
  18.217     Pad_L1,  // LeftShoulder;
  18.218     Pad_R2,  // RightTrigger;
  18.219     Pad_L2,  // LeftTrigger;
  18.220     Pad_Up,
  18.221     Pad_Down,
  18.222     Pad_Right,
  18.223     Pad_Left,
  18.224     Pad_Plus,
  18.225     Pad_Minus,
  18.226     Pad_1,
  18.227     Pad_2,
  18.228     Pad_H,
  18.229     Pad_C,
  18.230     Pad_Z,
  18.231     Pad_O,
  18.232     Pad_T,
  18.233     Pad_S,
  18.234     Pad_Select,
  18.235     Pad_Home,
  18.236     Pad_RT,  // RightThumb;
  18.237     Pad_LT   // LeftThumb;
  18.238 };
  18.239 */
  18.240 
  18.241 } // OVR
  18.242 
  18.243 #endif
  18.244 \ No newline at end of file
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/libovr/Src/Kernel/OVR_List.h	Sat Sep 14 16:14:59 2013 +0300
    19.3 @@ -0,0 +1,1 @@
    19.4 +/************************************************************************************
    19.5 
    19.6 PublicHeader:   OVR
    19.7 Filename    :   OVR_List.h
    19.8 Content     :   Template implementation for doubly-connected linked List
    19.9 Created     :   September 19, 2012
   19.10 Notes       : 
   19.11 
   19.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   19.13 
   19.14 Use of this software is subject to the terms of the Oculus license
   19.15 agreement provided at the time of installation or download, or which
   19.16 otherwise accompanies this software in either electronic or hard copy form.
   19.17 
   19.18 ************************************************************************************/
   19.19 
   19.20 #ifndef OVR_List_h
   19.21 #define OVR_List_h
   19.22 
   19.23 #include "OVR_Types.h"
   19.24 
   19.25 namespace OVR {
   19.26 
   19.27 //-----------------------------------------------------------------------------------
   19.28 // ***** ListNode
   19.29 //
   19.30 // Base class for the elements of the intrusive linked list.
   19.31 // To store elements in the List do:
   19.32 //
   19.33 // struct MyData : ListNode<MyData>
   19.34 // {
   19.35 //     . . .
   19.36 // };
   19.37 
   19.38 template<class T>
   19.39 struct ListNode
   19.40 {
   19.41     union {
   19.42         T*    pPrev;
   19.43         void* pVoidPrev;
   19.44     };
   19.45     union {
   19.46         T*    pNext;
   19.47         void* pVoidNext;
   19.48     };
   19.49 
   19.50     void    RemoveNode()
   19.51     {
   19.52         pPrev->pNext = pNext;
   19.53         pNext->pPrev = pPrev;
   19.54     }
   19.55 
   19.56     // Removes us from the list and inserts pnew there instead.
   19.57     void    ReplaceNodeWith(T* pnew)
   19.58     {
   19.59         pPrev->pNext = pnew;
   19.60         pNext->pPrev = pnew;
   19.61         pnew->pPrev = pPrev;
   19.62         pnew->pNext = pNext;
   19.63     }
   19.64        
   19.65     // Inserts the argument linked list node after us in the list.
   19.66     void    InsertNodeAfter(T* p)
   19.67     {
   19.68         p->pPrev          = pNext->pPrev; // this
   19.69         p->pNext          = pNext;
   19.70         pNext->pPrev      = p;
   19.71         pNext             = p;
   19.72     }
   19.73     // Inserts the argument linked list node before us in the list.
   19.74     void    InsertNodeBefore(T* p)
   19.75     {
   19.76         p->pNext          = pNext->pPrev; // this
   19.77         p->pPrev          = pPrev;
   19.78         pPrev->pNext      = p;
   19.79         pPrev             = p;
   19.80     }
   19.81 
   19.82     void    Alloc_MoveTo(ListNode<T>* pdest)
   19.83     {
   19.84         pdest->pNext = pNext;
   19.85         pdest->pPrev = pPrev;
   19.86         pPrev->pNext = (T*)pdest;
   19.87         pNext->pPrev = (T*)pdest;
   19.88     }
   19.89 };
   19.90 
   19.91 
   19.92 //------------------------------------------------------------------------
   19.93 // ***** List
   19.94 //
   19.95 // Doubly linked intrusive list. 
   19.96 // The data type must be derived from ListNode.
   19.97 // 
   19.98 // Adding:   PushFront(), PushBack().
   19.99 // Removing: Remove() - the element must be in the list!
  19.100 // Moving:   BringToFront(), SendToBack() - the element must be in the list!
  19.101 //
  19.102 // Iterating:
  19.103 //    MyData* data = MyList.GetFirst();
  19.104 //    while (!MyList.IsNull(data))
  19.105 //    {
  19.106 //        . . .
  19.107 //        data = MyList.GetNext(data);
  19.108 //    }
  19.109 //
  19.110 // Removing:
  19.111 //    MyData* data = MyList.GetFirst();
  19.112 //    while (!MyList.IsNull(data))
  19.113 //    {
  19.114 //        MyData* next = MyList.GetNext(data);
  19.115 //        if (ToBeRemoved(data))
  19.116 //             MyList.Remove(data);
  19.117 //        data = next;
  19.118 //    }
  19.119 //
  19.120 
  19.121 // List<> represents a doubly-linked list of T, where each T must derive
  19.122 // from ListNode<B>. B specifies the base class that was directly
  19.123 // derived from ListNode, and is only necessary if there is an intermediate
  19.124 // inheritance chain.
  19.125 
  19.126 template<class T, class B = T> class List
  19.127 {
  19.128 public:
  19.129     typedef T ValueType;
  19.130 
  19.131     List()
  19.132     {
  19.133         Root.pNext = Root.pPrev = (ValueType*)&Root;
  19.134     }
  19.135 
  19.136     void Clear()
  19.137     {
  19.138         Root.pNext = Root.pPrev = (ValueType*)&Root;
  19.139     }
  19.140 
  19.141     const ValueType* GetFirst() const { return (const ValueType*)Root.pNext; }
  19.142     const ValueType* GetLast () const { return (const ValueType*)Root.pPrev; }
  19.143           ValueType* GetFirst()       { return (ValueType*)Root.pNext; }
  19.144           ValueType* GetLast ()       { return (ValueType*)Root.pPrev; }
  19.145 
  19.146     // Determine if list is empty (i.e.) points to itself.
  19.147     // Go through void* access to avoid issues with strict-aliasing optimizing out the
  19.148     // access after RemoveNode(), etc.
  19.149     bool IsEmpty()                   const { return Root.pVoidNext == (const T*)(const B*)&Root; }
  19.150     bool IsFirst(const ValueType* p) const { return p == Root.pNext; }
  19.151     bool IsLast (const ValueType* p) const { return p == Root.pPrev; }
  19.152     bool IsNull (const ValueType* p) const { return p == (const T*)(const B*)&Root; }
  19.153 
  19.154     inline static const ValueType* GetPrev(const ValueType* p) { return (const ValueType*)p->pPrev; }
  19.155     inline static const ValueType* GetNext(const ValueType* p) { return (const ValueType*)p->pNext; }
  19.156     inline static       ValueType* GetPrev(      ValueType* p) { return (ValueType*)p->pPrev; }
  19.157     inline static       ValueType* GetNext(      ValueType* p) { return (ValueType*)p->pNext; }
  19.158 
  19.159     void PushFront(ValueType* p)
  19.160     {
  19.161         p->pNext          =  Root.pNext;
  19.162         p->pPrev          = (ValueType*)&Root;
  19.163         Root.pNext->pPrev =  p;
  19.164         Root.pNext        =  p;
  19.165     }
  19.166 
  19.167     void PushBack(ValueType* p)
  19.168     {
  19.169         p->pPrev          =  Root.pPrev;
  19.170         p->pNext          = (ValueType*)&Root;
  19.171         Root.pPrev->pNext =  p;
  19.172         Root.pPrev        =  p;
  19.173     }
  19.174 
  19.175     static void Remove(ValueType* p)
  19.176     {
  19.177         p->pPrev->pNext = p->pNext;
  19.178         p->pNext->pPrev = p->pPrev;
  19.179     }
  19.180 
  19.181     void BringToFront(ValueType* p)
  19.182     {
  19.183         Remove(p);
  19.184         PushFront(p);
  19.185     }
  19.186 
  19.187     void SendToBack(ValueType* p)
  19.188     {
  19.189         Remove(p);
  19.190         PushBack(p);
  19.191     }
  19.192 
  19.193     // Appends the contents of the argument list to the front of this list;
  19.194     // items are removed from the argument list.
  19.195     void PushListToFront(List<T>& src)
  19.196     {
  19.197         if (!src.IsEmpty())
  19.198         {
  19.199             ValueType* pfirst = src.GetFirst();
  19.200             ValueType* plast  = src.GetLast();
  19.201             src.Clear();
  19.202             plast->pNext   = Root.pNext;
  19.203             pfirst->pPrev  = (ValueType*)&Root;
  19.204             Root.pNext->pPrev = plast;
  19.205             Root.pNext        = pfirst;
  19.206         }
  19.207     }
  19.208 
  19.209     void PushListToBack(List<T>& src)
  19.210     {
  19.211         if (!src.IsEmpty())
  19.212         {
  19.213             ValueType* pfirst = src.GetFirst();
  19.214             ValueType* plast  = src.GetLast();
  19.215             src.Clear();
  19.216             plast->pNext   = (ValueType*)&Root;
  19.217             pfirst->pPrev  = Root.pPrev;
  19.218             Root.pPrev->pNext = pfirst;
  19.219             Root.pPrev        = plast;
  19.220         }
  19.221     }
  19.222 
  19.223     // Removes all source list items after (and including) the 'pfirst' node from the 
  19.224     // source list and adds them to out list.
  19.225     void    PushFollowingListItemsToFront(List<T>& src, ValueType *pfirst)
  19.226     {
  19.227         if (pfirst != &src.Root)
  19.228         {
  19.229             ValueType *plast = src.Root.pPrev;
  19.230 
  19.231             // Remove list remainder from source.
  19.232             pfirst->pPrev->pNext = (ValueType*)&src.Root;
  19.233             src.Root.pPrev      = pfirst->pPrev;
  19.234             // Add the rest of the items to list.
  19.235             plast->pNext      = Root.pNext;
  19.236             pfirst->pPrev     = (ValueType*)&Root;
  19.237             Root.pNext->pPrev = plast;
  19.238             Root.pNext        = pfirst;
  19.239         }
  19.240     }
  19.241 
  19.242     // Removes all source list items up to but NOT including the 'pend' node from the 
  19.243     // source list and adds them to out list.
  19.244     void    PushPrecedingListItemsToFront(List<T>& src, ValueType *ptail)
  19.245     {
  19.246         if (src.GetFirst() != ptail)
  19.247         {
  19.248             ValueType *pfirst = src.Root.pNext;
  19.249             ValueType *plast  = ptail->pPrev;
  19.250 
  19.251             // Remove list remainder from source.
  19.252             ptail->pPrev      = (ValueType*)&src.Root;
  19.253             src.Root.pNext    = ptail;            
  19.254 
  19.255             // Add the rest of the items to list.
  19.256             plast->pNext      = Root.pNext;
  19.257             pfirst->pPrev     = (ValueType*)&Root;
  19.258             Root.pNext->pPrev = plast;
  19.259             Root.pNext        = pfirst;
  19.260         }
  19.261     }
  19.262 
  19.263 
  19.264     // Removes a range of source list items starting at 'pfirst' and up to, but not including 'pend',
  19.265     // and adds them to out list. Note that source items MUST already be in the list.
  19.266     void    PushListItemsToFront(ValueType *pfirst, ValueType *pend)
  19.267     {
  19.268         if (pfirst != pend)
  19.269         {
  19.270             ValueType *plast = pend->pPrev;
  19.271 
  19.272             // Remove list remainder from source.
  19.273             pfirst->pPrev->pNext = pend;
  19.274             pend->pPrev          = pfirst->pPrev;
  19.275             // Add the rest of the items to list.
  19.276             plast->pNext      = Root.pNext;
  19.277             pfirst->pPrev     = (ValueType*)&Root;
  19.278             Root.pNext->pPrev = plast;
  19.279             Root.pNext        = pfirst;
  19.280         }
  19.281     }
  19.282 
  19.283 
  19.284     void    Alloc_MoveTo(List<T>* pdest)
  19.285     {
  19.286         if (IsEmpty())
  19.287             pdest->Clear();
  19.288         else
  19.289         {
  19.290             pdest->Root.pNext = Root.pNext;
  19.291             pdest->Root.pPrev = Root.pPrev;
  19.292 
  19.293             Root.pNext->pPrev = (ValueType*)&pdest->Root;
  19.294             Root.pPrev->pNext = (ValueType*)&pdest->Root;
  19.295         }        
  19.296     }
  19.297 
  19.298 
  19.299 private:
  19.300     // Copying is prohibited
  19.301     List(const List<T>&);
  19.302     const List<T>& operator = (const List<T>&);
  19.303 
  19.304     ListNode<B> Root;
  19.305 };
  19.306 
  19.307 
  19.308 //------------------------------------------------------------------------
  19.309 // ***** FreeListElements
  19.310 //
  19.311 // Remove all elements in the list and free them in the allocator
  19.312 
  19.313 template<class List, class Allocator>
  19.314 void FreeListElements(List& list, Allocator& allocator)
  19.315 {
  19.316     typename List::ValueType* self = list.GetFirst();
  19.317     while(!list.IsNull(self))
  19.318     {
  19.319         typename List::ValueType* next = list.GetNext(self);
  19.320         allocator.Free(self);
  19.321         self = next;
  19.322     }
  19.323     list.Clear();
  19.324 }
  19.325 
  19.326 } // OVR
  19.327 
  19.328 #endif
  19.329 \ No newline at end of file
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/libovr/Src/Kernel/OVR_Log.cpp	Sat Sep 14 16:14:59 2013 +0300
    20.3 @@ -0,0 +1,1 @@
    20.4 +/************************************************************************************
    20.5 
    20.6 Filename    :   OVR_Log.cpp
    20.7 Content     :   Logging support
    20.8 Created     :   September 19, 2012
    20.9 Notes       : 
   20.10 
   20.11 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   20.12 
   20.13 Use of this software is subject to the terms of the Oculus license
   20.14 agreement provided at the time of installation or download, or which
   20.15 otherwise accompanies this software in either electronic or hard copy form.
   20.16 
   20.17 ************************************************************************************/
   20.18 
   20.19 #include "OVR_Log.h"
   20.20 #include "OVR_Std.h"
   20.21 #include <stdarg.h>
   20.22 #include <stdio.h>
   20.23 
   20.24 #if defined(OVR_OS_WIN32)
   20.25 #include <windows.h>
   20.26 #elif defined(OVR_OS_ANDROID)
   20.27 #include <android/log.h>
   20.28 #endif
   20.29 
   20.30 namespace OVR {
   20.31 
   20.32 // Global Log pointer.
   20.33 Log* volatile OVR_GlobalLog = 0;
   20.34 
   20.35 //-----------------------------------------------------------------------------------
   20.36 // ***** Log Implementation
   20.37 
   20.38 Log::~Log()
   20.39 {
   20.40     // Clear out global log
   20.41     if (this == OVR_GlobalLog)
   20.42     {
   20.43         // TBD: perhaps we should ASSERT if this happens before system shutdown?
   20.44         OVR_GlobalLog = 0;
   20.45     }
   20.46 }
   20.47 
   20.48 void Log::LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList)
   20.49 {
   20.50     if ((messageType & LoggingMask) == 0)
   20.51         return;
   20.52 #ifndef OVR_BUILD_DEBUG
   20.53     if (IsDebugMessage(messageType))
   20.54         return;
   20.55 #endif
   20.56 
   20.57     char buffer[MaxLogBufferMessageSize];
   20.58     FormatLog(buffer, MaxLogBufferMessageSize, messageType, fmt, argList);
   20.59     DefaultLogOutput(buffer, IsDebugMessage(messageType));
   20.60 }
   20.61 
   20.62 void OVR::Log::LogMessage(LogMessageType messageType, const char* pfmt, ...)
   20.63 {
   20.64     va_list argList;
   20.65     va_start(argList, pfmt);
   20.66     LogMessageVarg(messageType, pfmt, argList);
   20.67     va_end(argList);
   20.68 }
   20.69 
   20.70 
   20.71 void Log::FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType,
   20.72                     const char* fmt, va_list argList)
   20.73 {    
   20.74     bool addNewline = true;
   20.75 
   20.76     switch(messageType)
   20.77     {
   20.78     case Log_Error:         OVR_strcpy(buffer, bufferSize, "Error: ");     break;
   20.79     case Log_Debug:         OVR_strcpy(buffer, bufferSize, "Debug: ");     break;
   20.80     case Log_Assert:        OVR_strcpy(buffer, bufferSize, "Assert: ");    break;
   20.81     case Log_Text:       buffer[0] = 0; addNewline = false; break;
   20.82     case Log_DebugText:  buffer[0] = 0; addNewline = false; break;
   20.83     default:        
   20.84         buffer[0] = 0;
   20.85         addNewline = false;
   20.86         break;
   20.87     }
   20.88 
   20.89     UPInt prefixLength = OVR_strlen(buffer);
   20.90     char *buffer2      = buffer + prefixLength;
   20.91     OVR_vsprintf(buffer2, bufferSize - prefixLength, fmt, argList);
   20.92 
   20.93     if (addNewline)
   20.94         OVR_strcat(buffer, bufferSize, "\n");
   20.95 }
   20.96 
   20.97 
   20.98 void Log::DefaultLogOutput(const char* formattedText, bool debug)
   20.99 {
  20.100 
  20.101 #if defined(OVR_OS_WIN32)
  20.102     // Under Win32, output regular messages to console if it exists; debug window otherwise.
  20.103     static DWORD dummyMode;
  20.104     static bool  hasConsole = (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE) &&
  20.105                               (GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &dummyMode));
  20.106 
  20.107     if (!hasConsole || debug)
  20.108     {
  20.109         ::OutputDebugStringA(formattedText);
  20.110     }
  20.111     else
  20.112     {
  20.113          fputs(formattedText, stdout);
  20.114     }    
  20.115 
  20.116 #elif defined(OVR_OS_ANDROID)
  20.117     __android_log_write(ANDROID_LOG_INFO, "OVR", formattedText);
  20.118 
  20.119 #else
  20.120     fputs(formattedText, stdout);
  20.121 
  20.122 #endif
  20.123 
  20.124     // Just in case.
  20.125     OVR_UNUSED2(formattedText, debug);
  20.126 }
  20.127 
  20.128 
  20.129 //static
  20.130 void Log::SetGlobalLog(Log *log)
  20.131 {
  20.132     OVR_GlobalLog = log;
  20.133 }
  20.134 //static
  20.135 Log* Log::GetGlobalLog()
  20.136 {
  20.137 // No global log by default?
  20.138 //    if (!OVR_GlobalLog)
  20.139 //        OVR_GlobalLog = GetDefaultLog();
  20.140     return OVR_GlobalLog;
  20.141 }
  20.142 
  20.143 //static
  20.144 Log* Log::GetDefaultLog()
  20.145 {
  20.146     // Create default log pointer statically so that it can be used
  20.147     // even during startup.
  20.148     static Log defaultLog;
  20.149     return &defaultLog;
  20.150 }
  20.151 
  20.152 
  20.153 //-----------------------------------------------------------------------------------
  20.154 // ***** Global Logging functions
  20.155 
  20.156 #define OVR_LOG_FUNCTION_IMPL(Name)  \
  20.157     void Log##Name(const char* fmt, ...) \
  20.158     {                                                                    \
  20.159         if (OVR_GlobalLog)                                               \
  20.160         {                                                                \
  20.161             va_list argList; va_start(argList, fmt);                     \
  20.162             OVR_GlobalLog->LogMessageVarg(Log_##Name, fmt, argList);  \
  20.163             va_end(argList);                                             \
  20.164         }                                                                \
  20.165     }
  20.166 
  20.167 OVR_LOG_FUNCTION_IMPL(Text)
  20.168 OVR_LOG_FUNCTION_IMPL(Error)
  20.169 
  20.170 #ifdef OVR_BUILD_DEBUG
  20.171 OVR_LOG_FUNCTION_IMPL(DebugText)
  20.172 OVR_LOG_FUNCTION_IMPL(Debug)
  20.173 OVR_LOG_FUNCTION_IMPL(Assert)
  20.174 #endif
  20.175 
  20.176 } // OVR
  20.177 \ No newline at end of file
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/libovr/Src/Kernel/OVR_Log.h	Sat Sep 14 16:14:59 2013 +0300
    21.3 @@ -0,0 +1,1 @@
    21.4 +/************************************************************************************
    21.5 
    21.6 PublicHeader:   OVR
    21.7 Filename    :   OVR_Log.h
    21.8 Content     :   Logging support
    21.9 Created     :   September 19, 2012
   21.10 Notes       : 
   21.11 
   21.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   21.13 
   21.14 Use of this software is subject to the terms of the Oculus license
   21.15 agreement provided at the time of installation or download, or which
   21.16 otherwise accompanies this software in either electronic or hard copy form.
   21.17 
   21.18 ************************************************************************************/
   21.19 
   21.20 #ifndef OVR_Log_h
   21.21 #define OVR_Log_h
   21.22 
   21.23 #include "OVR_Types.h"
   21.24 #include <stdarg.h>
   21.25 
   21.26 namespace OVR {
   21.27 
   21.28 //-----------------------------------------------------------------------------------
   21.29 // ***** Logging Constants
   21.30 
   21.31 // LogMaskConstants defined bit mask constants that describe what log messages
   21.32 // should be displayed.
   21.33 enum LogMaskConstants
   21.34 {
   21.35     LogMask_Regular = 0x100,
   21.36     LogMask_Debug   = 0x200,
   21.37     LogMask_None    = 0,
   21.38     LogMask_All     = LogMask_Regular|LogMask_Debug
   21.39 };
   21.40 
   21.41 
   21.42 // LogMessageType describes the type of the log message, controls when it is
   21.43 // displayed and what prefix/suffix is given to it. Messages are subdivided into
   21.44 // regular and debug logging types. Debug logging is only generated in debug builds.
   21.45 //
   21.46 // Log_Text         - General output text displayed without prefix or new-line.
   21.47 //                    Used in OVR libraries for general log flow messages
   21.48 //                    such as "Device Initialized".
   21.49 //
   21.50 // Log_Error        - Error message output with "Error: %s\n", intended for
   21.51 //                    application/sample-level use only, in cases where an expected
   21.52 //                    operation failed. OVR libraries should not use this internally,
   21.53 //                    reporting status codes instead.
   21.54 //
   21.55 // Log_DebugText    - Message without prefix or new lines; output in Debug build only.
   21.56 //
   21.57 // Log_Debug        - Debug-build only message, formatted with "Debug: %s\n".
   21.58 //                    Intended to comment on incorrect API usage that doesn't lead
   21.59 //                    to crashes but can be avoided with proper use.
   21.60 //                    There is no Debug Error on purpose, since real errors should
   21.61 //                    be handled by API user.
   21.62 //
   21.63 // Log_Assert      -  Debug-build only message, formatted with "Assert: %s\n".
   21.64 //                    Intended for severe unrecoverable conditions in library
   21.65 //                    source code. Generated though OVR_ASSERT_MSG(c, "Text").
   21.66 
   21.67 enum LogMessageType
   21.68 {    
   21.69     // General Logging
   21.70     Log_Text        = LogMask_Regular | 0,    
   21.71     Log_Error       = LogMask_Regular | 1, // "Error: %s\n".
   21.72     
   21.73     // Debug-only messages (not generated in release build)
   21.74     Log_DebugText   = LogMask_Debug | 0,
   21.75     Log_Debug       = LogMask_Debug | 1,   // "Debug: %s\n".
   21.76     Log_Assert      = LogMask_Debug | 2,   // "Assert: %s\n".
   21.77 };
   21.78 
   21.79 
   21.80 // LOG_VAARG_ATTRIBUTE macro, enforces printf-style fromatting for message types
   21.81 #ifdef __GNUC__
   21.82 #  define OVR_LOG_VAARG_ATTRIBUTE(a,b) __attribute__((format (printf, a, b)))
   21.83 #else
   21.84 #  define OVR_LOG_VAARG_ATTRIBUTE(a,b)
   21.85 #endif
   21.86 
   21.87 
   21.88 //-----------------------------------------------------------------------------------
   21.89 // ***** Log
   21.90 
   21.91 // Log defines a base class interface that can be implemented to catch both
   21.92 // debug and runtime messages.
   21.93 // Debug logging can be overridden by calling Log::SetGlobalLog.
   21.94 
   21.95 class Log
   21.96 {
   21.97     friend class System;
   21.98 public: 
   21.99     Log(unsigned logMask = LogMask_Debug) : LoggingMask(logMask) { }
  21.100     virtual ~Log();
  21.101 
  21.102     // Log formating buffer size used by default LogMessageVarg. Longer strings are truncated.
  21.103     enum { MaxLogBufferMessageSize = 2048 };
  21.104 
  21.105     unsigned        GetLoggingMask() const            { return LoggingMask; }
  21.106     void            SetLoggingMask(unsigned logMask)  { LoggingMask = logMask; }
  21.107 
  21.108     // This virtual function receives all the messages,
  21.109     // developers should override this function in order to do custom logging
  21.110     virtual void    LogMessageVarg(LogMessageType messageType, const char* fmt, va_list argList);
  21.111 
  21.112     // Call the logging function with specific message type, with no type filtering.
  21.113     void            LogMessage(LogMessageType messageType,
  21.114                                const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(3,4);
  21.115 
  21.116 
  21.117     // Helper used by LogMessageVarg to format the log message, writing the resulting
  21.118     // string into buffer. It formats text based on fmt and appends prefix/new line
  21.119     // based on LogMessageType.
  21.120     static void     FormatLog(char* buffer, unsigned bufferSize, LogMessageType messageType,
  21.121                               const char* fmt, va_list argList);
  21.122 
  21.123     // Default log output implementation used by by LogMessageVarg.
  21.124     // Debug flag may be used to re-direct output on some platforms, but doesn't
  21.125     // necessarily disable it in release builds; that is the job of the called.    
  21.126     static void     DefaultLogOutput(const char* textBuffer, bool debug);
  21.127 
  21.128     // Determines if the specified message type is for debugging only.
  21.129     static bool     IsDebugMessage(LogMessageType messageType)
  21.130     {
  21.131         return (messageType & LogMask_Debug) != 0;
  21.132     }
  21.133 
  21.134     // *** Global APIs
  21.135 
  21.136     // Global Log registration APIs.
  21.137     //  - Global log is used for OVR_DEBUG messages. Set global log to null (0)
  21.138     //    to disable all logging.
  21.139     static void     SetGlobalLog(Log *log);
  21.140     static Log*     GetGlobalLog();
  21.141 
  21.142     // Returns default log singleton instance.
  21.143     static Log*     GetDefaultLog();
  21.144 
  21.145     // Applies logMask to the default log and returns a pointer to it.
  21.146     // By default, only Debug logging is enabled, so to avoid SDK generating console
  21.147     // messages in user app (those are always disabled in release build,
  21.148     // even if the flag is set). This function is useful in System constructor.
  21.149     static Log*     ConfigureDefaultLog(unsigned logMask = LogMask_Debug)
  21.150     {
  21.151         Log* log = GetDefaultLog();
  21.152         log->SetLoggingMask(logMask);
  21.153         return log;
  21.154     }
  21.155 
  21.156 private:
  21.157     // Logging mask described by LogMaskConstants.
  21.158     unsigned    LoggingMask;
  21.159 };
  21.160 
  21.161 
  21.162 //-----------------------------------------------------------------------------------
  21.163 // ***** Global Logging Functions and Debug Macros
  21.164 
  21.165 // These functions will output text to global log with semantics described by
  21.166 // their LogMessageType.
  21.167 void LogText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  21.168 void LogError(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  21.169 
  21.170 #ifdef OVR_BUILD_DEBUG
  21.171 
  21.172     // Debug build only logging.
  21.173     void LogDebugText(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  21.174     void LogDebug(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  21.175     void LogAssert(const char* fmt, ...) OVR_LOG_VAARG_ATTRIBUTE(1,2);
  21.176 
  21.177     // Macro to do debug logging, printf-style.
  21.178     // An extra set of set of parenthesis must be used around arguments,
  21.179     // as in: OVR_LOG_DEBUG(("Value %d", 2)).
  21.180     #define OVR_DEBUG_LOG(args)       do { OVR::LogDebug args; } while(0)
  21.181     #define OVR_DEBUG_LOG_TEXT(args)  do { OVR::LogDebugText args; } while(0)
  21.182 
  21.183     #define OVR_ASSERT_LOG(c, args)   do { if (!(c)) { OVR::LogAssert args; OVR_DEBUG_BREAK; } } while(0)
  21.184 
  21.185 #else
  21.186 
  21.187     // If not in debug build, macros do nothing.
  21.188     #define OVR_DEBUG_LOG(args)         ((void)0)
  21.189     #define OVR_DEBUG_LOG_TEXT(args)    ((void)0)
  21.190     #define OVR_ASSERT_LOG(c, args)     ((void)0)
  21.191 
  21.192 #endif
  21.193 
  21.194 } // OVR 
  21.195 
  21.196 #endif
  21.197 \ No newline at end of file
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/libovr/Src/Kernel/OVR_Math.cpp	Sat Sep 14 16:14:59 2013 +0300
    22.3 @@ -0,0 +1,1 @@
    22.4 +/************************************************************************************
    22.5 
    22.6 Filename    :   OVR_Math.h
    22.7 Content     :   Implementation of 3D primitives such as vectors, matrices.
    22.8 Created     :   September 4, 2012
    22.9 Authors     :   Andrew Reisse, Michael Antonov
   22.10 
   22.11 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   22.12 
   22.13 Use of this software is subject to the terms of the Oculus license
   22.14 agreement provided at the time of installation or download, or which
   22.15 otherwise accompanies this software in either electronic or hard copy form.
   22.16 
   22.17 *************************************************************************************/
   22.18 
   22.19 #include "OVR_Math.h"
   22.20 
   22.21 #include <float.h>
   22.22 
   22.23 namespace OVR {
   22.24 
   22.25 
   22.26 //-------------------------------------------------------------------------------------
   22.27 // ***** Math
   22.28 
   22.29 
   22.30 // Single-precision Math constants class.
   22.31 const float Math<float>::Pi      = 3.1415926f;
   22.32 const float Math<float>::TwoPi   = 3.1415926f * 2;
   22.33 const float Math<float>::PiOver2 = 3.1415926f / 2.0f;
   22.34 const float Math<float>::PiOver4 = 3.1415926f / 4.0f;
   22.35 const float Math<float>::E       = 2.7182818f;
   22.36 
   22.37 const float Math<float>::MaxValue = FLT_MAX;
   22.38 const float Math<float>::MinPositiveValue = FLT_MIN;
   22.39 
   22.40 const float Math<float>::RadToDegreeFactor = 360.0f / Math<float>::TwoPi;
   22.41 const float Math<float>::DegreeToRadFactor = Math<float>::TwoPi / 360.0f;
   22.42 
   22.43 const float Math<float>::Tolerance = 0.00001f;
   22.44 const float Math<float>::SingularityRadius = 0.0000001f; // Use for Gimbal lock numerical problems
   22.45 
   22.46 
   22.47 // Double-precision Math constants class.
   22.48 const double Math<double>::Pi      = 3.14159265358979;
   22.49 const double Math<double>::TwoPi   = 3.14159265358979 * 2;
   22.50 const double Math<double>::PiOver2 = 3.14159265358979 / 2.0;
   22.51 const double Math<double>::PiOver4 = 3.14159265358979 / 4.0;
   22.52 const double Math<double>::E       = 2.71828182845905;
   22.53 
   22.54 const double Math<double>::MaxValue = DBL_MAX;
   22.55 const double Math<double>::MinPositiveValue = DBL_MIN;
   22.56 
   22.57 const double Math<double>::RadToDegreeFactor = 360.0 / Math<double>::TwoPi;
   22.58 const double Math<double>::DegreeToRadFactor = Math<double>::TwoPi / 360.0;
   22.59 
   22.60 const double Math<double>::Tolerance = 0.00001;
   22.61 const double Math<double>::SingularityRadius = 0.000000000001; // Use for Gimbal lock numerical problems
   22.62 
   22.63 
   22.64 
   22.65 //-------------------------------------------------------------------------------------
   22.66 // ***** Matrix4f
   22.67 
   22.68 
   22.69 Matrix4f Matrix4f::LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up)
   22.70 {
   22.71     Vector3f z = (eye - at).Normalized();  // Forward
   22.72     Vector3f x = up.Cross(z).Normalized(); // Right
   22.73     Vector3f y = z.Cross(x);
   22.74 
   22.75     Matrix4f m(x.x,  x.y,  x.z,  -(x * eye),
   22.76                y.x,  y.y,  y.z,  -(y * eye),
   22.77                z.x,  z.y,  z.z,  -(z * eye),
   22.78                0,    0,    0,    1 );
   22.79     return m;
   22.80 }
   22.81 
   22.82 Matrix4f Matrix4f::LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up)
   22.83 {
   22.84     Vector3f z = (at - eye).Normalized();  // Forward
   22.85     Vector3f x = up.Cross(z).Normalized(); // Right
   22.86     Vector3f y = z.Cross(x);
   22.87 
   22.88     Matrix4f m(x.x,  x.y,  x.z,  -(x * eye),
   22.89                y.x,  y.y,  y.z,  -(y * eye),
   22.90                z.x,  z.y,  z.z,  -(z * eye),
   22.91                0,    0,    0,    1 ); 
   22.92     return m;
   22.93 }
   22.94 
   22.95 
   22.96 Matrix4f Matrix4f::PerspectiveLH(float yfov, float aspect, float znear, float zfar)
   22.97 {
   22.98     Matrix4f m;
   22.99     float    tanHalfFov = tan(yfov * 0.5f);
  22.100 
  22.101     m.M[0][0] = 1.0f / (aspect * tanHalfFov);
  22.102     m.M[1][1] = 1.0f / tanHalfFov;
  22.103     m.M[2][2] = zfar / (zfar - znear);
  22.104     m.M[3][2] = 1.0f;
  22.105     m.M[2][3] = (zfar * znear) / (znear - zfar);
  22.106     m.M[3][3] = 0.0f;
  22.107 
  22.108     // Note: Post-projection matrix result assumes Left-Handed coordinate system,
  22.109     //       with Y up, X right and Z forward. This supports positive z-buffer values.
  22.110     return m;
  22.111 }
  22.112 
  22.113 
  22.114 Matrix4f Matrix4f::PerspectiveRH(float yfov, float aspect, float znear, float zfar)
  22.115 {
  22.116     Matrix4f m;
  22.117     float    tanHalfFov = tan(yfov * 0.5f);
  22.118   
  22.119     m.M[0][0] = 1.0f / (aspect * tanHalfFov);
  22.120     m.M[1][1] = 1.0f / tanHalfFov;
  22.121     m.M[2][2] = zfar / (znear - zfar);
  22.122    // m.M[2][2] = zfar / (zfar - znear);
  22.123     m.M[3][2] = -1.0f;
  22.124     m.M[2][3] = (zfar * znear) / (znear - zfar);
  22.125     m.M[3][3] = 0.0f;
  22.126 
  22.127     // Note: Post-projection matrix result assumes Left-Handed coordinate system,    
  22.128     //       with Y up, X right and Z forward. This supports positive z-buffer values.
  22.129     // This is the case even for RHS cooridnate input.       
  22.130     return m;
  22.131 }
  22.132 
  22.133 
  22.134 /*
  22.135 OffCenterLH
  22.136 
  22.137 2*zn/(r-l)   0            0              0
  22.138 0            2*zn/(t-b)   0              0
  22.139 (l+r)/(l-r)  (t+b)/(b-t)  zf/(zf-zn)     1
  22.140 0            0            zn*zf/(zn-zf)  0
  22.141 
  22.142 */
  22.143 
  22.144 
  22.145 Matrix4f Matrix4f::Ortho2D(float w, float h)
  22.146 {
  22.147     Matrix4f m;
  22.148     m.M[0][0] = 2.0f/w;
  22.149     m.M[1][1] = -2.0f/h;
  22.150     m.M[0][3] = -1.0;
  22.151     m.M[1][3] = 1.0;
  22.152     m.M[2][2] = 0;
  22.153     return m;
  22.154 }
  22.155 
  22.156 }
  22.157 \ No newline at end of file
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/libovr/Src/Kernel/OVR_Math.h	Sat Sep 14 16:14:59 2013 +0300
    23.3 @@ -0,0 +1,1 @@
    23.4 +/************************************************************************************
    23.5 
    23.6 PublicHeader:   OVR.h
    23.7 Filename    :   OVR_Math.h
    23.8 Content     :   Implementation of 3D primitives such as vectors, matrices.
    23.9 Created     :   September 4, 2012
   23.10 Authors     :   Andrew Reisse, Michael Antonov, Steve LaValle, Anna Yershova
   23.11 
   23.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   23.13 
   23.14 Use of this software is subject to the terms of the Oculus license
   23.15 agreement provided at the time of installation or download, or which
   23.16 otherwise accompanies this software in either electronic or hard copy form.
   23.17 
   23.18 *************************************************************************************/
   23.19 
   23.20 #ifndef OVR_Math_h
   23.21 #define OVR_Math_h
   23.22 
   23.23 #include <assert.h>
   23.24 #include <stdlib.h>
   23.25 #include <math.h>
   23.26 
   23.27 #include "OVR_Types.h"
   23.28 #include "OVR_RefCount.h"
   23.29 
   23.30 namespace OVR {
   23.31 
   23.32 //-------------------------------------------------------------------------------------
   23.33 // Constants for 3D world/axis definitions.
   23.34 
   23.35 // Definitions of axes for coordinate and rotation conversions.
   23.36 enum Axis
   23.37 {
   23.38     Axis_X = 0, Axis_Y = 1, Axis_Z = 2
   23.39 };
   23.40 
   23.41 // RotateDirection describes the rotation direction around an axis, interpreted as follows:
   23.42 //  CW  - Clockwise while looking "down" from positive axis towards the origin.
   23.43 //  CCW - Counter-clockwise while looking from the positive axis towards the origin,
   23.44 //        which is in the negative axis direction.
   23.45 //  CCW is the default for the RHS coordinate system. Oculus standard RHS coordinate
   23.46 //  system defines Y up, X right, and Z back (pointing out from the screen). In this
   23.47 //  system Rotate_CCW around Z will specifies counter-clockwise rotation in XY plane.
   23.48 enum RotateDirection
   23.49 {
   23.50     Rotate_CCW = 1,
   23.51     Rotate_CW  = -1 
   23.52 };
   23.53 
   23.54 enum HandedSystem
   23.55 {
   23.56     Handed_R = 1, Handed_L = -1
   23.57 };
   23.58 
   23.59 // AxisDirection describes which way the axis points. Used by WorldAxes.
   23.60 enum AxisDirection
   23.61 {
   23.62     Axis_Up    =  2,
   23.63     Axis_Down  = -2,
   23.64     Axis_Right =  1,
   23.65     Axis_Left  = -1,
   23.66     Axis_In    =  3,
   23.67     Axis_Out   = -3
   23.68 };
   23.69 
   23.70 struct WorldAxes
   23.71 {
   23.72     AxisDirection XAxis, YAxis, ZAxis;
   23.73 
   23.74     WorldAxes(AxisDirection x, AxisDirection y, AxisDirection z)
   23.75         : XAxis(x), YAxis(y), ZAxis(z) 
   23.76     { OVR_ASSERT(abs(x) != abs(y) && abs(y) != abs(z) && abs(z) != abs(x));}
   23.77 };
   23.78 
   23.79 
   23.80 //-------------------------------------------------------------------------------------
   23.81 // ***** Math
   23.82 
   23.83 // Math class contains constants and functions. This class is a template specialized
   23.84 // per type, with Math<float> and Math<double> being distinct.
   23.85 template<class Type>
   23.86 class Math
   23.87 {  
   23.88 };
   23.89 
   23.90 // Single-precision Math constants class.
   23.91 template<>
   23.92 class Math<float>
   23.93 {
   23.94 public:
   23.95     static const float Pi;
   23.96     static const float TwoPi;
   23.97     static const float PiOver2;
   23.98     static const float PiOver4;
   23.99     static const float E;
  23.100 
  23.101     static const float MaxValue;          // Largest positive float Value
  23.102     static const float MinPositiveValue;  // Smallest possible positive value
  23.103 
  23.104     static const float RadToDegreeFactor;
  23.105     static const float DegreeToRadFactor;
  23.106 
  23.107     static const float Tolerance; //  0.00001f;
  23.108     static const float SingularityRadius; //0.00000000001f for Gimbal lock numerical problems
  23.109 };
  23.110 
  23.111 // Double-precision Math constants class.
  23.112 template<>
  23.113 class Math<double>
  23.114 {
  23.115 public:
  23.116     static const double Pi;
  23.117     static const double TwoPi;
  23.118     static const double PiOver2;
  23.119     static const double PiOver4;
  23.120     static const double E;
  23.121 
  23.122     static const double MaxValue;          // Largest positive double Value
  23.123     static const double MinPositiveValue;  // Smallest possible positive value
  23.124 
  23.125     static const double RadToDegreeFactor;
  23.126     static const double DegreeToRadFactor;
  23.127 
  23.128     static const double Tolerance; //  0.00001f;
  23.129     static const double SingularityRadius; //0.00000000001 for Gimbal lock numerical problems
  23.130 };
  23.131 
  23.132 typedef Math<float>  Mathf;
  23.133 typedef Math<double> Mathd;
  23.134 
  23.135 // Conversion functions between degrees and radians
  23.136 template<class FT>
  23.137 FT RadToDegree(FT rads) { return rads * Math<FT>::RadToDegreeFactor; }
  23.138 template<class FT>
  23.139 FT DegreeToRad(FT rads) { return rads * Math<FT>::DegreeToRadFactor; }
  23.140 
  23.141 template<class T>
  23.142 class Quat;
  23.143 
  23.144 //-------------------------------------------------------------------------------------
  23.145 // ***** Vector2f - 2D Vector2f
  23.146 
  23.147 // Vector2f represents a 2-dimensional vector or point in space,
  23.148 // consisting of coordinates x and y,
  23.149 
  23.150 template<class T>
  23.151 class Vector2
  23.152 {
  23.153 public:
  23.154     T x, y;
  23.155 
  23.156     Vector2() : x(0), y(0) { }
  23.157     Vector2(T x_, T y_) : x(x_), y(y_) { }
  23.158     explicit Vector2(T s) : x(s), y(s) { }
  23.159 
  23.160     bool     operator== (const Vector2& b) const  { return x == b.x && y == b.y; }
  23.161     bool     operator!= (const Vector2& b) const  { return x != b.x || y != b.y; }
  23.162              
  23.163     Vector2  operator+  (const Vector2& b) const  { return Vector2(x + b.x, y + b.y); }
  23.164     Vector2& operator+= (const Vector2& b)        { x += b.x; y += b.y; return *this; }
  23.165     Vector2  operator-  (const Vector2& b) const  { return Vector2(x - b.x, y - b.y); }
  23.166     Vector2& operator-= (const Vector2& b)        { x -= b.x; y -= b.y; return *this; }
  23.167     Vector2  operator- () const                   { return Vector2(-x, -y); }
  23.168 
  23.169     // Scalar multiplication/division scales vector.
  23.170     Vector2  operator*  (T s) const               { return Vector2(x*s, y*s); }
  23.171     Vector2& operator*= (T s)                     { x *= s; y *= s; return *this; }
  23.172 
  23.173     Vector2  operator/  (T s) const               { T rcp = T(1)/s;
  23.174                                                     return Vector2(x*rcp, y*rcp); }
  23.175     Vector2& operator/= (T s)                     { T rcp = T(1)/s;
  23.176                                                     x *= rcp; y *= rcp;
  23.177                                                     return *this; }
  23.178 
  23.179     // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
  23.180     bool      Compare(const Vector2&b, T tolerance = Mathf::Tolerance)
  23.181     {
  23.182         return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance);
  23.183     }
  23.184     
  23.185     // Dot product overload.
  23.186     // Used to calculate angle q between two vectors among other things,
  23.187     // as (A dot B) = |a||b|cos(q).
  23.188     T     operator*  (const Vector2& b) const    { return x*b.x + y*b.y; }
  23.189 
  23.190     // Returns the angle from this vector to b, in radians.
  23.191     T       Angle(const Vector2& b) const        { return acos((*this * b)/(Length()*b.Length())); }
  23.192 
  23.193     // Return Length of the vector squared.
  23.194     T       LengthSq() const                     { return (x * x + y * y); }
  23.195     // Return vector length.
  23.196     T       Length() const                       { return sqrt(LengthSq()); }
  23.197 
  23.198     // Returns distance between two points represented by vectors.
  23.199     T       Distance(Vector2& b) const           { return (*this - b).Length(); }
  23.200     
  23.201     // Determine if this a unit vector.
  23.202     bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
  23.203     // Normalize, convention vector length to 1.    
  23.204     void    Normalize()                          { *this /= Length(); }
  23.205     // Returns normalized (unit) version of the vector without modifying itself.
  23.206     Vector2 Normalized() const                   { return *this / Length(); }
  23.207 
  23.208     // Linearly interpolates from this vector to another.
  23.209     // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
  23.210     Vector2 Lerp(const Vector2& b, T f) const    { return *this*(T(1) - f) + b*f; }
  23.211 
  23.212     // Projects this vector onto the argument; in other words,
  23.213     // A.Project(B) returns projection of vector A onto B.
  23.214     Vector2 ProjectTo(const Vector2& b) const    { return b * ((*this * b) / b.LengthSq()); }
  23.215 };
  23.216 
  23.217 
  23.218 typedef Vector2<float>  Vector2f;
  23.219 typedef Vector2<double> Vector2d;
  23.220 
  23.221 //-------------------------------------------------------------------------------------
  23.222 // ***** Vector3f - 3D Vector3f
  23.223 
  23.224 // Vector3f represents a 3-dimensional vector or point in space,
  23.225 // consisting of coordinates x, y and z.
  23.226 
  23.227 template<class T>
  23.228 class Vector3
  23.229 {
  23.230 public:
  23.231     T x, y, z;
  23.232 
  23.233     Vector3() : x(0), y(0), z(0) { }
  23.234     Vector3(T x_, T y_, T z_ = 0) : x(x_), y(y_), z(z_) { }
  23.235     explicit Vector3(T s) : x(s), y(s), z(s) { }
  23.236 
  23.237     bool     operator== (const Vector3& b) const  { return x == b.x && y == b.y && z == b.z; }
  23.238     bool     operator!= (const Vector3& b) const  { return x != b.x || y != b.y || z != b.z; }
  23.239              
  23.240     Vector3  operator+  (const Vector3& b) const  { return Vector3(x + b.x, y + b.y, z + b.z); }
  23.241     Vector3& operator+= (const Vector3& b)        { x += b.x; y += b.y; z += b.z; return *this; }
  23.242     Vector3  operator-  (const Vector3& b) const  { return Vector3(x - b.x, y - b.y, z - b.z); }
  23.243     Vector3& operator-= (const Vector3& b)        { x -= b.x; y -= b.y; z -= b.z; return *this; }
  23.244     Vector3  operator- () const                   { return Vector3(-x, -y, -z); }
  23.245 
  23.246     // Scalar multiplication/division scales vector.
  23.247     Vector3  operator*  (T s) const               { return Vector3(x*s, y*s, z*s); }
  23.248     Vector3& operator*= (T s)                     { x *= s; y *= s; z *= s; return *this; }
  23.249 
  23.250     Vector3  operator/  (T s) const               { T rcp = T(1)/s;
  23.251                                                     return Vector3(x*rcp, y*rcp, z*rcp); }
  23.252     Vector3& operator/= (T s)                     { T rcp = T(1)/s;
  23.253                                                     x *= rcp; y *= rcp; z *= rcp;
  23.254                                                     return *this; }
  23.255 
  23.256     // Compare two vectors for equality with tolerance. Returns true if vectors match withing tolerance.
  23.257     bool      Compare(const Vector3&b, T tolerance = Mathf::Tolerance)
  23.258     {
  23.259         return (fabs(b.x-x) < tolerance) && (fabs(b.y-y) < tolerance) && (fabs(b.z-z) < tolerance);
  23.260     }
  23.261     
  23.262     // Dot product overload.
  23.263     // Used to calculate angle q between two vectors among other things,
  23.264     // as (A dot B) = |a||b|cos(q).
  23.265     T     operator*  (const Vector3& b) const    { return x*b.x + y*b.y + z*b.z; }
  23.266 
  23.267     // Compute cross product, which generates a normal vector.
  23.268     // Direction vector can be determined by right-hand rule: Pointing index finder in
  23.269     // direction a and middle finger in direction b, thumb will point in a.Cross(b).
  23.270     Vector3 Cross(const Vector3& b) const        { return Vector3(y*b.z - z*b.y,
  23.271                                                                   z*b.x - x*b.z,
  23.272                                                                   x*b.y - y*b.x); }
  23.273 
  23.274     // Returns the angle from this vector to b, in radians.
  23.275     T       Angle(const Vector3& b) const        { return acos((*this * b)/(Length()*b.Length())); }
  23.276 
  23.277     // Return Length of the vector squared.
  23.278     T       LengthSq() const                     { return (x * x + y * y + z * z); }
  23.279     // Return vector length.
  23.280     T       Length() const                       { return sqrt(LengthSq()); }
  23.281 
  23.282     // Returns distance between two points represented by vectors.
  23.283     T       Distance(Vector3& b) const           { return (*this - b).Length(); }
  23.284     
  23.285     // Determine if this a unit vector.
  23.286     bool    IsNormalized() const                 { return fabs(LengthSq() - T(1)) < Math<T>::Tolerance; }
  23.287     // Normalize, convention vector length to 1.    
  23.288     void    Normalize()                          { *this /= Length(); }
  23.289     // Returns normalized (unit) version of the vector without modifying itself.
  23.290     Vector3 Normalized() const                   { return *this / Length(); }
  23.291 
  23.292     // Linearly interpolates from this vector to another.
  23.293     // Factor should be between 0.0 and 1.0, with 0 giving full value to this.
  23.294     Vector3 Lerp(const Vector3& b, T f) const    { return *this*(T(1) - f) + b*f; }
  23.295 
  23.296     // Projects this vector onto the argument; in other words,
  23.297     // A.Project(B) returns projection of vector A onto B.
  23.298     Vector3 ProjectTo(const Vector3& b) const    { return b * ((*this * b) / b.LengthSq()); }
  23.299 };
  23.300 
  23.301 
  23.302 typedef Vector3<float>  Vector3f;
  23.303 typedef Vector3<double> Vector3d;
  23.304 
  23.305 
  23.306 //-------------------------------------------------------------------------------------
  23.307 // ***** Matrix4f 
  23.308 
  23.309 // Matrix4f is a 4x4 matrix used for 3d transformations and projections.
  23.310 // Translation stored in the last column.
  23.311 // The matrix is stored in row-major order in memory, meaning that values
  23.312 // of the first row are stored before the next one.
  23.313 //
  23.314 // The arrangement of the matrix is chosen to be in Right-Handed 
  23.315 // coordinate system and counterclockwise rotations when looking down
  23.316 // the axis
  23.317 //
  23.318 // Transformation Order:
  23.319 //   - Transformations are applied from right to left, so the expression
  23.320 //     M1 * M2 * M3 * V means that the vector V is transformed by M3 first,
  23.321 //     followed by M2 and M1. 
  23.322 //
  23.323 // Coordinate system: Right Handed
  23.324 //
  23.325 // Rotations: Counterclockwise when looking down the axis. All angles are in radians.
  23.326 //    
  23.327 //  | sx   01   02   tx |    // First column  (sx, 10, 20): Axis X basis vector.
  23.328 //  | 10   sy   12   ty |    // Second column (01, sy, 21): Axis Y basis vector.
  23.329 //  | 20   21   sz   tz |    // Third columnt (02, 12, sz): Axis Z basis vector.
  23.330 //  | 30   31   32   33 |
  23.331 //
  23.332 //  The basis vectors are first three columns.
  23.333 
  23.334 class Matrix4f
  23.335 {
  23.336     static Matrix4f IdentityValue;
  23.337 
  23.338 public:
  23.339     float M[4][4];    
  23.340 
  23.341     enum NoInitType { NoInit };
  23.342 
  23.343     // Construct with no memory initialization.
  23.344     Matrix4f(NoInitType) { }
  23.345 
  23.346     // By default, we construct identity matrix.
  23.347     Matrix4f()
  23.348     {
  23.349         SetIdentity();        
  23.350     }
  23.351 
  23.352     Matrix4f(float m11, float m12, float m13, float m14,
  23.353              float m21, float m22, float m23, float m24,
  23.354              float m31, float m32, float m33, float m34,
  23.355              float m41, float m42, float m43, float m44)
  23.356     {
  23.357         M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = m14;
  23.358         M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = m24;
  23.359         M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = m34;
  23.360         M[3][0] = m41; M[3][1] = m42; M[3][2] = m43; M[3][3] = m44;
  23.361     }
  23.362 
  23.363     Matrix4f(float m11, float m12, float m13,
  23.364              float m21, float m22, float m23,
  23.365              float m31, float m32, float m33)
  23.366     {
  23.367         M[0][0] = m11; M[0][1] = m12; M[0][2] = m13; M[0][3] = 0;
  23.368         M[1][0] = m21; M[1][1] = m22; M[1][2] = m23; M[1][3] = 0;
  23.369         M[2][0] = m31; M[2][1] = m32; M[2][2] = m33; M[2][3] = 0;
  23.370         M[3][0] = 0;   M[3][1] = 0;   M[3][2] = 0;   M[3][3] = 1;
  23.371     }
  23.372 
  23.373     static const Matrix4f& Identity()  { return IdentityValue; }
  23.374 
  23.375     void SetIdentity()
  23.376     {
  23.377         M[0][0] = M[1][1] = M[2][2] = M[3][3] = 1;
  23.378         M[0][1] = M[1][0] = M[2][3] = M[3][1] = 0;
  23.379         M[0][2] = M[1][2] = M[2][0] = M[3][2] = 0;
  23.380         M[0][3] = M[1][3] = M[2][1] = M[3][0] = 0;
  23.381     }
  23.382 
  23.383     // Multiplies two matrices into destination with minimum copying.
  23.384     static Matrix4f& Multiply(Matrix4f* d, const Matrix4f& a, const Matrix4f& b)
  23.385     {
  23.386         OVR_ASSERT((d != &a) && (d != &b));
  23.387         int i = 0;
  23.388         do {
  23.389             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];
  23.390             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];
  23.391             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];
  23.392             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];
  23.393         } while((++i) < 4);
  23.394 
  23.395         return *d;
  23.396     }
  23.397 
  23.398     Matrix4f operator* (const Matrix4f& b) const
  23.399     {
  23.400         Matrix4f result(Matrix4f::NoInit);
  23.401         Multiply(&result, *this, b);
  23.402         return result;
  23.403     }
  23.404 
  23.405     Matrix4f& operator*= (const Matrix4f& b)
  23.406     {
  23.407         return Multiply(this, Matrix4f(*this), b);
  23.408     }
  23.409 
  23.410     Matrix4f operator* (float s) const
  23.411     {
  23.412         return Matrix4f(M[0][0] * s, M[0][1] * s, M[0][2] * s, M[0][3] * s,
  23.413                         M[1][0] * s, M[1][1] * s, M[1][2] * s, M[1][3] * s,
  23.414                         M[2][0] * s, M[2][1] * s, M[2][2] * s, M[2][3] * s,
  23.415                         M[3][0] * s, M[3][1] * s, M[3][2] * s, M[3][3] * s);
  23.416     }
  23.417 
  23.418     Matrix4f& operator*= (float s)
  23.419     {
  23.420         M[0][0] *= s; M[0][1] *= s; M[0][2] *= s; M[0][3] *= s;
  23.421         M[1][0] *= s; M[1][1] *= s; M[1][2] *= s; M[1][3] *= s;
  23.422         M[2][0] *= s; M[2][1] *= s; M[2][2] *= s; M[2][3] *= s;
  23.423         M[3][0] *= s; M[3][1] *= s; M[3][2] *= s; M[3][3] *= s;
  23.424         return *this;
  23.425     }
  23.426 
  23.427     Vector3f Transform(const Vector3f& v) const
  23.428     {
  23.429         return Vector3f(M[0][0] * v.x + M[0][1] * v.y + M[0][2] * v.z + M[0][3],
  23.430                         M[1][0] * v.x + M[1][1] * v.y + M[1][2] * v.z + M[1][3],
  23.431                         M[2][0] * v.x + M[2][1] * v.y + M[2][2] * v.z + M[2][3]);
  23.432     }
  23.433 
  23.434     Matrix4f Transposed() const
  23.435     {
  23.436         return Matrix4f(M[0][0], M[1][0], M[2][0], M[3][0],
  23.437                         M[0][1], M[1][1], M[2][1], M[3][1],
  23.438                         M[0][2], M[1][2], M[2][2], M[3][2],
  23.439                         M[0][3], M[1][3], M[2][3], M[3][3]);
  23.440     }
  23.441 
  23.442     void     Transpose()
  23.443     {
  23.444         *this = Transposed();
  23.445     }
  23.446 
  23.447 
  23.448     float SubDet (const int* rows, const int* cols) const
  23.449     {
  23.450         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]])
  23.451              - 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]])
  23.452              + 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]]);
  23.453     }
  23.454 
  23.455     float Cofactor(int I, int J) const
  23.456     {
  23.457         const int indices[4][3] = {{1,2,3},{0,2,3},{0,1,3},{0,1,2}};
  23.458         return ((I+J)&1) ? -SubDet(indices[I],indices[J]) : SubDet(indices[I],indices[J]);
  23.459     }
  23.460 
  23.461     float    Determinant() const
  23.462     {
  23.463         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);
  23.464     }
  23.465 
  23.466     Matrix4f Adjugated() const
  23.467     {
  23.468         return Matrix4f(Cofactor(0,0), Cofactor(1,0), Cofactor(2,0), Cofactor(3,0), 
  23.469                         Cofactor(0,1), Cofactor(1,1), Cofactor(2,1), Cofactor(3,1), 
  23.470                         Cofactor(0,2), Cofactor(1,2), Cofactor(2,2), Cofactor(3,2),
  23.471                         Cofactor(0,3), Cofactor(1,3), Cofactor(2,3), Cofactor(3,3));
  23.472     }
  23.473 
  23.474     Matrix4f Inverted() const
  23.475     {
  23.476         float det = Determinant();
  23.477         assert(det != 0);
  23.478         return Adjugated() * (1.0f/det);
  23.479     }
  23.480 
  23.481     void Invert()
  23.482     {
  23.483         *this = Inverted();
  23.484     }
  23.485 
  23.486     //AnnaSteve:
  23.487     // a,b,c, are the YawPitchRoll angles to be returned
  23.488     // rotation a around axis A1
  23.489     // is followed by rotation b around axis A2
  23.490     // is followed by rotation c around axis A3
  23.491     // rotations are CCW or CW (D) in LH or RH coordinate system (S)
  23.492     template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
  23.493     void ToEulerAngles(float *a, float *b, float *c)
  23.494     {
  23.495         OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3));
  23.496 
  23.497         float psign = -1.0f;
  23.498         if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3)) // Determine whether even permutation
  23.499         psign = 1.0f;
  23.500         
  23.501         float pm = psign*M[A1][A3];
  23.502         if (pm < -1.0f + Math<float>::SingularityRadius)
  23.503         { // South pole singularity
  23.504             *a = 0.0f;
  23.505             *b = -S*D*Math<float>::PiOver2;
  23.506             *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
  23.507         }
  23.508         else if (pm > 1.0 - Math<float>::SingularityRadius)
  23.509         { // North pole singularity
  23.510             *a = 0.0f;
  23.511             *b = S*D*Math<float>::PiOver2;
  23.512             *c = S*D*atan2( psign*M[A2][A1], M[A2][A2] );
  23.513         }
  23.514         else
  23.515         { // Normal case (nonsingular)
  23.516             *a = S*D*atan2( -psign*M[A2][A3], M[A3][A3] );
  23.517             *b = S*D*asin(pm);
  23.518             *c = S*D*atan2( -psign*M[A1][A2], M[A1][A1] );
  23.519         }
  23.520 
  23.521         return;
  23.522     }
  23.523 
  23.524     //AnnaSteve:
  23.525     // a,b,c, are the YawPitchRoll angles to be returned
  23.526     // rotation a around axis A1
  23.527     // is followed by rotation b around axis A2
  23.528     // is followed by rotation c around axis A1
  23.529     // rotations are CCW or CW (D) in LH or RH coordinate system (S)
  23.530     template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
  23.531     void ToEulerAnglesABA(float *a, float *b, float *c)
  23.532     {        
  23.533          OVR_COMPILER_ASSERT(A1 != A2);
  23.534   
  23.535         // Determine the axis that was not supplied
  23.536         int m = 3 - A1 - A2;
  23.537 
  23.538         float psign = -1.0f;
  23.539         if ((A1 + 1) % 3 == A2) // Determine whether even permutation
  23.540             psign = 1.0f;
  23.541 
  23.542         float c2 = M[A1][A1];
  23.543         if (c2 < -1.0 + Math<float>::SingularityRadius)
  23.544         { // South pole singularity
  23.545             *a = 0.0f;
  23.546             *b = S*D*Math<float>::Pi;
  23.547             *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
  23.548         }
  23.549         else if (c2 > 1.0 - Math<float>::SingularityRadius)
  23.550         { // North pole singularity
  23.551             *a = 0.0f;
  23.552             *b = 0.0f;
  23.553             *c = S*D*atan2( -psign*M[A2][m],M[A2][A2]);
  23.554         }
  23.555         else
  23.556         { // Normal case (nonsingular)
  23.557             *a = S*D*atan2( M[A2][A1],-psign*M[m][A1]);
  23.558             *b = S*D*acos(c2);
  23.559             *c = S*D*atan2( M[A1][A2],psign*M[A1][m]);
  23.560         }
  23.561         return;
  23.562     }
  23.563   
  23.564     // Creates a matrix that converts the vertices from one coordinate system
  23.565     // to another.
  23.566     // 
  23.567     static Matrix4f AxisConversion(const WorldAxes& to, const WorldAxes& from)
  23.568     {        
  23.569         // Holds axis values from the 'to' structure
  23.570         int toArray[3] = { to.XAxis, to.YAxis, to.ZAxis };
  23.571 
  23.572         // The inverse of the toArray
  23.573         int inv[4]; 
  23.574         inv[0] = inv[abs(to.XAxis)] = 0;
  23.575         inv[abs(to.YAxis)] = 1;
  23.576         inv[abs(to.ZAxis)] = 2;
  23.577 
  23.578         Matrix4f m(0,  0,  0, 
  23.579                    0,  0,  0,
  23.580                    0,  0,  0);
  23.581 
  23.582         // Only three values in the matrix need to be changed to 1 or -1.
  23.583         m.M[inv[abs(from.XAxis)]][0] = float(from.XAxis/toArray[inv[abs(from.XAxis)]]);
  23.584         m.M[inv[abs(from.YAxis)]][1] = float(from.YAxis/toArray[inv[abs(from.YAxis)]]);
  23.585         m.M[inv[abs(from.ZAxis)]][2] = float(from.ZAxis/toArray[inv[abs(from.ZAxis)]]);
  23.586         return m;
  23.587     } 
  23.588 
  23.589 
  23.590 
  23.591     static Matrix4f Translation(const Vector3f& v)
  23.592     {
  23.593         Matrix4f t;
  23.594         t.M[0][3] = v.x;
  23.595         t.M[1][3] = v.y;
  23.596         t.M[2][3] = v.z;
  23.597         return t;
  23.598     }
  23.599 
  23.600     static Matrix4f Translation(float x, float y, float z = 0.0f)
  23.601     {
  23.602         Matrix4f t;
  23.603         t.M[0][3] = x;
  23.604         t.M[1][3] = y;
  23.605         t.M[2][3] = z;
  23.606         return t;
  23.607     }
  23.608 
  23.609     static Matrix4f Scaling(const Vector3f& v)
  23.610     {
  23.611         Matrix4f t;
  23.612         t.M[0][0] = v.x;
  23.613         t.M[1][1] = v.y;
  23.614         t.M[2][2] = v.z;
  23.615         return t;
  23.616     }
  23.617 
  23.618     static Matrix4f Scaling(float x, float y, float z)
  23.619     {
  23.620         Matrix4f t;
  23.621         t.M[0][0] = x;
  23.622         t.M[1][1] = y;
  23.623         t.M[2][2] = z;
  23.624         return t;
  23.625     }
  23.626 
  23.627     static Matrix4f Scaling(float s)
  23.628     {
  23.629         Matrix4f t;
  23.630         t.M[0][0] = s;
  23.631         t.M[1][1] = s;
  23.632         t.M[2][2] = s;
  23.633         return t;
  23.634     }
  23.635 
  23.636   
  23.637 
  23.638     //AnnaSteve : Just for quick testing.  Not for final API.  Need to remove case.
  23.639     static Matrix4f RotationAxis(Axis A, float angle, RotateDirection d, HandedSystem s)
  23.640     {
  23.641         float sina = s * d *sin(angle);
  23.642         float cosa = cos(angle);
  23.643         
  23.644         switch(A)
  23.645         {
  23.646         case Axis_X:
  23.647             return Matrix4f(1,  0,     0, 
  23.648                             0,  cosa,  -sina,
  23.649                             0,  sina,  cosa);
  23.650         case Axis_Y:
  23.651             return Matrix4f(cosa,  0,   sina, 
  23.652                             0,     1,   0,
  23.653                             -sina, 0,   cosa);
  23.654         case Axis_Z:
  23.655             return Matrix4f(cosa,  -sina,  0, 
  23.656                             sina,  cosa,   0,
  23.657                             0,     0,      1);
  23.658         }
  23.659     }
  23.660 
  23.661 
  23.662     // Creates a rotation matrix rotating around the X axis by 'angle' radians.
  23.663     // Rotation direction is depends on the coordinate system:
  23.664     //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
  23.665     //                        while looking in the negative axis direction. This is the
  23.666     //                        same as looking down from positive axis values towards origin.
  23.667     //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
  23.668     //       negative axis direction.
  23.669     static Matrix4f RotationX(float angle)
  23.670     {
  23.671         float sina = sin(angle);
  23.672         float cosa = cos(angle);
  23.673         return Matrix4f(1,  0,     0, 
  23.674                         0,  cosa,  -sina,
  23.675                         0,  sina,  cosa);
  23.676     }
  23.677 
  23.678     // Creates a rotation matrix rotating around the Y axis by 'angle' radians.
  23.679     // Rotation direction is depends on the coordinate system:
  23.680     //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
  23.681     //                        while looking in the negative axis direction. This is the
  23.682     //                        same as looking down from positive axis values towards origin.
  23.683     //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
  23.684     //       negative axis direction.
  23.685     static Matrix4f RotationY(float angle)
  23.686     {
  23.687         float sina = sin(angle);
  23.688         float cosa = cos(angle);
  23.689         return Matrix4f(cosa,  0,   sina, 
  23.690                         0,     1,   0,
  23.691                         -sina, 0,   cosa);
  23.692     }
  23.693 
  23.694     // Creates a rotation matrix rotating around the Z axis by 'angle' radians.
  23.695     // Rotation direction is depends on the coordinate system:
  23.696     //  RHS (Oculus default): Positive angle values rotate Counter-clockwise (CCW),
  23.697     //                        while looking in the negative axis direction. This is the
  23.698     //                        same as looking down from positive axis values towards origin.
  23.699     //  LHS: Positive angle values rotate clock-wise (CW), while looking in the
  23.700     //       negative axis direction.
  23.701     static Matrix4f RotationZ(float angle)
  23.702     {
  23.703         float sina = sin(angle);
  23.704         float cosa = cos(angle);
  23.705         return Matrix4f(cosa,  -sina,  0, 
  23.706                         sina,  cosa,   0,
  23.707                         0,     0,      1);
  23.708     }
  23.709 
  23.710 
  23.711     // LookAtRH creates a View transformation matrix for right-handed coordinate system.
  23.712     // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
  23.713     // specifying the up vector. The resulting matrix should be used with PerspectiveRH
  23.714     // projection.
  23.715     static Matrix4f LookAtRH(const Vector3f& eye, const Vector3f& at, const Vector3f& up);
  23.716 
  23.717     // LookAtLH creates a View transformation matrix for left-handed coordinate system.
  23.718     // The resulting matrix points camera from 'eye' towards 'at' direction, with 'up'
  23.719     // specifying the up vector. 
  23.720     static Matrix4f LookAtLH(const Vector3f& eye, const Vector3f& at, const Vector3f& up);
  23.721     
  23.722     
  23.723     // PerspectiveRH creates a right-handed perspective projection matrix that can be
  23.724     // used with the Oculus sample renderer. 
  23.725     //  yfov   - Specifies vertical field of view in radians.
  23.726     //  aspect - Screen aspect ration, which is usually width/height for square pixels.
  23.727     //           Note that xfov = yfov * aspect.
  23.728     //  znear  - Absolute value of near Z clipping clipping range.
  23.729     //  zfar   - Absolute value of far  Z clipping clipping range (larger then near).
  23.730     // Even though RHS usually looks in the direction of negative Z, positive values
  23.731     // are expected for znear and zfar.
  23.732     static Matrix4f PerspectiveRH(float yfov, float aspect, float znear, float zfar);
  23.733     
  23.734     
  23.735     // PerspectiveRH creates a left-handed perspective projection matrix that can be
  23.736     // used with the Oculus sample renderer. 
  23.737     //  yfov   - Specifies vertical field of view in radians.
  23.738     //  aspect - Screen aspect ration, which is usually width/height for square pixels.
  23.739     //           Note that xfov = yfov * aspect.
  23.740     //  znear  - Absolute value of near Z clipping clipping range.
  23.741     //  zfar   - Absolute value of far  Z clipping clipping range (larger then near).
  23.742     static Matrix4f PerspectiveLH(float yfov, float aspect, float znear, float zfar);
  23.743 
  23.744 
  23.745     static Matrix4f Ortho2D(float w, float h);
  23.746 };
  23.747 
  23.748 
  23.749 //-------------------------------------------------------------------------------------
  23.750 // ***** Quat
  23.751 
  23.752 // Quatf represents a quaternion class used for rotations.
  23.753 // 
  23.754 // Quaternion multiplications are done in right-to-left order, to match the
  23.755 // behavior of matrices.
  23.756 
  23.757 
  23.758 template<class T>
  23.759 class Quat
  23.760 {
  23.761 public:
  23.762     // w + Xi + Yj + Zk
  23.763     T x, y, z, w;    
  23.764 
  23.765     Quat() : x(0), y(0), z(0), w(1) {}
  23.766     Quat(T x_, T y_, T z_, T w_) : x(x_), y(y_), z(z_), w(w_) {}
  23.767 
  23.768 
  23.769     // Constructs rotation quaternion around the axis.
  23.770     Quat(const Vector3<T>& axis, T angle)
  23.771     {
  23.772         Vector3<T> unitAxis = axis.Normalized();
  23.773         T          sinHalfAngle = sin(angle * T(0.5));
  23.774 
  23.775         w = cos(angle * T(0.5));
  23.776         x = unitAxis.x * sinHalfAngle;
  23.777         y = unitAxis.y * sinHalfAngle;
  23.778         z = unitAxis.z * sinHalfAngle;
  23.779     }
  23.780 
  23.781     //AnnaSteve:
  23.782     void AxisAngle(Axis A, T angle, RotateDirection d, HandedSystem s)
  23.783     {
  23.784         T sinHalfAngle = s * d *sin(angle * (T)0.5);
  23.785         T v[3];
  23.786         v[0] = v[1] = v[2] = (T)0;
  23.787         v[A] = sinHalfAngle;
  23.788         //return Quat(v[0], v[1], v[2], cos(angle * (T)0.5));
  23.789         w = cos(angle * (T)0.5);
  23.790         x = v[0];
  23.791         y = v[1];
  23.792         z = v[2];
  23.793     }
  23.794 
  23.795 
  23.796     void GetAxisAngle(Vector3<T>* axis, T* angle) const
  23.797     {
  23.798         if (LengthSq() > Math<T>::Tolerance * Math<T>::Tolerance)
  23.799         {
  23.800             *axis  = Vector3<T>(x, y, z).Normalized();
  23.801             *angle = 2 * acos(w);
  23.802         }
  23.803         else
  23.804         {
  23.805             *axis = Vector3<T>(1, 0, 0);
  23.806             *angle= 0;
  23.807         }
  23.808     }
  23.809 
  23.810     bool operator== (const Quat& b) const   { return x == b.x && y == b.y && z == b.z && w == b.w; }
  23.811     bool operator!= (const Quat& b) const   { return x != b.x || y != b.y || z != b.z || w != b.w; }
  23.812 
  23.813     Quat  operator+  (const Quat& b) const  { return Quat(x + b.x, y + b.y, z + b.z, w + b.w); }
  23.814     Quat& operator+= (const Quat& b)        { w += b.w; x += b.x; y += b.y; z += b.z; return *this; }
  23.815     Quat  operator-  (const Quat& b) const  { return Quat(x - b.x, y - b.y, z - b.z, w - b.w); }
  23.816     Quat& operator-= (const Quat& b)        { w -= b.w; x -= b.x; y -= b.y; z -= b.z; return *this; }
  23.817 
  23.818     Quat  operator*  (T s) const            { return Quat(x * s, y * s, z * s, w * s); }
  23.819     Quat& operator*= (T s)                  { w *= s; x *= s; y *= s; z *= s; return *this; }
  23.820     Quat  operator/  (T s) const            { T rcp = T(1)/s; return Quat(x * rcp, y * rcp, z * rcp, w *rcp); }
  23.821     Quat& operator/= (T s)                  { T rcp = T(1)/s; w *= rcp; x *= rcp; y *= rcp; z *= rcp; return *this; }
  23.822 
  23.823     // Get Imaginary part vector
  23.824     Vector3<T> Imag() const                 { return Vector3<T>(x,y,z); }
  23.825 
  23.826     // Get quaternion length.
  23.827     T       Length() const                  { return sqrt(x * x + y * y + z * z + w * w); }
  23.828     // Get quaternion length squared.
  23.829     T       LengthSq() const                { return (x * x + y * y + z * z + w * w); }
  23.830     // Simple Eulidean distance in R^4 (not SLERP distance, but at least respects Haar measure)
  23.831     T       Distance(const Quat& q) const
  23.832     {
  23.833         T d1 = (*this - q).Length();
  23.834         T d2 = (*this + q).Length(); // Antipoldal point check
  23.835         return (d1 < d2) ? d1 : d2;
  23.836     }
  23.837     T       DistanceSq(const Quat& q) const
  23.838     {
  23.839         T d1 = (*this - q).LengthSq();
  23.840         T d2 = (*this + q).LengthSq(); // Antipoldal point check
  23.841         return (d1 < d2) ? d1 : d2;
  23.842     }
  23.843 
  23.844     // Normalize
  23.845     bool    IsNormalized() const            { return fabs(LengthSq() - 1) < Math<T>::Tolerance; }
  23.846     void    Normalize()                     { *this /= Length(); }
  23.847     Quat    Normalized() const              { return *this / Length(); }
  23.848 
  23.849     // Returns conjugate of the quaternion. Produces inverse rotation if quaternion is normalized.
  23.850     Quat    Conj() const                    { return Quat(-x, -y, -z, w); }
  23.851 
  23.852     // AnnaSteve fixed: order of quaternion multiplication
  23.853     // Quaternion multiplication. Combines quaternion rotations, performing the one on the 
  23.854     // right hand side first.
  23.855     Quat  operator* (const Quat& b) const   { return Quat(w * b.x + x * b.w + y * b.z - z * b.y,
  23.856                                                           w * b.y - x * b.z + y * b.w + z * b.x,
  23.857                                                           w * b.z + x * b.y - y * b.x + z * b.w,
  23.858                                                           w * b.w - x * b.x - y * b.y - z * b.z); }
  23.859 
  23.860     // 
  23.861     // this^p normalized; same as rotating by this p times.
  23.862     Quat PowNormalized(T p) const
  23.863     {
  23.864         Vector3<T> v;
  23.865         T          a;
  23.866         GetAxisAngle(&v, &a);
  23.867         return Quat(v, a * p);
  23.868     }
  23.869     
  23.870     // Rotate transforms vector in a manner that matches Matrix rotations (counter-clockwise,
  23.871     // assuming negative direction of the axis). Standard formula: q(t) * V * q(t)^-1. 
  23.872     Vector3<T> Rotate(const Vector3<T>& v) const
  23.873     {
  23.874         return ((*this * Quat<T>(v.x, v.y, v.z, 0)) * Inverted()).Imag();
  23.875     }
  23.876 
  23.877     
  23.878     // Inversed quaternion rotates in the opposite direction.
  23.879     Quat        Inverted() const
  23.880     {
  23.881         return Quat(-x, -y, -z, w);
  23.882     }
  23.883 
  23.884     // Sets this quaternion to the one rotates in the opposite direction.
  23.885     void        Invert()
  23.886     {
  23.887         *this = Quat(-x, -y, -z, w);
  23.888     }
  23.889     
  23.890     // Converting quaternion to matrix.
  23.891     operator Matrix4f() const
  23.892     {
  23.893         T ww = w*w;
  23.894         T xx = x*x;
  23.895         T yy = y*y;
  23.896         T zz = z*z;
  23.897 
  23.898         return Matrix4f(float(ww + xx - yy - zz),  float(T(2) * (x*y - w*z)), float(T(2) * (x*z + w*y)),
  23.899                         float(T(2) * (x*y + w*z)), float(ww - xx + yy - zz),  float(T(2) * (y*z - w*x)),
  23.900                         float(T(2) * (x*z - w*y)), float(T(2) * (y*z + w*x)), float(ww - xx - yy + zz) );
  23.901     }
  23.902 
  23.903     
  23.904     // GetEulerAngles extracts Euler angles from the quaternion, in the specified order of
  23.905     // axis rotations and the specified coordinate system. Right-handed coordinate system
  23.906     // is the default, with CCW rotations while looking in the negative axis direction.
  23.907     // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
  23.908     // rotation a around axis A1
  23.909     // is followed by rotation b around axis A2
  23.910     // is followed by rotation c around axis A3
  23.911     // rotations are CCW or CW (D) in LH or RH coordinate system (S)
  23.912     template <Axis A1, Axis A2, Axis A3, RotateDirection D, HandedSystem S>
  23.913     void GetEulerAngles(T *a, T *b, T *c)
  23.914     {
  23.915         OVR_COMPILER_ASSERT((A1 != A2) && (A2 != A3) && (A1 != A3));
  23.916 
  23.917         T Q[3] = { x, y, z };  //Quaternion components x,y,z
  23.918 
  23.919         T ww  = w*w;
  23.920         T Q11 = Q[A1]*Q[A1];
  23.921         T Q22 = Q[A2]*Q[A2];
  23.922         T Q33 = Q[A3]*Q[A3];
  23.923 
  23.924         T psign = T(-1.0);
  23.925         // Determine whether even permutation
  23.926         if (((A1 + 1) % 3 == A2) && ((A2 + 1) % 3 == A3))
  23.927             psign = T(1.0);
  23.928         
  23.929         T s2 = psign * T(2.0) * (psign*w*Q[A2] + Q[A1]*Q[A3]);
  23.930 
  23.931         if (s2 < (T)-1.0 + Math<T>::SingularityRadius)
  23.932         { // South pole singularity
  23.933             *a = T(0.0);
  23.934             *b = -S*D*Math<T>::PiOver2;
  23.935             *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]),
  23.936 		                   ww + Q22 - Q11 - Q33 );
  23.937         }
  23.938         else if (s2 > (T)1.0 - Math<T>::SingularityRadius)
  23.939         {  // North pole singularity
  23.940             *a = (T)0.0;
  23.941             *b = S*D*Math<T>::PiOver2;
  23.942             *c = S*D*atan2((T)2.0*(psign*Q[A1]*Q[A2] + w*Q[A3]),
  23.943 		                   ww + Q22 - Q11 - Q33);
  23.944         }
  23.945         else
  23.946         {
  23.947             *a = -S*D*atan2((T)-2.0*(w*Q[A1] - psign*Q[A2]*Q[A3]),
  23.948 		                    ww + Q33 - Q11 - Q22);
  23.949             *b = S*D*asin(s2);
  23.950             *c = S*D*atan2((T)2.0*(w*Q[A3] - psign*Q[A1]*Q[A2]),
  23.951 		                   ww + Q11 - Q22 - Q33);
  23.952         }      
  23.953         return;
  23.954     }
  23.955 
  23.956     template <Axis A1, Axis A2, Axis A3, RotateDirection D>
  23.957     void GetEulerAngles(T *a, T *b, T *c)
  23.958     { GetEulerAngles<A1, A2, A3, D, Handed_R>(a, b, c); }
  23.959 
  23.960     template <Axis A1, Axis A2, Axis A3>
  23.961     void GetEulerAngles(T *a, T *b, T *c)
  23.962     { GetEulerAngles<A1, A2, A3, Rotate_CCW, Handed_R>(a, b, c); }
  23.963 
  23.964 
  23.965     // GetEulerAnglesABA extracts Euler angles from the quaternion, in the specified order of
  23.966     // axis rotations and the specified coordinate system. Right-handed coordinate system
  23.967     // is the default, with CCW rotations while looking in the negative axis direction.
  23.968     // Here a,b,c, are the Yaw/Pitch/Roll angles to be returned.
  23.969     // rotation a around axis A1
  23.970     // is followed by rotation b around axis A2
  23.971     // is followed by rotation c around axis A1
  23.972     // Rotations are CCW or CW (D) in LH or RH coordinate system (S)
  23.973     template <Axis A1, Axis A2, RotateDirection D, HandedSystem S>
  23.974     void GetEulerAnglesABA(T *a, T *b, T *c)
  23.975     {
  23.976         OVR_COMPILER_ASSERT(A1 != A2);
  23.977 
  23.978         T Q[3] = {x, y, z}; // Quaternion components
  23.979 
  23.980         // Determine the missing axis that was not supplied
  23.981         int m = 3 - A1 - A2;
  23.982 
  23.983         T ww = w*w;
  23.984         T Q11 = Q[A1]*Q[A1];
  23.985         T Q22 = Q[A2]*Q[A2];
  23.986         T Qmm = Q[m]*Q[m];
  23.987 
  23.988         T psign = T(-1.0);
  23.989         if ((A1 + 1) % 3 == A2) // Determine whether even permutation
  23.990         {
  23.991             psign = (T)1.0;
  23.992         }
  23.993 
  23.994         T c2 = ww + Q11 - Q22 - Qmm;
  23.995         if (c2 < (T)-1.0 + Math<T>::SingularityRadius)
  23.996         { // South pole singularity
  23.997             *a = (T)0.0;
  23.998             *b = S*D*Math<T>::Pi;
  23.999             *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]),
 23.1000 		                    ww + Q22 - Q11 - Qmm);
 23.1001         }
 23.1002         else if (c2 > (T)1.0 - Math<T>::SingularityRadius)
 23.1003         {  // North pole singularity
 23.1004             *a = (T)0.0;
 23.1005             *b = (T)0.0;
 23.1006             *c = S*D*atan2( (T)2.0*(w*Q[A1] - psign*Q[A2]*Q[m]),
 23.1007 		                   ww + Q22 - Q11 - Qmm);
 23.1008         }
 23.1009         else
 23.1010         {
 23.1011             *a = S*D*atan2( psign*w*Q[m] + Q[A1]*Q[A2],
 23.1012 		                   w*Q[A2] -psign*Q[A1]*Q[m]);
 23.1013             *b = S*D*acos(c2);
 23.1014             *c = S*D*atan2( -psign*w*Q[m] + Q[A1]*Q[A2],
 23.1015 		                   w*Q[A2] + psign*Q[A1]*Q[m]);
 23.1016         }
 23.1017         return;
 23.1018     }
 23.1019 };
 23.1020 
 23.1021 
 23.1022 typedef Quat<float>  Quatf;
 23.1023 typedef Quat<double> Quatd;
 23.1024 
 23.1025 
 23.1026 
 23.1027 //-------------------------------------------------------------------------------------
 23.1028 // ***** Angle
 23.1029 
 23.1030 // Cleanly representing the algebra of 2D rotations.
 23.1031 // The operations maintain the angle between -Pi and Pi, the same range as atan2.
 23.1032 // 
 23.1033 
 23.1034 template<class T>
 23.1035 class Angle
 23.1036 {
 23.1037 public:
 23.1038 	enum AngularUnits
 23.1039 	{
 23.1040 		Radians = 0,
 23.1041 		Degrees = 1
 23.1042 	};
 23.1043 
 23.1044     Angle() : a(0) {}
 23.1045     
 23.1046 	// Fix the range to be between -Pi and Pi
 23.1047 	Angle(T a_, AngularUnits u = Radians) : a((u == Radians) ? a_ : a_*Math<T>::DegreeToRadFactor) { FixRange(); }
 23.1048 
 23.1049 	T    Get(AngularUnits u = Radians) const       { return (u == Radians) ? a : a*Math<T>::RadToDegreeFactor; }
 23.1050 	void Set(const T& x, AngularUnits u = Radians) { a = (u == Radians) ? x : x*Math<T>::DegreeToRadFactor; FixRange(); }
 23.1051 	int Sign() const                               { if (a == 0) return 0; else return (a > 0) ? 1 : -1; }
 23.1052 	T   Abs() const                                { return (a > 0) ? a : -a; }
 23.1053 
 23.1054     bool operator== (const Angle& b) const    { return a == b.a; }
 23.1055     bool operator!= (const Angle& b) const    { return a != b.a; }
 23.1056 //	bool operator<  (const Angle& b) const    { return a < a.b; } 
 23.1057 //	bool operator>  (const Angle& b) const    { return a > a.b; } 
 23.1058 //	bool operator<= (const Angle& b) const    { return a <= a.b; } 
 23.1059 //	bool operator>= (const Angle& b) const    { return a >= a.b; } 
 23.1060 //	bool operator= (const T& x)               { a = x; FixRange(); }
 23.1061 
 23.1062 	// These operations assume a is already between -Pi and Pi.
 23.1063     Angle  operator+  (const Angle& b) const  { return Angle(a + b.a); }
 23.1064 	Angle  operator+  (const T& x) const      { return Angle(a + x); }
 23.1065 	Angle& operator+= (const Angle& b)        { a = a + b.a; FastFixRange(); return *this; }
 23.1066 	Angle& operator+= (const T& x)            { a = a + x; FixRange(); return *this; }
 23.1067 	Angle  operator-  (const Angle& b) const  { return Angle(a - b.a); }
 23.1068 	Angle  operator-  (const T& x) const      { return Angle(a - x); }
 23.1069 	Angle& operator-= (const Angle& b)        { a = a - b.a; FastFixRange(); return *this; }
 23.1070 	Angle& operator-= (const T& x)            { a = a - x; FixRange(); return *this; }
 23.1071 	
 23.1072 	T   Distance(const Angle& b)              { T c = fabs(a - b.a); return (c <= Math<T>::Pi) ? c : Math<T>::TwoPi - c; }
 23.1073 
 23.1074 private:
 23.1075 
 23.1076 	// The stored angle, which should be maintained between -Pi and Pi
 23.1077 	T a;
 23.1078 
 23.1079 	// Fixes the angle range to [-Pi,Pi], but assumes no more than 2Pi away on either side 
 23.1080 	inline void FastFixRange()
 23.1081 	{
 23.1082 		if (a < -Math<T>::Pi)
 23.1083 			a += Math<T>::TwoPi;
 23.1084 		else if (a > Math<T>::Pi)
 23.1085 			a -= Math<T>::TwoPi;
 23.1086 	}
 23.1087 
 23.1088 	// Fixes the angle range to [-Pi,Pi] for any given range, but slower then the fast method
 23.1089 	inline void FixRange()
 23.1090 	{
 23.1091 		a = fmod(a,Math<T>::TwoPi);
 23.1092 		if (a < -Math<T>::Pi)
 23.1093 			a += Math<T>::TwoPi;
 23.1094 		else if (a > Math<T>::Pi)
 23.1095 			a -= Math<T>::TwoPi;
 23.1096 	}
 23.1097 };
 23.1098 
 23.1099 
 23.1100 typedef Angle<float>  Anglef;
 23.1101 typedef Angle<double> Angled;
 23.1102 
 23.1103 
 23.1104 //-------------------------------------------------------------------------------------
 23.1105 // ***** Plane
 23.1106 
 23.1107 // Consists of a normal vector and distance from the origin where the plane is located.
 23.1108 
 23.1109 template<class T>
 23.1110 class Plane : public RefCountBase<Plane<T> >
 23.1111 {
 23.1112 public:
 23.1113     Vector3<T> N;
 23.1114     T          D;
 23.1115 
 23.1116     Plane() : D(0) {}
 23.1117 
 23.1118     // Normals must already be normalized
 23.1119     Plane(const Vector3<T>& n, T d) : N(n), D(d) {}
 23.1120     Plane(T x, T y, T z, T d) : N(x,y,z), D(d) {}
 23.1121 
 23.1122     // construct from a point on the plane and the normal
 23.1123     Plane(const Vector3<T>& p, const Vector3<T>& n) : N(n), D(-(p * n)) {}
 23.1124 
 23.1125     // Find the point to plane distance. The sign indicates what side of the plane the point is on (0 = point on plane).
 23.1126     T TestSide(const Vector3<T>& p) const
 23.1127     {
 23.1128         return (N * p) + D;
 23.1129     }
 23.1130 
 23.1131     Plane<T> Flipped() const
 23.1132     {
 23.1133         return Plane(-N, -D);
 23.1134     }
 23.1135 
 23.1136     void Flip()
 23.1137     {
 23.1138         N = -N;
 23.1139         D = -D;
 23.1140     }
 23.1141 
 23.1142 	bool operator==(const Plane<T>& rhs) const
 23.1143 	{
 23.1144 		return (this->D == rhs.D && this->N == rhs.N);
 23.1145 	}
 23.1146 };
 23.1147 
 23.1148 typedef Plane<float> Planef;
 23.1149 
 23.1150 }
 23.1151 
 23.1152 #endif
 23.1153 \ No newline at end of file
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/libovr/Src/Kernel/OVR_RefCount.cpp	Sat Sep 14 16:14:59 2013 +0300
    24.3 @@ -0,0 +1,1 @@
    24.4 +/************************************************************************************
    24.5 
    24.6 Filename    :   OVR_RefCount.cpp
    24.7 Content     :   Reference counting implementation
    24.8 Created     :   September 19, 2012
    24.9 Notes       : 
   24.10 
   24.11 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   24.12 
   24.13 Use of this software is subject to the terms of the Oculus license
   24.14 agreement provided at the time of installation or download, or which
   24.15 otherwise accompanies this software in either electronic or hard copy form.
   24.16 
   24.17 ************************************************************************************/
   24.18 
   24.19 #include "OVR_RefCount.h"
   24.20 #include "OVR_Atomic.h"
   24.21 #include "OVR_Log.h"
   24.22 
   24.23 namespace OVR {
   24.24 
   24.25 #ifdef OVR_CC_ARM
   24.26 void* ReturnArg0(void* p)
   24.27 {
   24.28     return p;
   24.29 }
   24.30 #endif
   24.31 
   24.32 // ***** Reference Count Base implementation
   24.33 
   24.34 RefCountImplCore::~RefCountImplCore()
   24.35 {
   24.36     // RefCount can be either 1 or 0 here.
   24.37     //  0 if Release() was properly called.
   24.38     //  1 if the object was declared on stack or as an aggregate.
   24.39     OVR_ASSERT(RefCount <= 1);
   24.40 }
   24.41 
   24.42 #ifdef OVR_BUILD_DEBUG
   24.43 void RefCountImplCore::reportInvalidDelete(void *pmem)
   24.44 {
   24.45     OVR_DEBUG_LOG(
   24.46         ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem));
   24.47     OVR_ASSERT(0);
   24.48 }
   24.49 #endif
   24.50 
   24.51 RefCountNTSImplCore::~RefCountNTSImplCore()
   24.52 {
   24.53     // RefCount can be either 1 or 0 here.
   24.54     //  0 if Release() was properly called.
   24.55     //  1 if the object was declared on stack or as an aggregate.
   24.56     OVR_ASSERT(RefCount <= 1);
   24.57 }
   24.58 
   24.59 #ifdef OVR_BUILD_DEBUG
   24.60 void RefCountNTSImplCore::reportInvalidDelete(void *pmem)
   24.61 {
   24.62     OVR_DEBUG_LOG(
   24.63         ("Invalid delete call on ref-counted object at %p. Please use Release()", pmem));
   24.64     OVR_ASSERT(0);
   24.65 }
   24.66 #endif
   24.67 
   24.68 
   24.69 // *** Thread-Safe RefCountImpl
   24.70 
   24.71 void    RefCountImpl::AddRef()
   24.72 {
   24.73     AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1);
   24.74 }
   24.75 void    RefCountImpl::Release()
   24.76 {
   24.77     if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
   24.78         delete this;
   24.79 }
   24.80 
   24.81 // *** Thread-Safe RefCountVImpl w/virtual AddRef/Release
   24.82 
   24.83 void    RefCountVImpl::AddRef()
   24.84 {
   24.85     AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, 1);
   24.86 }
   24.87 void    RefCountVImpl::Release()
   24.88 {
   24.89     if ((AtomicOps<int>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
   24.90         delete this;
   24.91 }
   24.92 
   24.93 // *** NON-Thread-Safe RefCountImpl
   24.94 
   24.95 void    RefCountNTSImpl::Release() const
   24.96 {
   24.97     RefCount--;
   24.98     if (RefCount == 0)
   24.99         delete this;
  24.100 }
  24.101 
  24.102 
  24.103 } // OVR
  24.104 \ No newline at end of file
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/libovr/Src/Kernel/OVR_RefCount.h	Sat Sep 14 16:14:59 2013 +0300
    25.3 @@ -0,0 +1,1 @@
    25.4 +/************************************************************************************
    25.5 
    25.6 PublicHeader:   Kernel
    25.7 Filename    :   OVR_RefCount.h
    25.8 Content     :   Reference counting implementation headers
    25.9 Created     :   September 19, 2012
   25.10 Notes       : 
   25.11 
   25.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   25.13 
   25.14 Use of this software is subject to the terms of the Oculus license
   25.15 agreement provided at the time of installation or download, or which
   25.16 otherwise accompanies this software in either electronic or hard copy form.
   25.17 
   25.18 ************************************************************************************/
   25.19 
   25.20 #ifndef OVR_RefCount_h
   25.21 #define OVR_RefCount_h
   25.22 
   25.23 #include "OVR_Types.h"
   25.24 #include "OVR_Allocator.h"
   25.25 
   25.26 namespace OVR {
   25.27 
   25.28 //-----------------------------------------------------------------------------------
   25.29 // ***** Reference Counting
   25.30 
   25.31 // There are three types of reference counting base classes:
   25.32 //
   25.33 //  RefCountBase     - Provides thread-safe reference counting (Default).
   25.34 //  RefCountBaseNTS  - Non Thread Safe version of reference counting.
   25.35 
   25.36 
   25.37 // ***** Declared classes
   25.38 
   25.39 template<class C>
   25.40 class   RefCountBase;
   25.41 template<class C>
   25.42 class   RefCountBaseNTS;
   25.43 
   25.44 class   RefCountImpl;
   25.45 class   RefCountNTSImpl;
   25.46 
   25.47 
   25.48 //-----------------------------------------------------------------------------------
   25.49 // ***** Implementation For Reference Counting
   25.50 
   25.51 // RefCountImplCore holds RefCount value and defines a few utility
   25.52 // functions shared by all implementations.
   25.53 
   25.54 class RefCountImplCore
   25.55 {
   25.56 protected:
   25.57     volatile int RefCount;
   25.58 
   25.59 public:
   25.60     // RefCountImpl constructor always initializes RefCount to 1 by default.
   25.61     OVR_FORCE_INLINE RefCountImplCore() : RefCount(1) { }
   25.62 
   25.63     // Need virtual destructor
   25.64     // This:    1. Makes sure the right destructor's called.
   25.65     //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
   25.66     virtual ~RefCountImplCore();
   25.67 
   25.68     // Debug method only.
   25.69     int GetRefCount() const { return RefCount;  }
   25.70 
   25.71     // This logic is used to detect invalid 'delete' calls of reference counted
   25.72     // objects. Direct delete calls are not allowed on them unless they come in
   25.73     // internally from Release.
   25.74 #ifdef OVR_BUILD_DEBUG    
   25.75     static void   OVR_CDECL  reportInvalidDelete(void *pmem);
   25.76     inline static void checkInvalidDelete(RefCountImplCore *pmem)
   25.77     {
   25.78         if (pmem->RefCount != 0)
   25.79             reportInvalidDelete(pmem);
   25.80     }
   25.81 #else
   25.82     inline static void checkInvalidDelete(RefCountImplCore *) { }
   25.83 #endif
   25.84 
   25.85     // Base class ref-count content should not be copied.
   25.86     void operator = (const RefCountImplCore &) { }  
   25.87 };
   25.88 
   25.89 class RefCountNTSImplCore
   25.90 {
   25.91 protected:
   25.92     mutable int RefCount;
   25.93 
   25.94 public:
   25.95     // RefCountImpl constructor always initializes RefCount to 1 by default.
   25.96     OVR_FORCE_INLINE RefCountNTSImplCore() : RefCount(1) { }
   25.97 
   25.98     // Need virtual destructor
   25.99     // This:    1. Makes sure the right destructor's called.
  25.100     //          2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
  25.101     virtual ~RefCountNTSImplCore();
  25.102 
  25.103     // Debug method only.
  25.104     int             GetRefCount() const { return RefCount;  }
  25.105 
  25.106     // This logic is used to detect invalid 'delete' calls of reference counted
  25.107     // objects. Direct delete calls are not allowed on them unless they come in
  25.108     // internally from Release.
  25.109 #ifdef OVR_BUILD_DEBUG    
  25.110     static void   OVR_CDECL  reportInvalidDelete(void *pmem);
  25.111     OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem)
  25.112     {
  25.113         if (pmem->RefCount != 0)
  25.114             reportInvalidDelete(pmem);
  25.115     }
  25.116 #else
  25.117     OVR_FORCE_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { }
  25.118 #endif
  25.119 
  25.120     // Base class ref-count content should not be copied.
  25.121     void operator = (const RefCountNTSImplCore &) { }  
  25.122 };
  25.123 
  25.124 
  25.125 
  25.126 // RefCountImpl provides Thread-Safe implementation of reference counting, so
  25.127 // it should be used by default in most places.
  25.128 
  25.129 class RefCountImpl : public RefCountImplCore
  25.130 {
  25.131 public:
  25.132     // Thread-Safe Ref-Count Implementation.
  25.133     void    AddRef();
  25.134     void    Release();   
  25.135 };
  25.136 
  25.137 // RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
  25.138 // virtual AddRef and Release.
  25.139 
  25.140 class RefCountVImpl : public RefCountImplCore
  25.141 {
  25.142 public:
  25.143     // Thread-Safe Ref-Count Implementation.
  25.144     virtual void      AddRef();
  25.145     virtual void      Release();   
  25.146 };
  25.147 
  25.148 
  25.149 // RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
  25.150 // which is slightly more efficient since it doesn't use atomics.
  25.151 
  25.152 class RefCountNTSImpl : public RefCountNTSImplCore
  25.153 {
  25.154 public:
  25.155     OVR_FORCE_INLINE void    AddRef() const { RefCount++; }
  25.156     void    Release() const;   
  25.157 };
  25.158 
  25.159 
  25.160 
  25.161 // RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
  25.162 // to the reference counting implementation. Base must be one of the RefCountImpl classes.
  25.163 
  25.164 template<class Base>
  25.165 class RefCountBaseStatImpl : public Base
  25.166 {
  25.167 public:
  25.168     RefCountBaseStatImpl() { }
  25.169      
  25.170     // *** Override New and Delete
  25.171 
  25.172     // DOM-IGNORE-BEGIN
  25.173     // Undef new temporarily if it is being redefined
  25.174 #ifdef OVR_DEFINE_NEW
  25.175 #undef new
  25.176 #endif
  25.177 
  25.178 #ifdef OVR_BUILD_DEBUG
  25.179     // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
  25.180     #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)   \
  25.181         do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
  25.182 #else
  25.183     #define OVR_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
  25.184 #endif
  25.185 
  25.186     // Redefine all new & delete operators.
  25.187     OVR_MEMORY_REDEFINE_NEW_IMPL(Base, OVR_REFCOUNTALLOC_CHECK_DELETE)
  25.188 
  25.189 #ifdef OVR_DEFINE_NEW
  25.190 #define new OVR_DEFINE_NEW
  25.191 #endif
  25.192         // OVR_BUILD_DEFINE_NEW
  25.193         // DOM-IGNORE-END
  25.194 };
  25.195 
  25.196 
  25.197 
  25.198 //-----------------------------------------------------------------------------------
  25.199 // *** End user RefCountBase<> classes
  25.200 
  25.201 
  25.202 // RefCountBase is a base class for classes that require thread-safe reference
  25.203 // counting; it also overrides the new and delete operators to use MemoryHeap.
  25.204 //
  25.205 // Reference counted objects start out with RefCount value of 1. Further lifetime
  25.206 // management is done through the AddRef() and Release() methods, typically
  25.207 // hidden by Ptr<>.
  25.208 
  25.209 template<class C>
  25.210 class RefCountBase : public RefCountBaseStatImpl<RefCountImpl>
  25.211 {
  25.212 public:    
  25.213     // Constructor.
  25.214     OVR_FORCE_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl>() { }    
  25.215 };
  25.216 
  25.217 // RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
  25.218 
  25.219 template<class C>
  25.220 class RefCountBaseV : public RefCountBaseStatImpl<RefCountVImpl>
  25.221 {
  25.222 public:    
  25.223     // Constructor.
  25.224     OVR_FORCE_INLINE RefCountBaseV() : RefCountBaseStatImpl<RefCountVImpl>() { }    
  25.225 };
  25.226 
  25.227 
  25.228 // RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
  25.229 // counting; it also overrides the new and delete operators to use MemoryHeap.
  25.230 // This class should only be used if all pointers to it are known to be assigned,
  25.231 // destroyed and manipulated within one thread.
  25.232 //
  25.233 // Reference counted objects start out with RefCount value of 1. Further lifetime
  25.234 // management is done through the AddRef() and Release() methods, typically
  25.235 // hidden by Ptr<>.
  25.236 
  25.237 template<class C>
  25.238 class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl>
  25.239 {
  25.240 public:    
  25.241     // Constructor.
  25.242     OVR_FORCE_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl>() { }    
  25.243 };
  25.244 
  25.245 //-----------------------------------------------------------------------------------
  25.246 // ***** Pickable template pointer
  25.247 enum PickType { PickValue };
  25.248 
  25.249 template <typename T>
  25.250 class Pickable
  25.251 {
  25.252 public:
  25.253     Pickable() : pV(NULL) {}
  25.254     explicit Pickable(T* p) : pV(p) {}
  25.255     Pickable(T* p, PickType) : pV(p) 
  25.256     {
  25.257         OVR_ASSERT(pV);
  25.258         if (pV)
  25.259             pV->AddRef();
  25.260     }
  25.261     template <typename OT>
  25.262     Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {}
  25.263 
  25.264 public:
  25.265     Pickable& operator =(const Pickable& other)
  25.266     {
  25.267         OVR_ASSERT(pV == NULL);
  25.268         pV = other.pV;
  25.269         // Extra check.
  25.270         //other.pV = NULL;
  25.271         return *this;
  25.272     }
  25.273 
  25.274 public:
  25.275     T* GetPtr() const { return pV; }
  25.276     T* operator->() const
  25.277     {
  25.278         return pV;
  25.279     }
  25.280     T& operator*() const
  25.281     {
  25.282         OVR_ASSERT(pV);
  25.283         return *pV;
  25.284     }
  25.285 
  25.286 private:
  25.287     T* pV;
  25.288 };
  25.289 
  25.290 template <typename T>
  25.291 OVR_FORCE_INLINE
  25.292 Pickable<T> MakePickable(T* p)
  25.293 {
  25.294     return Pickable<T>(p);
  25.295 }
  25.296 
  25.297 //-----------------------------------------------------------------------------------
  25.298 // ***** Ref-Counted template pointer
  25.299 
  25.300 // Automatically AddRefs and Releases interfaces
  25.301 
  25.302 void* ReturnArg0(void* p);
  25.303 
  25.304 template<class C>
  25.305 class Ptr
  25.306 {
  25.307 #ifdef OVR_CC_ARM
  25.308     static C* ReturnArg(void* p) { return (C*)ReturnArg0(p); }
  25.309 #endif
  25.310 
  25.311 protected:
  25.312     C   *pObject;
  25.313 
  25.314 public:
  25.315 
  25.316     // Constructors
  25.317     OVR_FORCE_INLINE Ptr() : pObject(0)
  25.318     { }
  25.319 #ifdef OVR_CC_ARM
  25.320     OVR_FORCE_INLINE Ptr(C &robj) : pObject(ReturnArg(&robj))
  25.321 #else
  25.322     OVR_FORCE_INLINE Ptr(C &robj) : pObject(&robj)
  25.323 #endif
  25.324     { }
  25.325     OVR_FORCE_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr())
  25.326     {
  25.327         // No AddRef() on purpose.
  25.328     }
  25.329     OVR_FORCE_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject)
  25.330     {
  25.331         other.pObject = NULL;
  25.332         // No AddRef() on purpose.
  25.333     }
  25.334     OVR_FORCE_INLINE Ptr(C *pobj)
  25.335     {
  25.336         if (pobj) pobj->AddRef();   
  25.337         pObject = pobj;
  25.338     }
  25.339     OVR_FORCE_INLINE Ptr(const Ptr<C> &src)
  25.340     {
  25.341         if (src.pObject) src.pObject->AddRef();     
  25.342         pObject = src.pObject;
  25.343     }
  25.344 
  25.345     template<class R>
  25.346     OVR_FORCE_INLINE Ptr(Ptr<R> &src)
  25.347     {
  25.348         if (src) src->AddRef();
  25.349         pObject = src;
  25.350     }
  25.351     template<class R>
  25.352     OVR_FORCE_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr())
  25.353     {
  25.354         // No AddRef() on purpose.
  25.355     }
  25.356 
  25.357     // Destructor
  25.358     OVR_FORCE_INLINE ~Ptr()
  25.359     {
  25.360         if (pObject) pObject->Release();        
  25.361     }
  25.362 
  25.363     // Compares
  25.364     OVR_FORCE_INLINE bool operator == (const Ptr &other) const       { return pObject == other.pObject; }
  25.365     OVR_FORCE_INLINE bool operator != (const Ptr &other) const       { return pObject != other.pObject; }
  25.366 
  25.367     OVR_FORCE_INLINE bool operator == (C *pother) const              { return pObject == pother; }
  25.368     OVR_FORCE_INLINE bool operator != (C *pother) const              { return pObject != pother; }
  25.369 
  25.370 
  25.371     OVR_FORCE_INLINE bool operator < (const Ptr &other) const       { return pObject < other.pObject; }
  25.372 
  25.373     // Assignment
  25.374     template<class R>
  25.375     OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<R> &src)
  25.376     {
  25.377         if (src) src->AddRef();
  25.378         if (pObject) pObject->Release();        
  25.379         pObject = src;
  25.380         return *this;
  25.381     }   
  25.382     // Specialization
  25.383     OVR_FORCE_INLINE const Ptr<C>& operator = (const Ptr<C> &src)
  25.384     {
  25.385         if (src) src->AddRef();
  25.386         if (pObject) pObject->Release();        
  25.387         pObject = src;
  25.388         return *this;
  25.389     }   
  25.390     
  25.391     OVR_FORCE_INLINE const Ptr<C>& operator = (C *psrc)
  25.392     {
  25.393         if (psrc) psrc->AddRef();
  25.394         if (pObject) pObject->Release();        
  25.395         pObject = psrc;
  25.396         return *this;
  25.397     }   
  25.398     OVR_FORCE_INLINE const Ptr<C>& operator = (C &src)
  25.399     {       
  25.400         if (pObject) pObject->Release();        
  25.401         pObject = &src;
  25.402         return *this;
  25.403     }
  25.404     OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<C> src)
  25.405     {
  25.406         return Pick(src);
  25.407     }
  25.408     template<class R>
  25.409     OVR_FORCE_INLINE Ptr<C>& operator = (Pickable<R> src)
  25.410     {
  25.411         return Pick(src);
  25.412     }
  25.413     
  25.414     // Set Assignment
  25.415     template<class R>
  25.416     OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<R> &src)
  25.417     {
  25.418         if (src) src->AddRef();
  25.419         if (pObject) pObject->Release();
  25.420         pObject = src;
  25.421         return *this;
  25.422     }
  25.423     // Specialization
  25.424     OVR_FORCE_INLINE Ptr<C>& SetPtr(const Ptr<C> &src)
  25.425     {
  25.426         if (src) src->AddRef();
  25.427         if (pObject) pObject->Release();
  25.428         pObject = src;
  25.429         return *this;
  25.430     }   
  25.431     
  25.432     OVR_FORCE_INLINE Ptr<C>& SetPtr(C *psrc)
  25.433     {
  25.434         if (psrc) psrc->AddRef();
  25.435         if (pObject) pObject->Release();
  25.436         pObject = psrc;
  25.437         return *this;
  25.438     }   
  25.439     OVR_FORCE_INLINE Ptr<C>& SetPtr(C &src)
  25.440     {       
  25.441         if (pObject) pObject->Release();
  25.442         pObject = &src;
  25.443         return *this;
  25.444     }
  25.445     OVR_FORCE_INLINE Ptr<C>& SetPtr(Pickable<C> src)
  25.446     {       
  25.447         return Pick(src);
  25.448     }
  25.449 
  25.450     // Nulls ref-counted pointer without decrement
  25.451     OVR_FORCE_INLINE void    NullWithoutRelease()    
  25.452     { 
  25.453         pObject = 0;    
  25.454     }
  25.455 
  25.456     // Clears the pointer to the object
  25.457     OVR_FORCE_INLINE void    Clear()
  25.458     {
  25.459         if (pObject) pObject->Release();
  25.460         pObject = 0;
  25.461     }
  25.462 
  25.463     // Obtain pointer reference directly, for D3D interfaces
  25.464     OVR_FORCE_INLINE C*& GetRawRef()                 { return pObject; }
  25.465 
  25.466     // Access Operators
  25.467     OVR_FORCE_INLINE C* GetPtr() const               { return pObject; }
  25.468     OVR_FORCE_INLINE C& operator * () const          { return *pObject; }
  25.469     OVR_FORCE_INLINE C* operator -> ()  const        { return pObject; }
  25.470     // Conversion                   
  25.471     OVR_FORCE_INLINE operator C* () const            { return pObject; }
  25.472 
  25.473     // Pickers.
  25.474 
  25.475     // Pick a value.
  25.476     OVR_FORCE_INLINE Ptr<C>& Pick(Ptr<C>& other)
  25.477     {
  25.478         if (&other != this)
  25.479         {
  25.480             if (pObject) pObject->Release();
  25.481             pObject = other.pObject;
  25.482             other.pObject = 0;
  25.483         }
  25.484 
  25.485         return *this;
  25.486     }
  25.487 
  25.488     OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<C> v)
  25.489     {
  25.490         if (v.GetPtr() != pObject)
  25.491         {
  25.492             if (pObject) pObject->Release();
  25.493             pObject = v.GetPtr();
  25.494         }
  25.495 
  25.496         return *this;
  25.497     }
  25.498 
  25.499     template<class R>
  25.500     OVR_FORCE_INLINE Ptr<C>& Pick(Pickable<R> v)
  25.501     {
  25.502         if (v.GetPtr() != pObject)
  25.503         {
  25.504             if (pObject) pObject->Release();
  25.505             pObject = v.GetPtr();
  25.506         }
  25.507 
  25.508         return *this;
  25.509     }
  25.510 
  25.511     OVR_FORCE_INLINE Ptr<C>& Pick(C* p)
  25.512     {
  25.513         if (p != pObject)
  25.514         {
  25.515             if (pObject) pObject->Release();
  25.516             pObject = p;
  25.517         }
  25.518 
  25.519         return *this;
  25.520     }
  25.521 };
  25.522 
  25.523 } // OVR
  25.524 
  25.525 #endif
  25.526 \ No newline at end of file
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/libovr/Src/Kernel/OVR_Std.cpp	Sat Sep 14 16:14:59 2013 +0300
    26.3 @@ -0,0 +1,1 @@
    26.4 +/************************************************************************************
    26.5 
    26.6 Filename    :   OVR_Std.cpp
    26.7 Content     :   Standard C function implementation
    26.8 Created     :   September 19, 2012
    26.9 Notes       : 
   26.10 
   26.11 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   26.12 
   26.13 Use of this software is subject to the terms of the Oculus license
   26.14 agreement provided at the time of installation or download, or which
   26.15 otherwise accompanies this software in either electronic or hard copy form.
   26.16 
   26.17 ************************************************************************************/
   26.18 
   26.19 #include "OVR_Std.h"
   26.20 #include "OVR_Alg.h"
   26.21 
   26.22 // localeconv() call in OVR_strtod()
   26.23 #include <locale.h>
   26.24 
   26.25 namespace OVR {
   26.26 
   26.27 // Source for functions not available on all platforms is included here.
   26.28 
   26.29 // Case insensitive compare implemented in platform-specific way.
   26.30 int OVR_CDECL OVR_stricmp(const char* a, const char* b)
   26.31 {
   26.32 #if defined(OVR_OS_WIN32)
   26.33     #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
   26.34         return ::_stricmp(a, b);
   26.35     #else
   26.36         return ::stricmp(a, b);
   26.37     #endif
   26.38 
   26.39 #else
   26.40     return strcasecmp(a, b);
   26.41 #endif
   26.42 }
   26.43 
   26.44 int OVR_CDECL OVR_strnicmp(const char* a, const char* b, UPInt count)
   26.45 {
   26.46 #if defined(OVR_OS_WIN32)
   26.47 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
   26.48     return ::_strnicmp(a, b, count);
   26.49 #else
   26.50     return ::strnicmp(a, b, count);
   26.51 #endif
   26.52 
   26.53 #else
   26.54     return strncasecmp(a, b, count);
   26.55 #endif
   26.56 }
   26.57 
   26.58 wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src)
   26.59 {
   26.60 #if defined(OVR_MSVC_SAFESTRING)
   26.61     wcscpy_s(dest, destsize, src);
   26.62     return dest;
   26.63 #elif defined(OVR_OS_WIN32)
   26.64     OVR_UNUSED(destsize);
   26.65     wcscpy(dest, src);
   26.66     return dest;
   26.67 #else
   26.68     UPInt l = OVR_wcslen(src) + 1; // incl term null
   26.69     l = (l < destsize) ? l : destsize;
   26.70     memcpy(dest, src, l * sizeof(wchar_t));
   26.71     return dest;
   26.72 #endif
   26.73 }
   26.74 
   26.75 wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count)
   26.76 {
   26.77 #if defined(OVR_MSVC_SAFESTRING)
   26.78     wcsncpy_s(dest, destsize, src, count);
   26.79     return dest;
   26.80 #else
   26.81     UPInt srclen = OVR_wcslen(src);
   26.82     UPInt l = Alg::Min(srclen, count);
   26.83     l = (l < destsize) ? l : destsize;
   26.84     memcpy(dest, src, l * sizeof(wchar_t));
   26.85     if (count > srclen)
   26.86     {
   26.87         UPInt remLen = Alg::Min(destsize - l, (count - srclen));
   26.88         memset(&dest[l], 0, sizeof(wchar_t)*remLen);
   26.89     }
   26.90     else if (l < destsize)
   26.91         dest[l] = 0;
   26.92     return dest;
   26.93 #endif
   26.94 }
   26.95 
   26.96 
   26.97 wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src)
   26.98 {
   26.99 #if defined(OVR_MSVC_SAFESTRING)
  26.100     wcscat_s(dest, destsize, src);
  26.101     return dest;
  26.102 #elif defined(OVR_OS_WIN32)
  26.103     OVR_UNUSED(destsize);
  26.104     wcscat(dest, src);
  26.105     return dest;
  26.106 #else
  26.107     UPInt dstlen = OVR_wcslen(dest); // do not incl term null
  26.108     UPInt srclen = OVR_wcslen(src) + 1; // incl term null
  26.109     UPInt copylen = (dstlen + srclen < destsize) ? srclen : destsize - dstlen;
  26.110     memcpy(dest + dstlen, src, copylen * sizeof(wchar_t));
  26.111     return dest;
  26.112 #endif
  26.113 }
  26.114 
  26.115 UPInt   OVR_CDECL OVR_wcslen(const wchar_t* str)
  26.116 {
  26.117 #if defined(OVR_OS_WIN32)
  26.118     return wcslen(str);
  26.119 #else
  26.120     UPInt i = 0;
  26.121     while(str[i] != '\0')
  26.122         ++i;
  26.123     return i;
  26.124 #endif
  26.125 }
  26.126 
  26.127 int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b)
  26.128 {
  26.129 #if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX)
  26.130     return wcscmp(a, b);
  26.131 #else
  26.132     // not supported, use custom implementation
  26.133     const wchar_t *pa = a, *pb = b;
  26.134     while (*pa && *pb)
  26.135     {
  26.136         wchar_t ca = *pa;
  26.137         wchar_t cb = *pb;
  26.138         if (ca < cb)
  26.139             return -1;
  26.140         else if (ca > cb)
  26.141             return 1;
  26.142         pa++;
  26.143         pb++;
  26.144     }
  26.145     if (*pa)
  26.146         return 1;
  26.147     else if (*pb)
  26.148         return -1;
  26.149     else
  26.150         return 0;
  26.151 #endif
  26.152 }
  26.153 
  26.154 int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b)
  26.155 {
  26.156 #if defined(OVR_OS_WIN32)
  26.157 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
  26.158     return ::_wcsicmp(a, b);
  26.159 #else
  26.160     return ::wcsicmp(a, b);
  26.161 #endif
  26.162 #elif defined(OVR_OS_MAC) || defined(__CYGWIN__) || defined(OVR_OS_ANDROID) || defined(OVR_OS_IPHONE)
  26.163     // not supported, use custom implementation
  26.164     const wchar_t *pa = a, *pb = b;
  26.165     while (*pa && *pb)
  26.166     {
  26.167         wchar_t ca = OVR_towlower(*pa);
  26.168         wchar_t cb = OVR_towlower(*pb);
  26.169         if (ca < cb)
  26.170             return -1;
  26.171         else if (ca > cb)
  26.172             return 1;
  26.173         pa++;
  26.174         pb++;
  26.175     }
  26.176     if (*pa)
  26.177         return 1;
  26.178     else if (*pb)
  26.179         return -1;
  26.180     else
  26.181         return 0;
  26.182 #else
  26.183     return wcscasecmp(a, b);
  26.184 #endif
  26.185 }
  26.186 
  26.187 // This function is not inline because of dependency on <locale.h>
  26.188 double OVR_CDECL OVR_strtod(const char* string, char** tailptr)
  26.189 {
  26.190 #if !defined(OVR_OS_ANDROID)
  26.191     const char s = *localeconv()->decimal_point;
  26.192 
  26.193     if (s != '.')
  26.194     {
  26.195         char buffer[347 + 1];
  26.196 
  26.197         OVR_strcpy(buffer, sizeof(buffer), string);
  26.198 
  26.199         for (char* c = buffer; *c != '\0'; ++c)
  26.200         {
  26.201             if (*c == '.')
  26.202             {
  26.203                 *c = s;
  26.204                 break;
  26.205             }
  26.206         }
  26.207 
  26.208         return strtod(buffer, tailptr);
  26.209     }
  26.210 #endif
  26.211 
  26.212     return strtod(string, tailptr);
  26.213 }
  26.214 
  26.215 
  26.216 #ifndef OVR_NO_WCTYPE
  26.217 
  26.218 //// Use this class to generate Unicode bitsets. For example:
  26.219 ////
  26.220 //// UnicodeBitSet bitSet;
  26.221 //// for(unsigned i = 0; i < 65536; ++i)
  26.222 //// {
  26.223 ////     if (iswalpha(i))
  26.224 ////         bitSet.Set(i);
  26.225 //// }
  26.226 //// bitSet.Dump();
  26.227 ////
  26.228 ////---------------------------------------------------------------
  26.229 //class UnicodeBitSet
  26.230 //{
  26.231 //public:
  26.232 //    UnicodeBitSet()
  26.233 //    {
  26.234 //        memset(Offsets, 0, sizeof(Offsets));
  26.235 //        memset(Bits,    0, sizeof(Bits));
  26.236 //    }
  26.237 //
  26.238 //    void Set(unsigned bit) { Bits[bit >> 8][(bit >> 4) & 15] |= 1 << (bit & 15); }
  26.239 //
  26.240 //    void Dump()
  26.241 //    {
  26.242 //        unsigned i, j;
  26.243 //        unsigned offsetCount = 0;
  26.244 //        for(i = 0; i < 256; ++i)
  26.245 //        {
  26.246 //            if (isNull(i)) Offsets[i] = 0;
  26.247 //            else
  26.248 //            if (isFull(i)) Offsets[i] = 1;
  26.249 //            else           Offsets[i] = UInt16(offsetCount++ * 16 + 256);
  26.250 //        }
  26.251 //        for(i = 0; i < 16; ++i)
  26.252 //        {
  26.253 //            for(j = 0; j < 16; ++j)
  26.254 //            {
  26.255 //                printf("%5u,", Offsets[i*16+j]);
  26.256 //            }
  26.257 //            printf("\n");
  26.258 //        }
  26.259 //        for(i = 0; i < 256; ++i)
  26.260 //        {
  26.261 //            if (Offsets[i] > 255)
  26.262 //            {
  26.263 //                for(j = 0; j < 16; j++)
  26.264 //                {
  26.265 //                    printf("%5u,", Bits[i][j]);
  26.266 //                }
  26.267 //                printf("\n");
  26.268 //            }
  26.269 //        }
  26.270 //    }
  26.271 //
  26.272 //private:
  26.273 //    bool isNull(unsigned n) const
  26.274 //    {
  26.275 //        const UInt16* p = Bits[n];
  26.276 //        for(unsigned i = 0; i < 16; ++i)
  26.277 //            if (p[i] != 0) return false;
  26.278 //        return true;
  26.279 //    }
  26.280 //
  26.281 //    bool isFull(unsigned n) const
  26.282 //    {
  26.283 //        const UInt16* p = Bits[n];
  26.284 //        for(unsigned i = 0; i < 16; ++i)
  26.285 //            if (p[i] != 0xFFFF) return false;
  26.286 //        return true;
  26.287 //    }
  26.288 //
  26.289 //    UInt16 Offsets[256];
  26.290 //    UInt16 Bits[256][16];
  26.291 //};
  26.292 
  26.293 
  26.294 const UInt16 UnicodeAlnumBits[] = {
  26.295   256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
  26.296   480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
  26.297   640,  656,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.298   672,  688,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.299     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  704,    1,    1,
  26.300     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.301     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.302     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.303     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.304     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,
  26.305     1,    1,    1,    1,  736,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
  26.306     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.307     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.308     1,    1,    1,    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    0,
  26.309     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.310     0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  768,  784,    1,  800,  816,  832,
  26.311     0,    0,    0, 1023,65534, 2047,65534, 2047,    0,    0,    0,  524,65535,65407,65535,65407,
  26.312 65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
  26.313     0,    0,    0,    0,   32,    0,    0, 1024,55104,65535,65531,65535,32767,64767,65535,   15,
  26.314 65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
  26.315     0,    0,    0,65534,65535,  639,65534,65535,  255,    0,    0,    0,    0,65535, 2047,    7,
  26.316     0,    0,65534, 2047,65534,   63, 1023,65535,65535,65535,65535,65535,65535, 8175, 8702, 8191,
  26.317     0,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
  26.318 65518,65535,65535,58367, 8191,65281,65487,    0,40942,65529,65023,50117, 6559,45184,65487,    3,
  26.319 34788,65529,65023,50029, 6535,24064,65472,   31,45038,65531,65023,58349, 7103,    1,65473,    0,
  26.320 40942,65529,65023,58317, 6543,45248,65475,    0,51180,54845,50968,50111, 7623,  128,65408,    0,
  26.321 57326,65533,65023,50159, 7647,   96,65475,    0,57324,65533,65023,50159, 7647,16480,65475,    0,
  26.322 57324,65533,65023,50175, 7631,  128,65475,    0,65516,64639,65535,12283,32895,65375,    0,   12,
  26.323 65534,65535,65535, 2047,32767, 1023,    0,    0, 9622,65264,60590,15359, 8223,13311,    0,    0,
  26.324     1,    0, 1023,    0,65279,65535, 2047,65534, 3843,65279,65535, 8191,    0,    0,    0,    0,
  26.325 65535,65535,63227,  327, 1023, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535,  127,
  26.326 65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
  26.327 65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
  26.328 32767,32573,65535,65535,65407, 2047,65024,    3,    0,    0,65535,65535,65535,65535,65535,   31,
  26.329 65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
  26.330 65535,65535,65535,65535,65535,65535,40959,  127,65534, 2047,65535,65535,65535,65535, 2047,    0,
  26.331     0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511,    0, 1023,    0,
  26.332     0, 1023,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
  26.333 65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
  26.334 65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
  26.335     0,    0,    0,    0,    0,    0,    0,32768,    0,    0,    0,    0,    0,    0,    0,    0,
  26.336 64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
  26.337   192,    0, 1022, 1792,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 2047,
  26.338 65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
  26.339 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
  26.340 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
  26.341 65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
  26.342 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
  26.343 65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.344   127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
  26.345 65535,65535,65535,16383,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
  26.346     0,    0,    0,    0,    0,    0,    0,65495,65535,65535,65535,65535,65535,65535,65535, 8191,
  26.347     0, 1023,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
  26.348 
  26.349 const UInt16 UnicodeAlphaBits[] = {
  26.350   256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
  26.351   480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
  26.352   640,  656,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.353   672,  688,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.354     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  704,    1,    1,
  26.355     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.356     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.357     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.358     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.359     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,
  26.360     1,    1,    1,    1,  736,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
  26.361     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.362     1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.363     1,    1,    1,    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    0,
  26.364     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.365     0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  768,  784,    1,  800,  816,  832,
  26.366     0,    0,    0,    0,65534, 2047,65534, 2047,    0,    0,    0,    0,65535,65407,65535,65407,
  26.367 65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
  26.368     0,    0,    0,    0,   32,    0,    0, 1024,55104,65535,65531,65535,32767,64767,65535,   15,
  26.369 65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
  26.370     0,    0,    0,65534,65535,  639,65534,65535,  255,    0,    0,    0,    0,65535, 2047,    7,
  26.371     0,    0,65534, 2047,65534,   63,    0,65535,65535,65535,65535,65535,65535, 8175, 8702, 7168,
  26.372     0,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
  26.373 65518,65535,65535,58367, 8191,65281,   15,    0,40942,65529,65023,50117, 6559,45184,   15,    3,
  26.374 34788,65529,65023,50029, 6535,24064,    0,   31,45038,65531,65023,58349, 7103,    1,    1,    0,
  26.375 40942,65529,65023,58317, 6543,45248,    3,    0,51180,54845,50968,50111, 7623,  128,    0,    0,
  26.376 57326,65533,65023,50159, 7647,   96,    3,    0,57324,65533,65023,50159, 7647,16480,    3,    0,
  26.377 57324,65533,65023,50175, 7631,  128,    3,    0,65516,64639,65535,12283,32895,65375,    0,   12,
  26.378 65534,65535,65535, 2047,32767,    0,    0,    0, 9622,65264,60590,15359, 8223,12288,    0,    0,
  26.379     1,    0,    0,    0,65279,65535, 2047,65534, 3843,65279,65535, 8191,    0,    0,    0,    0,
  26.380 65535,65535,63227,  327,    0, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535,  127,
  26.381 65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
  26.382 65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
  26.383 32767,32573,65535,65535,65407, 2047,    0,    0,    0,    0,65535,65535,65535,65535,65535,   31,
  26.384 65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
  26.385 65535,65535,65535,65535,65535,65535,40959,  127,65534, 2047,65535,65535,65535,65535, 2047,    0,
  26.386     0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511,    0,    0,    0,
  26.387     0,    0,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
  26.388 65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
  26.389 65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
  26.390     0,    0,    0,    0,    0,    0,    0,32768,    0,    0,    0,    0,    0,    0,    0,    0,
  26.391 64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
  26.392   192,    0, 1022, 1792,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 2047,
  26.393 65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
  26.394 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
  26.395 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
  26.396 65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
  26.397 65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
  26.398 65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.399   127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
  26.400 65535,65535,65535,16383,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
  26.401     0,    0,    0,    0,    0,    0,    0,65495,65535,65535,65535,65535,65535,65535,65535, 8191,
  26.402     0,    0,65534, 2047,65534, 2047,65472,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
  26.403 
  26.404 const UInt16 UnicodeDigitBits[] = {
  26.405   256,    0,    0,    0,    0,    0,  272,    0,    0,  288,  304,  320,  336,  352,  368,  384,
  26.406   400,    0,    0,  416,    0,    0,    0,  432,  448,    0,    0,    0,    0,    0,    0,    0,
  26.407     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.408     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.409     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.410     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.411     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.412     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.413     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.414     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.415     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.416     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.417     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.418     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.419     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.420     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  464,
  26.421     0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,  524,    0,    0,    0,    0,
  26.422     0,    0,    0,    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0, 1023,
  26.423     0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65472,    0,
  26.424     0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65472,    0,
  26.425     0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65408,    0,
  26.426     0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,65472,    0,
  26.427     0,    0,    0,    0,    0,    0,65472,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.428     0,    0,    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0, 1023,    0,    0,
  26.429     0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.430     0,    0,    0,    0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.431     0,    0,    0,    0,    0,    0,65024,    3,    0,    0,    0,    0,    0,    0,    0,    0,
  26.432     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 1023,    0,
  26.433     0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.434     0, 1023,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  26.435 
  26.436 const UInt16 UnicodeSpaceBits[] = {
  26.437   256,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.438     0,    0,    0,    0,    0,    0,  272,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.439   288,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.440   304,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.441     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.442     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.443     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.444     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.445     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.446     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.447     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.448     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.449     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.450     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.451     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.452     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.453 15872,    0,    1,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,    0,    0,
  26.454     0,    0,    0,    0,    0,    0,    0,    0,    1,    0,    0,    0,    0,    0,    0,    0,
  26.455  4095,    0,33536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.456     1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  26.457 
  26.458 const UInt16 UnicodeXDigitBits[] = {
  26.459   256,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.460     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.461     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.462     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.463     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.464     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.465     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.466     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.467     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.468     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.469     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.470     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.471     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.472     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.473     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.474     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  272,
  26.475     0,    0,    0, 1023,  126,    0,  126,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.476     0, 1023,  126,    0,  126,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  26.477 
  26.478 // Uncomment if necessary
  26.479 //const UInt16 UnicodeCntrlBits[] = {
  26.480 //  256,    0,    0,    0,    0,    0,    0,  272,    0,    0,    0,    0,    0,    0,    0,    0,
  26.481 //    0,    0,    0,    0,    0,    0,    0,    0,  288,    0,    0,    0,    0,    0,    0,    0,
  26.482 //  304,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.483 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.484 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.485 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.486 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.487 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.488 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.489 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.490 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.491 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.492 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.493 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.494 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.495 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  320,  336,
  26.496 //65535,65535,    0,    0,    0,    0,    0,32768,65535,65535,    0,    0,    0,    0,    0,    0,
  26.497 //32768,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.498 //30720,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.499 //61440,    0,31744,    0,    0,    0,64512,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.500 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,32768,
  26.501 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 3584};
  26.502 //
  26.503 //const UInt16 UnicodeGraphBits[] = {
  26.504 //  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
  26.505 //  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
  26.506 //  640,  656,    0,  672,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.507 //  688,  704,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.508 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,    1,    1,
  26.509 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.510 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.511 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.512 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.513 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  736,
  26.514 //    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
  26.515 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.516 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.517 //    1,    1,    1,    1,    1,    1,    1,  768,    0,    0,    0,    0,    0,    0,    0,    0,
  26.518 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.519 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  784,  800,    1,  816,  832,  848,
  26.520 //    0,    0,65534,65535,65535,65535,65535,32767,    0,    0,65534,65535,65535,65535,65535,65535,
  26.521 //65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
  26.522 //    0,    0,    0,    0,   32,    0,    0,17408,55232,65535,65531,65535,32767,64767,65535,   15,
  26.523 //65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
  26.524 //    0,    0,    0,65534,65535,65151,65534,65535, 1791,    0,    0,16384,    9,65535, 2047,   31,
  26.525 // 4096,34816,65534, 2047,65534,   63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191,
  26.526 //16383,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
  26.527 //65518,65535,65535,58367, 8191,65281,65535,    1,40942,65529,65023,50117, 6559,45184,65487,    3,
  26.528 //34788,65529,65023,50029, 6535,24064,65472,   31,45038,65531,65023,58349, 7103,    1,65473,    0,
  26.529 //40942,65529,65023,58317, 6543,45248,65475,    0,51180,54845,50968,50111, 7623,  128,65408,    0,
  26.530 //57326,65533,65023,50159, 7647,   96,65475,    0,57324,65533,65023,50159, 7647,16480,65475,    0,
  26.531 //57324,65533,65023,50175, 7631,  128,65475,    0,65516,64639,65535,12283,32895,65375,    0,   28,
  26.532 //65534,65535,65535, 2047,65535, 4095,    0,    0, 9622,65264,60590,15359, 8223,13311,    0,    0,
  26.533 //65521,    7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191,    0,    0,    0,    0,
  26.534 //65535,65535,63227,  327,65535, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535, 2175,
  26.535 //65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
  26.536 //65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
  26.537 //32767,32573,65535,65535,65407, 2047,65534,    3,    0,    0,65535,65535,65535,65535,65535,   31,
  26.538 //65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
  26.539 //65535,65535,65535,65535,65535,65535,65535,  127,65534, 8191,65535,65535,65535,65535,16383,    0,
  26.540 //    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511, 6128, 1023,    0,
  26.541 // 2047, 1023,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
  26.542 //65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
  26.543 //65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
  26.544 //    0,65535,  255,65535,16239,    0,    0,57344,24576,    0,    0,    0,    0,    0,    0,    0,
  26.545 //64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
  26.546 //    0,    0, 1536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.547 //65486,65523, 1022, 1793,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 4095,
  26.548 //65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
  26.549 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
  26.550 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
  26.551 //65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
  26.552 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
  26.553 //65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.554 //  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
  26.555 //65535,65535,65535,65535,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
  26.556 //    0,    0,    0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535, 8191,
  26.557 //63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
  26.558 //
  26.559 //const UInt16 UnicodePrintBits[] = {
  26.560 //  256,    1,  272,  288,  304,  320,  336,  352,    0,  368,  384,  400,  416,  432,  448,  464,
  26.561 //  480,  496,  512,  528,  544,    1,  560,  576,  592,    0,    0,    0,    0,    0,  608,  624,
  26.562 //  640,  656,    0,  672,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.563 //  688,  704,    0,    0,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.564 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  720,    1,    1,
  26.565 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.566 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.567 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.568 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.569 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,  736,
  26.570 //    1,    1,    1,    1,  752,    0,    0,    0,    0,    0,    0,    0,    1,    1,    1,    1,
  26.571 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.572 //    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
  26.573 //    1,    1,    1,    1,    1,    1,    1,  768,    0,    0,    0,    0,    0,    0,    0,    0,
  26.574 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.575 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,  784,  800,    1,  816,  832,  848,
  26.576 //  512,    0,65535,65535,65535,65535,65535,32767,    0,    0,65535,65535,65535,65535,65535,65535,
  26.577 //65535,65535,65532,   15,    0,65535,65535,65535,65535,65535,16383,63999,    3,    0,16415,    0,
  26.578 //    0,    0,    0,    0,   32,    0,    0,17408,55232,65535,65531,65535,32767,64767,65535,   15,
  26.579 //65535,65535,65535,65535,65535,65535,65535,65535,61443,65535,65535,65535, 6559,65535,65535,  831,
  26.580 //    0,    0,    0,65534,65535,65151,65534,65535, 1791,    0,    0,16384,    9,65535, 2047,   31,
  26.581 // 4096,34816,65534, 2047,65534,   63,16383,65535,65535,65535,65535,65535,65535, 8191, 8702, 8191,
  26.582 //16383,65535, 8191,65535,    0,    0,    0,    0,65535,65535,65535,    1,    0,    0,    0,    0,
  26.583 //65518,65535,65535,58367, 8191,65281,65535,    1,40942,65529,65023,50117, 6559,45184,65487,    3,
  26.584 //34788,65529,65023,50029, 6535,24064,65472,   31,45038,65531,65023,58349, 7103,    1,65473,    0,
  26.585 //40942,65529,65023,58317, 6543,45248,65475,    0,51180,54845,50968,50111, 7623,  128,65408,    0,
  26.586 //57326,65533,65023,50159, 7647,   96,65475,    0,57324,65533,65023,50159, 7647,16480,65475,    0,
  26.587 //57324,65533,65023,50175, 7631,  128,65475,    0,65516,64639,65535,12283,32895,65375,    0,   28,
  26.588 //65534,65535,65535, 2047,65535, 4095,    0,    0, 9622,65264,60590,15359, 8223,13311,    0,    0,
  26.589 //65521,    7, 1023,15360,65279,65535, 2047,65534, 3875,65279,65535, 8191,    0,    0,    0,    0,
  26.590 //65535,65535,63227,  327,65535, 1023,    0,    0,    0,    0,65535,65535,   63,65535,65535, 2175,
  26.591 //65535,65535,65535,65535,65535,33791,65535,65535,65535,65535,65287,65535,65535,65535,65535, 1023,
  26.592 //65407,65535,65535,65535,15743,15743,65535,65535,15743,65535,32767,32573,32573,65407,32767,65535,
  26.593 //32767,32573,65535,65535,65407, 2047,65534,    3,    0,    0,65535,65535,65535,65535,65535,   31,
  26.594 //65534,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,
  26.595 //65535,65535,65535,65535,65535,65535,65535,  127,65534, 8191,65535,65535,65535,65535,16383,    0,
  26.596 //    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,65535,65535,  511, 6128, 1023,    0,
  26.597 // 2047, 1023,65535,65535,65527,65535,65535,  255,65535,65535, 1023,    0,    0,    0,    0,    0,
  26.598 //65535,65535,65535,65535,65535,65535,65535,65535,65535, 4095,65535,65535,65535,65535,65535, 1023,
  26.599 //65535,16191,65535,65535,16191,43775,65535,16383,65535,65535,65535,24543, 8156, 4047, 8191, 8156,
  26.600 //    0,65535,  255,65535,16239,    0,    0,57344,24576,    0,    0,    0,    0,    0,    0,    0,
  26.601 //64644,15919,48464, 1019,    0,    0,65535,65535,   15,    0,    0,    0,    0,    0,    0,    0,
  26.602 //    0,    0, 1536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.603 //65487,65523, 1022, 1793,65534,65535,65535,65535,65535,   31,65534,65535,65535,65535,65535, 4095,
  26.604 //65504,65535, 8191,65534,65535,65535,65535,65535,32767,    0,65535,  255,    0,    0,    0,    0,
  26.605 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,
  26.606 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   63,    0,    0,    0,    0,    0,
  26.607 //65535,65535,65535,65535,65535,65535,65535,65535, 8191,    0,    0,    0,    0,    0,    0,    0,
  26.608 //65535,65535,65535,65535,65535,65535,65535,65535,65535,65535,   15,    0,    0,    0,    0,    0,
  26.609 //65535,65535,16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.610 //  127,41208,65023,24447,65499,65535,65535,65535,65535,65535,65535,    3,    0,65528,65535,65535,
  26.611 //65535,65535,65535,65535,    0,65535,65535,65535,65535,65532,65535,65535,  255,    0,    0, 4095,
  26.612 //    0,    0,    0,65535,65055,65527, 3339,65495,65535,65535,65535,65535,65535,65535,65535,40959,
  26.613 //63470,36863,65535,49151,65534,12287,65534,65534,65535,16383,65535,32767,64764, 7420,    0,    0};
  26.614 //
  26.615 //const UInt16 UnicodePunctBits[] = {
  26.616 //  256,    0,    0,  272,    0,  288,  304,  320,    0,  336,    0,    0,    0,  352,  368,  384,
  26.617 //  400,    0,    0,  416,    0,    0,  432,  448,  464,    0,    0,    0,    0,    0,    0,    0,
  26.618 //  480,    0,    0,  496,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.619 //  512,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.620 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.621 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.622 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.623 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.624 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.625 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.626 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.627 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.628 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.629 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.630 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.631 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  528,  544,  560,
  26.632 //    0,    0,65534,64512,    1,63488,    1,30720,    0,    0,65534,65535,    0,  128,    0,  128,
  26.633 //    0,    0,    0,    0,    0,    0,    0,16384,  128,    0,    0,    0,    0,    0,    0,    0,
  26.634 //    0,    0,    0,    0,    0,64512,    0,    0, 1536,    0,    0,16384,    9,    0,    0,   24,
  26.635 // 4096,34816,    0,    0,    0,    0,15360,    0,    0,    0,    0,    0,    0,   16,    0,    0,
  26.636 //16383,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.637 //    0,    0,    0,    0,    0,    0,   48,    1,    0,    0,    0,    0,    0,    0,    0,    0,
  26.638 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   16,
  26.639 //    0,    0,    0,    0,32768, 3072,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.640 //65520,    7,    0,15360,    0,    0,    0,    0,   32,    0,    0,    0,    0,    0,    0,    0,
  26.641 //    0,    0,    0,    0,64512,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 2048,
  26.642 //    0,    0,    0,    0,    0,    0,  510,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.643 //    0,    0,    0,    0,    0,    0,24576,    0,    0, 6144,    0,    0,    0,    0,14336,    0,
  26.644 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 6128,    0,    0,
  26.645 // 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.646 //    0,65535,  255,65535,16239,    0,    0,24576,24576,    0,    0,    0,    0,    0,    0,    0,
  26.647 //    0,    0, 1536,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.648 //65294,65523,    0,    1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, 2048,
  26.649 //    0,    0,    0,49152,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.650 //    0,    0,    0,65535,65055,65527, 3339,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.651 //63470,35840,    1,47104,    0,10240,   62,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  26.652 //
  26.653 //const UInt16 UnicodeLowerBits[] = {
  26.654 //  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.655 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  352,  368,
  26.656 //  384,  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.657 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.658 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.659 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.660 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.661 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.662 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.663 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.664 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.665 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.666 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.667 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.668 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.669 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  416,    0,    0,    0,  432,
  26.670 //    0,    0,    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,32768,65535,65407,
  26.671 //43690,43690,43690,21930,43861,43690,43690,54442,12585,20004,11562,58961,23392,46421,43690,43565,
  26.672 //43690,43690,43688,   10,    0,65535,65535,65535,65535,65535,16383,    0,    0,    0,    0,    0,
  26.673 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    1,61440,65535,32767,43235,43690,   15,
  26.674 //    0,    0,    0,65535,65535,65535,43690,43690,40962,43690,43690,43690, 4372,43690,43690,  554,
  26.675 //    0,    0,    0,    0,    0,    0,65534,65535,  255,    0,    0,    0,    0,    0,    0,    0,
  26.676 //43690,43690,43690,43690,43690,43690,43690,43690,43690, 4074,43690,43690,43690,43690,43690,  682,
  26.677 //  255,   63,  255,  255,   63,  255,  255,16383,65535,65535,65535,20703, 4316,  207,  255, 4316,
  26.678 //    0,    0,    0,    0,    0,    0,    0,32768,    0,    0,    0,    0,    0,    0,    0,    0,
  26.679 //50176,    8,32768,  528,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.680 //  127,  248,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.681 //    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  26.682 //
  26.683 //const UInt16 UnicodeUpperBits[] = {
  26.684 //  256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.685 //  352,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  368,  384,
  26.686 //    0,  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.687 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.688 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.689 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.690 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.691 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.692 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.693 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.694 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.695 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.696 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.697 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.698 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.699 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  416,
  26.700 //    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,65535,32639,    0,    0,
  26.701 //21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53973, 4526,44464,19114,21845,21974,
  26.702 //21845,21845,21844,    5,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.703 //    0,    0,    0,    0,    0,    0,    0,    0,55104,65534, 4091,    0,    0,21532,21845,    0,
  26.704 //65535,65535,65535,    0,    0,    0,21845,21845,20481,21845,21845,21845, 2187,21845,21845,  277,
  26.705 //    0,    0,    0,65534,65535,  127,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.706 //    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,   63,    0,    0,    0,
  26.707 //21845,21845,21845,21845,21845,21845,21845,21845,21845,   21,21845,21845,21845,21845,21845,  341,
  26.708 //65280,16128,65280,65280,16128,43520,65280,    0,65280,65280,65280, 7936, 7936, 3840, 7936, 7936,
  26.709 //14468,15911,15696,   11,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.710 //    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  26.711 
  26.712 
  26.713 // MA: March 19, 2010
  26.714 // Modified ToUpper and ToLower tables to match values expected by AS3 tests.
  26.715 // ToLower modifications:
  26.716 //    304 ->  105
  26.717 //   1024 -> 1104 *
  26.718 //   1037 -> 1117 * 
  26.719 // UoUpper modifications:
  26.720 //    255 ->  376
  26.721 //    305 ->   73
  26.722 //    383 ->   83
  26.723 //   1104 -> 1024 *
  26.724 //   1117 -> 1037 *
  26.725 // Entries marked with a '*' don't make complete sense based on Unicode manual, although
  26.726 // they match AS3.
  26.727 
  26.728 
  26.729 static const UInt16 UnicodeToUpperBits[] = {
  26.730   256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.731     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  352,  368,
  26.732     0,  384,    0,    0,  400,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.733     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.734     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.735     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.736     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.737     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.738     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.739     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.740     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.741     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.742     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.743     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.744     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.745     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  416,
  26.746     0,    0,    0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,65535,65407,
  26.747 43690,43690,43690,21674,43349,43690,43690,54442, 4392,  516, 8490, 8785,21056,46421,43690,43048, // MA: Modified for AS3.
  26.748 43690,  170,    0,    0,    0, 2776,33545,   36, 3336,    4,    0,    0,    0,    0,    0,    0,
  26.749     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,61440,65534,32767,    0,43688,    0,
  26.750     0,    0,    0,65535,65535,65535,43690,43690,    2,43690,43690,43690, 4372,43690,35498,  554, // MA: Modified for AS3.
  26.751     0,    0,    0,    0,    0,    0,65534,65535,  127,    0,    0,    0,    0,    0,    0,    0,
  26.752 43690,43690,43690,43690,43690,43690,43690,43690,43690,   42,43690,43690,43690,43690,43690,  682,
  26.753   255,   63,  255,  255,   63,  170,  255,16383,    0,    0,    0,    3,    0,    3,   35,    0,
  26.754     0,    0,    0,    0,    0,    0,    0,65535,    0,    0,    0,    0,    0,    0,    0,    0,
  26.755     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65535, 1023,    0,
  26.756     0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  26.757 
  26.758 static const UInt16 UnicodeToLowerBits[] = {
  26.759   256,  272,  288,  304,  320,  336,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.760   352,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  368,  384,
  26.761     0,  400,    0,    0,  416,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.762     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.763     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.764     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.765     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.766     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.767     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.768     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.769     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.770     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.771     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.772     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.773     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.774     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,  432,
  26.775     0,    0,    0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,65535,32639,    0,    0,
  26.776 21845,21845,21845,43605,21674,21845,21845,11093,52950,45531,53909, 4526,42128,19114,21845,21522,// MA: Modidied for AS3.
  26.777 21845,   85,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.778     0,    0,    0,    0,    0,    0,    0,    0,55104,65534, 4091,    0,    0,    0,21844,    0,
  26.779 65535,65535,65535,    0,    0,    0,21845,21845,    1,21845,21845,21845, 2186,21845,17749,  277,
  26.780     0,    0,    0,65534,65535,  127,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.781     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65535,65535,   63,    0,    0,    0,
  26.782 21845,21845,21845,21845,21845,21845,21845,21845,21845,   21,21845,21845,21845,21845,21845,  341,
  26.783 65280,16128,65280,65280,16128,43520,65280,    0,    0,    0,    0, 3840, 3840, 3840, 7936, 3840,
  26.784     0,    0,    0,    0,    0,    0,65535,    0,    0,    0,    0,    0,    0,    0,    0,    0,
  26.785     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,65472,65535,    0,    0,    0,
  26.786     0,    0,65534, 2047,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0};
  26.787 
  26.788 struct GUnicodePairType
  26.789 {
  26.790     UInt16 Key, Value;
  26.791 };
  26.792 
  26.793 static inline bool CmpUnicodeKey(const GUnicodePairType& a, UInt16 key)
  26.794 {
  26.795     return a.Key < key;
  26.796 }
  26.797 
  26.798 static const GUnicodePairType UnicodeToUpperTable[] = {
  26.799 {   97,   65}, {   98,   66}, {   99,   67}, {  100,   68}, {  101,   69}, {  102,   70}, {  103,   71},
  26.800 {  104,   72}, {  105,   73}, {  106,   74}, {  107,   75}, {  108,   76}, {  109,   77}, {  110,   78},
  26.801 {  111,   79}, {  112,   80}, {  113,   81}, {  114,   82}, {  115,   83}, {  116,   84}, {  117,   85},
  26.802 {  118,   86}, {  119,   87}, {  120,   88}, {  121,   89}, {  122,   90}, {  224,  192}, {  225,  193},
  26.803 {  226,  194}, {  227,  195}, {  228,  196}, {  229,  197}, {  230,  198}, {  231,  199}, {  232,  200},
  26.804 {  233,  201}, {  234,  202}, {  235,  203}, {  236,  204}, {  237,  205}, {  238,  206}, {  239,  207},
  26.805 {  240,  208}, {  241,  209}, {  242,  210}, {  243,  211}, {  244,  212}, {  245,  213}, {  246,  214},
  26.806 {  248,  216}, {  249,  217}, {  250,  218}, {  251,  219}, {  252,  220}, {  253,  221}, {  254,  222},
  26.807 {  255,  376}, {  257,  256}, {  259,  258}, {  261,  260}, {  263,  262}, {  265,  264}, {  267,  266},
  26.808 {  269,  268}, {  271,  270}, {  273,  272}, {  275,  274}, {  277,  276}, {  279,  278}, {  281,  280},
  26.809 {  283,  282}, {  285,  284}, {  287,  286}, {  289,  288}, {  291,  290}, {  293,  292}, {  295,  294},
  26.810 {  297,  296}, {  299,  298}, {  301,  300}, {  303,  302}, {  305,   73}, {  307,  306}, {  309,  308}, {  311,  310},
  26.811 {  314,  313}, {  316,  315}, {  318,  317}, {  320,  319}, {  322,  321}, {  324,  323}, {  326,  325},
  26.812 {  328,  327}, {  331,  330}, {  333,  332}, {  335,  334}, {  337,  336}, {  339,  338}, {  341,  340},
  26.813 {  343,  342}, {  345,  344}, {  347,  346}, {  349,  348}, {  351,  350}, {  353,  352}, {  355,  354},
  26.814 {  357,  356}, {  359,  358}, {  361,  360}, {  363,  362}, {  365,  364}, {  367,  366}, {  369,  368},
  26.815 {  371,  370}, {  373,  372}, {  375,  374}, {  378,  377}, {  380,  379}, {  382,  381}, {  383,   83}, {  387,  386},
  26.816 {  389,  388}, {  392,  391}, {  396,  395}, {  402,  401}, {  409,  408}, {  417,  416}, {  419,  418},
  26.817 {  421,  420}, {  424,  423}, {  429,  428}, {  432,  431}, {  436,  435}, {  438,  437}, {  441,  440},
  26.818 {  445,  444}, {  454,  452}, {  457,  455}, {  460,  458}, {  462,  461}, {  464,  463}, {  466,  465},
  26.819 {  468,  467}, {  470,  469}, {  472,  471}, {  474,  473}, {  476,  475}, {  477,  398}, {  479,  478},
  26.820 {  481,  480}, {  483,  482}, {  485,  484}, {  487,  486}, {  489,  488}, {  491,  490}, {  493,  492},
  26.821 {  495,  494}, {  499,  497}, {  501,  500}, {  507,  506}, {  509,  508}, {  511,  510}, {  513,  512},
  26.822 {  515,  514}, {  517,  516}, {  519,  518}, {  521,  520}, {  523,  522}, {  525,  524}, {  527,  526},
  26.823 {  529,  528}, {  531,  530}, {  533,  532}, {  535,  534}, {  595,  385}, {  596,  390}, {  598,  393},
  26.824 {  599,  394}, {  601,  399}, {  603,  400}, {  608,  403}, {  611,  404}, {  616,  407}, {  617,  406},
  26.825 {  623,  412}, {  626,  413}, {  629,  415}, {  643,  425}, {  648,  430}, {  650,  433}, {  651,  434},
  26.826 {  658,  439}, {  940,  902}, {  941,  904}, {  942,  905}, {  943,  906}, {  945,  913}, {  946,  914},
  26.827 {  947,  915}, {  948,  916}, {  949,  917}, {  950,  918}, {  951,  919}, {  952,  920}, {  953,  921},
  26.828 {  954,  922}, {  955,  923}, {  956,  924}, {  957,  925}, {  958,  926}, {  959,  927}, {  960,  928},
  26.829 {  961,  929}, {  962,  931}, {  963,  931}, {  964,  932}, {  965,  933}, {  966,  934}, {  967,  935},
  26.830 {  968,  936}, {  969,  937}, {  970,  938}, {  971,  939}, {  972,  908}, {  973,  910}, {  974,  911},
  26.831 {  995,  994}, {  997,  996}, {  999,  998}, { 1001, 1000}, { 1003, 1002}, { 1005, 1004}, { 1007, 1006},
  26.832 { 1072, 1040}, { 1073, 1041}, { 1074, 1042}, { 1075, 1043}, { 1076, 1044}, { 1077, 1045}, { 1078, 1046},
  26.833 { 1079, 1047}, { 1080, 1048}, { 1081, 1049}, { 1082, 1050}, { 1083, 1051}, { 1084, 1052}, { 1085, 1053},
  26.834 { 1086, 1054}, { 1087, 1055}, { 1088, 1056}, { 1089, 1057}, { 1090, 1058}, { 1091, 1059}, { 1092, 1060},
  26.835 { 1093, 1061}, { 1094, 1062}, { 1095, 1063}, { 1096, 1064}, { 1097, 1065}, { 1098, 1066}, { 1099, 1067},
  26.836 { 1100, 1068}, { 1101, 1069}, { 1102, 1070}, { 1103, 1071}, { 1104, 1024}, { 1105, 1025}, { 1106, 1026}, { 1107, 1027},
  26.837 { 1108, 1028}, { 1109, 1029}, { 1110, 1030}, { 1111, 1031}, { 1112, 1032}, { 1113, 1033}, { 1114, 1034},
  26.838 { 1115, 1035}, { 1116, 1036}, { 1117, 1037}, { 1118, 1038}, { 1119, 1039}, { 1121, 1120}, { 1123, 1122}, { 1125, 1124},
  26.839 { 1127, 1126}, { 1129, 1128}, { 1131, 1130}, { 1133, 1132}, { 1135, 1134}, { 1137, 1136}, { 1139, 1138},
  26.840 { 1141, 1140}, { 1143, 1142}, { 1145, 1144}, { 1147, 1146}, { 1149, 1148}, { 1151, 1150}, { 1153, 1152},
  26.841 { 1169, 1168}, { 1171, 1170}, { 1173, 1172}, { 1175, 1174}, { 1177, 1176}, { 1179, 1178}, { 1181, 1180},
  26.842 { 1183, 1182}, { 1185, 1184}, { 1187, 1186}, { 1189, 1188}, { 1191, 1190}, { 1193, 1192}, { 1195, 1194},
  26.843 { 1197, 1196}, { 1199, 1198}, { 1201, 1200}, { 1203, 1202}, { 1205, 1204}, { 1207, 1206}, { 1209, 1208},
  26.844 { 1211, 1210}, { 1213, 1212}, { 1215, 1214}, { 1218, 1217}, { 1220, 1219}, { 1224, 1223}, { 1228, 1227},
  26.845 { 1233, 1232}, { 1235, 1234}, { 1237, 1236}, { 1239, 1238}, { 1241, 1240}, { 1243, 1242}, { 1245, 1244},
  26.846 { 1247, 1246}, { 1249, 1248}, { 1251, 1250}, { 1253, 1252}, { 1255, 1254}, { 1257, 1256}, { 1259, 1258},
  26.847 { 1263, 1262}, { 1265, 1264}, { 1267, 1266}, { 1269, 1268}, { 1273, 1272}, { 1377, 1329}, { 1378, 1330},
  26.848 { 1379, 1331}, { 1380, 1332}, { 1381, 1333}, { 1382, 1334}, { 1383, 1335}, { 1384, 1336}, { 1385, 1337},
  26.849 { 1386, 1338}, { 1387, 1339}, { 1388, 1340}, { 1389, 1341}, { 1390, 1342}, { 1391, 1343}, { 1392, 1344},
  26.850 { 1393, 1345}, { 1394, 1346}, { 1395, 1347}, { 1396, 1348}, { 1397, 1349}, { 1398, 1350}, { 1399, 1351},
  26.851 { 1400, 1352}, { 1401, 1353}, { 1402, 1354}, { 1403, 1355}, { 1404, 1356}, { 1405, 1357}, { 1406, 1358},
  26.852 { 1407, 1359}, { 1408, 1360}, { 1409, 1361}, { 1410, 1362}, { 1411, 1363}, { 1412, 1364}, { 1413, 1365},
  26.853 { 1414, 1366}, { 7681, 7680}, { 7683, 7682}, { 7685, 7684}, { 7687, 7686}, { 7689, 7688}, { 7691, 7690},
  26.854 { 7693, 7692}, { 7695, 7694}, { 7697, 7696}, { 7699, 7698}, { 7701, 7700}, { 7703, 7702}, { 7705, 7704},
  26.855 { 7707, 7706}, { 7709, 7708}, { 7711, 7710}, { 7713, 7712}, { 7715, 7714}, { 7717, 7716}, { 7719, 7718},
  26.856 { 7721, 7720}, { 7723, 7722}, { 7725, 7724}, { 7727, 7726}, { 7729, 7728}, { 7731, 7730}, { 7733, 7732},
  26.857 { 7735, 7734}, { 7737, 7736}, { 7739, 7738}, { 7741, 7740}, { 7743, 7742}, { 7745, 7744}, { 7747, 7746},
  26.858 { 7749, 7748}, { 7751, 7750}, { 7753, 7752}, { 7755, 7754}, { 7757, 7756}, { 7759, 7758}, { 7761, 7760},
  26.859 { 7763, 7762}, { 7765, 7764}, { 7767, 7766}, { 7769, 7768}, { 7771, 7770}, { 7773, 7772}, { 7775, 7774},
  26.860 { 7777, 7776}, { 7779, 7778}, { 7781, 7780}, { 7783, 7782}, { 7785, 7784}, { 7787, 7786}, { 7789, 7788},
  26.861 { 7791, 7790}, { 7793, 7792}, { 7795, 7794}, { 7797, 7796}, { 7799, 7798}, { 7801, 7800}, { 7803, 7802},
  26.862 { 7805, 7804}, { 7807, 7806}, { 7809, 7808}, { 7811, 7810}, { 7813, 7812}, { 7815, 7814}, { 7817, 7816},
  26.863 { 7819, 7818}, { 7821, 7820}, { 7823, 7822}, { 7825, 7824}, { 7827, 7826}, { 7829, 7828}, { 7841, 7840},
  26.864 { 7843, 7842}, { 7845, 7844}, { 7847, 7846}, { 7849, 7848}, { 7851, 7850}, { 7853, 7852}, { 7855, 7854},
  26.865 { 7857, 7856}, { 7859, 7858}, { 7861, 7860}, { 7863, 7862}, { 7865, 7864}, { 7867, 7866}, { 7869, 7868},
  26.866 { 7871, 7870}, { 7873, 7872}, { 7875, 7874}, { 7877, 7876}, { 7879, 7878}, { 7881, 7880}, { 7883, 7882},
  26.867 { 7885, 7884}, { 7887, 7886}, { 7889, 7888}, { 7891, 7890}, { 7893, 7892}, { 7895, 7894}, { 7897, 7896},
  26.868 { 7899, 7898}, { 7901, 7900}, { 7903, 7902}, { 7905, 7904}, { 7907, 7906}, { 7909, 7908}, { 7911, 7910},
  26.869 { 7913, 7912}, { 7915, 7914}, { 7917, 7916}, { 7919, 7918}, { 7921, 7920}, { 7923, 7922}, { 7925, 7924},
  26.870 { 7927, 7926}, { 7929, 7928}, { 7936, 7944}, { 7937, 7945}, { 7938, 7946}, { 7939, 7947}, { 7940, 7948},
  26.871 { 7941, 7949}, { 7942, 7950}, { 7943, 7951}, { 7952, 7960}, { 7953, 7961}, { 7954, 7962}, { 7955, 7963},
  26.872 { 7956, 7964}, { 7957, 7965}, { 7968, 7976}, { 7969, 7977}, { 7970, 7978}, { 7971, 7979}, { 7972, 7980},
  26.873 { 7973, 7981}, { 7974, 7982}, { 7975, 7983}, { 7984, 7992}, { 7985, 7993}, { 7986, 7994}, { 7987, 7995},
  26.874 { 7988, 7996}, { 7989, 7997}, { 7990, 7998}, { 7991, 7999}, { 8000, 8008}, { 8001, 8009}, { 8002, 8010},
  26.875 { 8003, 8011}, { 8004, 8012}, { 8005, 8013}, { 8017, 8025}, { 8019, 8027}, { 8021, 8029}, { 8023, 8031},
  26.876 { 8032, 8040}, { 8033, 8041}, { 8034, 8042}, { 8035, 8043}, { 8036, 8044}, { 8037, 8045}, { 8038, 8046},
  26.877 { 8039, 8047}, { 8048, 8122}, { 8049, 8123}, { 8050, 8136}, { 8051, 8137}, { 8052, 8138}, { 8053, 8139},
  26.878 { 8054, 8154}, { 8055, 8155}, { 8056, 8184}, { 8057, 8185}, { 8058, 8170}, { 8059, 8171}, { 8060, 8186},
  26.879 { 8061, 8187}, { 8112, 8120}, { 8113, 8121}, { 8144, 8152}, { 8145, 8153}, { 8160, 8168}, { 8161, 8169},
  26.880 { 8165, 8172}, { 8560, 8544}, { 8561, 8545}, { 8562, 8546}, { 8563, 8547}, { 8564, 8548}, { 8565, 8549},
  26.881 { 8566, 8550}, { 8567, 8551}, { 8568, 8552}, { 8569, 8553}, { 8570, 8554}, { 8571, 8555}, { 8572, 8556},
  26.882 { 8573, 8557}, { 8574, 8558}, { 8575, 8559}, { 9424, 9398}, { 9425, 9399}, { 9426, 9400}, { 9427, 9401},
  26.883 { 9428, 9402}, { 9429, 9403}, { 9430, 9404}, { 9431, 9405}, { 9432, 9406}, { 9433, 9407}, { 9434, 9408},
  26.884 { 9435, 9409}, { 9436, 9410}, { 9437, 9411}, { 9438, 9412}, { 9439, 9413}, { 9440, 9414}, { 9441, 9415},
  26.885 { 9442, 9416}, { 9443, 9417}, { 9444, 9418}, { 9445, 9419}, { 9446, 9420}, { 9447, 9421}, { 9448, 9422},
  26.886 { 9449, 9423}, {65345,65313}, {65346,65314}, {65347,65315}, {65348,65316}, {65349,65317}, {65350,65318},
  26.887 {65351,65319}, {65352,65320}, {65353,65321}, {65354,65322}, {65355,65323}, {65356,65324}, {65357,65325},
  26.888 {65358,65326}, {65359,65327}, {65360,65328}, {65361,65329}, {65362,65330}, {65363,65331}, {65364,65332},
  26.889 {65365,65333}, {65366,65334}, {65367,65335}, {65368,65336}, {65369,65337}, {65370,65338}, {65535,    0}};
  26.890 
  26.891 static const GUnicodePairType UnicodeToLowerTable[] = {
  26.892 {   65,   97}, {   66,   98}, {   67,   99}, {   68,  100}, {   69,  101}, {   70,  102}, {   71,  103},
  26.893 {   72,  104}, {   73,  105}, {   74,  106}, {   75,  107}, {   76,  108}, {   77,  109}, {   78,  110},
  26.894 {   79,  111}, {   80,  112}, {   81,  113}, {   82,  114}, {   83,  115}, {   84,  116}, {   85,  117},
  26.895 {   86,  118}, {   87,  119}, {   88,  120}, {   89,  121}, {   90,  122}, {  192,  224}, {  193,  225},
  26.896 {  194,  226}, {  195,  227}, {  196,  228}, {  197,  229}, {  198,  230}, {  199,  231}, {  200,  232},
  26.897 {  201,  233}, {  202,  234}, {  203,  235}, {  204,  236}, {  205,  237}, {  206,  238}, {  207,  239},
  26.898 {  208,  240}, {  209,  241}, {  210,  242}, {  211,  243}, {  212,  244}, {  213,  245}, {  214,  246},
  26.899 {  216,  248}, {  217,  249}, {  218,  250}, {  219,  251}, {  220,  252}, {  221,  253}, {  222,  254},
  26.900 {  256,  257}, {  258,  259}, {  260,  261}, {  262,  263}, {  264,  265}, {  266,  267}, {  268,  269},
  26.901 {  270,  271}, {  272,  273}, {  274,  275}, {  276,  277}, {  278,  279}, {  280,  281}, {  282,  283},
  26.902 {  284,  285}, {  286,  287}, {  288,  289}, {  290,  291}, {  292,  293}, {  294,  295}, {  296,  297},
  26.903 {  298,  299}, {  300,  301}, {  302,  303}, {  304,  105}, {  306,  307}, {  308,  309}, {  310,  311}, {  313,  314},
  26.904 {  315,  316}, {  317,  318}, {  319,  320}, {  321,  322}, {  323,  324}, {  325,  326}, {  327,  328},
  26.905 {  330,  331}, {  332,  333}, {  334,  335}, {  336,  337}, {  338,  339}, {  340,  341}, {  342,  343},
  26.906 {  344,  345}, {  346,  347}, {  348,  349}, {  350,  351}, {  352,  353}, {  354,  355}, {  356,  357},
  26.907 {  358,  359}, {  360,  361}, {  362,  363}, {  364,  365}, {  366,  367}, {  368,  369}, {  370,  371},
  26.908 {  372,  373}, {  374,  375}, {  376,  255}, {  377,  378}, {  379,  380}, {  381,  382}, {  385,  595},
  26.909 {  386,  387}, {  388,  389}, {  390,  596}, {  391,  392}, {  393,  598}, {  394,  599}, {  395,  396},
  26.910 {  398,  477}, {  399,  601}, {  400,  603}, {  401,  402}, {  403,  608}, {  404,  611}, {  406,  617},
  26.911 {  407,  616}, {  408,  409}, {  412,  623}, {  413,  626}, {  415,  629}, {  416,  417}, {  418,  419},
  26.912 {  420,  421}, {  423,  424}, {  425,  643}, {  428,  429}, {  430,  648}, {  431,  432}, {  433,  650},
  26.913 {  434,  651}, {  435,  436}, {  437,  438}, {  439,  658}, {  440,  441}, {  444,  445}, {  452,  454},
  26.914 {  455,  457}, {  458,  460}, {  461,  462}, {  463,  464}, {  465,  466}, {  467,  468}, {  469,  470},
  26.915 {  471,  472}, {  473,  474}, {  475,  476}, {  478,  479}, {  480,  481}, {  482,  483}, {  484,  485},
  26.916 {  486,  487}, {  488,  489}, {  490,  491}, {  492,  493}, {  494,  495}, {  497,  499}, {  500,  501},
  26.917 {  506,  507}, {  508,  509}, {  510,  511}, {  512,  513}, {  514,  515}, {  516,  517}, {  518,  519},
  26.918 {  520,  521}, {  522,  523}, {  524,  525}, {  526,  527}, {  528,  529}, {  530,  531}, {  532,  533},
  26.919 {  534,  535}, {  902,  940}, {  904,  941}, {  905,  942}, {  906,  943}, {  908,  972}, {  910,  973},
  26.920 {  911,  974}, {  913,  945}, {  914,  946}, {  915,  947}, {  916,  948}, {  917,  949}, {  918,  950},
  26.921 {  919,  951}, {  920,  952}, {  921,  953}, {  922,  954}, {  923,  955}, {  924,  956}, {  925,  957},
  26.922 {  926,  958}, {  927,  959}, {  928,  960}, {  929,  961}, {  931,  963}, {  932,  964}, {  933,  965},
  26.923 {  934,  966}, {  935,  967}, {  936,  968}, {  937,  969}, {  938,  970}, {  939,  971}, {  994,  995},
  26.924 {  996,  997}, {  998,  999}, { 1000, 1001}, { 1002, 1003}, { 1004, 1005}, { 1006, 1007}, { 1024, 1104}, { 1025, 1105},
  26.925 { 1026, 1106}, { 1027, 1107}, { 1028, 1108}, { 1029, 1109}, { 1030, 1110}, { 1031, 1111}, { 1032, 1112},
  26.926 { 1033, 1113}, { 1034, 1114}, { 1035, 1115}, { 1036, 1116}, { 1037, 1117}, { 1038, 1118}, { 1039, 1119}, { 1040, 1072},
  26.927 { 1041, 1073}, { 1042, 1074}, { 1043, 1075}, { 1044, 1076}, { 1045, 1077}, { 1046, 1078}, { 1047, 1079},
  26.928 { 1048, 1080}, { 1049, 1081}, { 1050, 1082}, { 1051, 1083}, { 1052, 1084}, { 1053, 1085}, { 1054, 1086},
  26.929 { 1055, 1087}, { 1056, 1088}, { 1057, 1089}, { 1058, 1090}, { 1059, 1091}, { 1060, 1092}, { 1061, 1093},
  26.930 { 1062, 1094}, { 1063, 1095}, { 1064, 1096}, { 1065, 1097}, { 1066, 1098}, { 1067, 1099}, { 1068, 1100},
  26.931 { 1069, 1101}, { 1070, 1102}, { 1071, 1103}, { 1120, 1121}, { 1122, 1123}, { 1124, 1125}, { 1126, 1127},
  26.932 { 1128, 1129}, { 1130, 1131}, { 1132, 1133}, { 1134, 1135}, { 1136, 1137}, { 1138, 1139}, { 1140, 1141},
  26.933 { 1142, 1143}, { 1144, 1145}, { 1146, 1147}, { 1148, 1149}, { 1150, 1151}, { 1152, 1153}, { 1168, 1169},
  26.934 { 1170, 1171}, { 1172, 1173}, { 1174, 1175}, { 1176, 1177}, { 1178, 1179}, { 1180, 1181}, { 1182, 1183},
  26.935 { 1184, 1185}, { 1186, 1187}, { 1188, 1189}, { 1190, 1191}, { 1192, 1193}, { 1194, 1195}, { 1196, 1197},
  26.936 { 1198, 1199}, { 1200, 1201}, { 1202, 1203}, { 1204, 1205}, { 1206, 1207}, { 1208, 1209}, { 1210, 1211},
  26.937 { 1212, 1213}, { 1214, 1215}, { 1217, 1218}, { 1219, 1220}, { 1223, 1224}, { 1227, 1228}, { 1232, 1233},
  26.938 { 1234, 1235}, { 1236, 1237}, { 1238, 1239}, { 1240, 1241}, { 1242, 1243}, { 1244, 1245}, { 1246, 1247},
  26.939 { 1248, 1249}, { 1250, 1251}, { 1252, 1253}, { 1254, 1255}, { 1256, 1257}, { 1258, 1259}, { 1262, 1263},
  26.940 { 1264, 1265}, { 1266, 1267}, { 1268, 1269}, { 1272, 1273}, { 1329, 1377}, { 1330, 1378}, { 1331, 1379},
  26.941 { 1332, 1380}, { 1333, 1381}, { 1334, 1382}, { 1335, 1383}, { 1336, 1384}, { 1337, 1385}, { 1338, 1386},
  26.942 { 1339, 1387}, { 1340, 1388}, { 1341, 1389}, { 1342, 1390}, { 1343, 1391}, { 1344, 1392}, { 1345, 1393},
  26.943 { 1346, 1394}, { 1347, 1395}, { 1348, 1396}, { 1349, 1397}, { 1350, 1398}, { 1351, 1399}, { 1352, 1400},
  26.944 { 1353, 1401}, { 1354, 1402}, { 1355, 1403}, { 1356, 1404}, { 1357, 1405}, { 1358, 1406}, { 1359, 1407},
  26.945 { 1360, 1408}, { 1361, 1409}, { 1362, 1410}, { 1363, 1411}, { 1364, 1412}, { 1365, 1413}, { 1366, 1414},
  26.946 { 4256, 4304}, { 4257, 4305}, { 4258, 4306}, { 4259, 4307}, { 4260, 4308}, { 4261, 4309}, { 4262, 4310},
  26.947 { 4263, 4311}, { 4264, 4312}, { 4265, 4313}, { 4266, 4314}, { 4267, 4315}, { 4268, 4316}, { 4269, 4317},
  26.948 { 4270, 4318}, { 4271, 4319}, { 4272, 4320}, { 4273, 4321}, { 4274, 4322}, { 4275, 4323}, { 4276, 4324},
  26.949 { 4277, 4325}, { 4278, 4326}, { 4279, 4327}, { 4280, 4328}, { 4281, 4329}, { 4282, 4330}, { 4283, 4331},
  26.950 { 4284, 4332}, { 4285, 4333}, { 4286, 4334}, { 4287, 4335}, { 4288, 4336}, { 4289, 4337}, { 4290, 4338},
  26.951 { 4291, 4339}, { 4292, 4340}, { 4293, 4341}, { 7680, 7681}, { 7682, 7683}, { 7684, 7685}, { 7686, 7687},
  26.952 { 7688, 7689}, { 7690, 7691}, { 7692, 7693}, { 7694, 7695}, { 7696, 7697}, { 7698, 7699}, { 7700, 7701},
  26.953 { 7702, 7703}, { 7704, 7705}, { 7706, 7707}, { 7708, 7709}, { 7710, 7711}, { 7712, 7713}, { 7714, 7715},
  26.954 { 7716, 7717}, { 7718, 7719}, { 7720, 7721}, { 7722, 7723}, { 7724, 7725}, { 7726, 7727}, { 7728, 7729},
  26.955 { 7730, 7731}, { 7732, 7733}, { 7734, 7735}, { 7736, 7737}, { 7738, 7739}, { 7740, 7741}, { 7742, 7743},
  26.956 { 7744, 7745}, { 7746, 7747}, { 7748, 7749}, { 7750, 7751}, { 7752, 7753}, { 7754, 7755}, { 7756, 7757},
  26.957 { 7758, 7759}, { 7760, 7761}, { 7762, 7763}, { 7764, 7765}, { 7766, 7767}, { 7768, 7769}, { 7770, 7771},
  26.958 { 7772, 7773}, { 7774, 7775}, { 7776, 7777}, { 7778, 7779}, { 7780, 7781}, { 7782, 7783}, { 7784, 7785},
  26.959 { 7786, 7787}, { 7788, 7789}, { 7790, 7791}, { 7792, 7793}, { 7794, 7795}, { 7796, 7797}, { 7798, 7799},
  26.960 { 7800, 7801}, { 7802, 7803}, { 7804, 7805}, { 7806, 7807}, { 7808, 7809}, { 7810, 7811}, { 7812, 7813},
  26.961 { 7814, 7815}, { 7816, 7817}, { 7818, 7819}, { 7820, 7821}, { 7822, 7823}, { 7824, 7825}, { 7826, 7827},
  26.962 { 7828, 7829}, { 7840, 7841}, { 7842, 7843}, { 7844, 7845}, { 7846, 7847}, { 7848, 7849}, { 7850, 7851},
  26.963 { 7852, 7853}, { 7854, 7855}, { 7856, 7857}, { 7858, 7859}, { 7860, 7861}, { 7862, 7863}, { 7864, 7865},
  26.964 { 7866, 7867}, { 7868, 7869}, { 7870, 7871}, { 7872, 7873}, { 7874, 7875}, { 7876, 7877}, { 7878, 7879},
  26.965 { 7880, 7881}, { 7882, 7883}, { 7884, 7885}, { 7886, 7887}, { 7888, 7889}, { 7890, 7891}, { 7892, 7893},
  26.966 { 7894, 7895}, { 7896, 7897}, { 7898, 7899}, { 7900, 7901}, { 7902, 7903}, { 7904, 7905}, { 7906, 7907},
  26.967 { 7908, 7909}, { 7910, 7911}, { 7912, 7913}, { 7914, 7915}, { 7916, 7917}, { 7918, 7919}, { 7920, 7921},
  26.968 { 7922, 7923}, { 7924, 7925}, { 7926, 7927}, { 7928, 7929}, { 7944, 7936}, { 7945, 7937}, { 7946, 7938},
  26.969 { 7947, 7939}, { 7948, 7940}, { 7949, 7941}, { 7950, 7942}, { 7951, 7943}, { 7960, 7952}, { 7961, 7953},
  26.970 { 7962, 7954}, { 7963, 7955}, { 7964, 7956}, { 7965, 7957}, { 7976, 7968}, { 7977, 7969}, { 7978, 7970},
  26.971 { 7979, 7971}, { 7980, 7972}, { 7981, 7973}, { 7982, 7974}, { 7983, 7975}, { 7992, 7984}, { 7993, 7985},
  26.972 { 7994, 7986}, { 7995, 7987}, { 7996, 7988}, { 7997, 7989}, { 7998, 7990}, { 7999, 7991}, { 8008, 8000},
  26.973 { 8009, 8001}, { 8010, 8002}, { 8011, 8003}, { 8012, 8004}, { 8013, 8005}, { 8025, 8017}, { 8027, 8019},
  26.974 { 8029, 8021}, { 8031, 8023}, { 8040, 8032}, { 8041, 8033}, { 8042, 8034}, { 8043, 8035}, { 8044, 8036},
  26.975 { 8045, 8037}, { 8046, 8038}, { 8047, 8039}, { 8120, 8112}, { 8121, 8113}, { 8122, 8048}, { 8123, 8049},
  26.976 { 8136, 8050}, { 8137, 8051}, { 8138, 8052}, { 8139, 8053}, { 8152, 8144}, { 8153, 8145}, { 8154, 8054},
  26.977 { 8155, 8055}, { 8168, 8160}, { 8169, 8161}, { 8170, 8058}, { 8171, 8059}, { 8172, 8165}, { 8184, 8056},
  26.978 { 8185, 8057}, { 8186, 8060}, { 8187, 8061}, { 8544, 8560}, { 8545, 8561}, { 8546, 8562}, { 8547, 8563},
  26.979 { 8548, 8564}, { 8549, 8565}, { 8550, 8566}, { 8551, 8567}, { 8552, 8568}, { 8553, 8569}, { 8554, 8570},
  26.980 { 8555, 8571}, { 8556, 8572}, { 8557, 8573}, { 8558, 8574}, { 8559, 8575}, { 9398, 9424}, { 9399, 9425},
  26.981 { 9400, 9426}, { 9401, 9427}, { 9402, 9428}, { 9403, 9429}, { 9404, 9430}, { 9405, 9431}, { 9406, 9432},
  26.982 { 9407, 9433}, { 9408, 9434}, { 9409, 9435}, { 9410, 9436}, { 9411, 9437}, { 9412, 9438}, { 9413, 9439},
  26.983 { 9414, 9440}, { 9415, 9441}, { 9416, 9442}, { 9417, 9443}, { 9418, 9444}, { 9419, 9445}, { 9420, 9446},
  26.984 { 9421, 9447}, { 9422, 9448}, { 9423, 9449}, {65313,65345}, {65314,65346}, {65315,65347}, {65316,65348},
  26.985 {65317,65349}, {65318,65350}, {65319,65351}, {65320,65352}, {65321,65353}, {65322,65354}, {65323,65355},
  26.986 {65324,65356}, {65325,65357}, {65326,65358}, {65327,65359}, {65328,65360}, {65329,65361}, {65330,65362},
  26.987 {65331,65363}, {65332,65364}, {65333,65365}, {65334,65366}, {65335,65367}, {65336,65368}, {65337,65369},
  26.988 {65338,65370}, {65535,    0}};
  26.989 
  26.990 int OVR_CDECL OVR_towupper(wchar_t charCode)
  26.991 {
  26.992     // Don't use UnicodeUpperBits! It differs from UnicodeToUpperBits.
  26.993     if (UnicodeCharIs(UnicodeToUpperBits, charCode))
  26.994     {
  26.995         // To protect from memory overrun in case the character is not found
  26.996         // we use one extra fake element in the table {65536, 0}.
  26.997         UPInt idx = Alg::LowerBoundSliced(
  26.998             UnicodeToUpperTable,
  26.999             0,
 26.1000             sizeof(UnicodeToUpperTable) / sizeof(UnicodeToUpperTable[0]) - 1,
 26.1001             (UInt16)charCode,
 26.1002             CmpUnicodeKey);
 26.1003         return UnicodeToUpperTable[idx].Value;
 26.1004     }
 26.1005     return charCode;
 26.1006 }
 26.1007 
 26.1008 int OVR_CDECL OVR_towlower(wchar_t charCode)
 26.1009 {
 26.1010     // Don't use UnicodeLowerBits! It differs from UnicodeToLowerBits.
 26.1011     if (UnicodeCharIs(UnicodeToLowerBits, charCode))
 26.1012     {
 26.1013         // To protect from memory overrun in case the character is not found
 26.1014         // we use one extra fake element in the table {65536, 0}.
 26.1015         UPInt idx = Alg::LowerBoundSliced(
 26.1016             UnicodeToLowerTable,
 26.1017             0,
 26.1018             sizeof(UnicodeToLowerTable) / sizeof(UnicodeToLowerTable[0]) - 1,
 26.1019             (UInt16)charCode,
 26.1020             CmpUnicodeKey);
 26.1021         return UnicodeToLowerTable[idx].Value;
 26.1022     }
 26.1023     return charCode;
 26.1024 }
 26.1025 
 26.1026 #endif //OVR_NO_WCTYPE
 26.1027 
 26.1028 } // OVR
 26.1029 \ No newline at end of file
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/libovr/Src/Kernel/OVR_Std.h	Sat Sep 14 16:14:59 2013 +0300
    27.3 @@ -0,0 +1,1 @@
    27.4 +/************************************************************************************
    27.5 
    27.6 PublicHeader:   OVR.h
    27.7 Filename    :   OVR_Std.h
    27.8 Content     :   Standard C function interface
    27.9 Created     :   September 19, 2012
   27.10 Notes       : 
   27.11 
   27.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   27.13 
   27.14 Use of this software is subject to the terms of the Oculus license
   27.15 agreement provided at the time of installation or download, or which
   27.16 otherwise accompanies this software in either electronic or hard copy form.
   27.17 
   27.18 ************************************************************************************/
   27.19 
   27.20 #ifndef OVR_Std_h
   27.21 #define OVR_Std_h
   27.22 
   27.23 #include "OVR_Types.h"
   27.24 #include <stdarg.h> // for va_list args
   27.25 #include <string.h>
   27.26 #include <stdio.h>
   27.27 #include <stdlib.h>
   27.28 #include <ctype.h>
   27.29 
   27.30 #if !defined(OVR_OS_WINCE) && defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
   27.31 #define OVR_MSVC_SAFESTRING
   27.32 #include <errno.h>
   27.33 #endif
   27.34 
   27.35 // Wide-char funcs
   27.36 #include <wchar.h>
   27.37 #include <wctype.h>
   27.38 
   27.39 namespace OVR {
   27.40 
   27.41 #if defined(OVR_OS_WIN32)
   27.42 inline char* OVR_CDECL OVR_itoa(int val, char *dest, UPInt destsize, int radix)
   27.43 {
   27.44 #if defined(OVR_MSVC_SAFESTRING)
   27.45     _itoa_s(val, dest, destsize, radix);
   27.46     return dest;
   27.47 #else
   27.48     OVR_UNUSED(destsize);
   27.49     return itoa(val, dest, radix);
   27.50 #endif
   27.51 }
   27.52 #else // OVR_OS_WIN32
   27.53 inline char* OVR_itoa(int val, char* dest, unsigned int len, int radix)
   27.54 {
   27.55     if (val == 0)
   27.56     {
   27.57         if (len > 1)
   27.58         {
   27.59             dest[0] = '0';
   27.60             dest[1] = '\0';  
   27.61         }
   27.62         return dest;
   27.63     }
   27.64 
   27.65     int cur = val;
   27.66     unsigned int i    = 0; 
   27.67     unsigned int sign = 0;
   27.68 
   27.69     if (val < 0)
   27.70     {
   27.71         val = -val;
   27.72         sign = 1;
   27.73     }
   27.74 
   27.75     while ((val != 0) && (i < (len - 1 - sign)))        
   27.76     {
   27.77         cur    = val % radix;
   27.78         val   /= radix;
   27.79 
   27.80         if (radix == 16)
   27.81         {
   27.82             switch(cur)
   27.83             {
   27.84             case 10:
   27.85                 dest[i] = 'a';
   27.86                 break;
   27.87             case 11:
   27.88                 dest[i] = 'b';
   27.89                 break;
   27.90             case 12:
   27.91                 dest[i] = 'c';
   27.92                 break;
   27.93             case 13:
   27.94                 dest[i] = 'd';
   27.95                 break;
   27.96             case 14:
   27.97                 dest[i] = 'e';
   27.98                 break;
   27.99             case 15:
  27.100                 dest[i] = 'f';
  27.101                 break;
  27.102             default:
  27.103                 dest[i] = (char)('0' + cur);
  27.104                 break;
  27.105             }
  27.106         } 
  27.107         else
  27.108         {
  27.109             dest[i] = (char)('0' + cur);
  27.110         }
  27.111         ++i;
  27.112     }
  27.113 
  27.114     if (sign)
  27.115     {
  27.116         dest[i++] = '-';
  27.117     }
  27.118 
  27.119     for (unsigned int j = 0; j < i / 2; ++j)
  27.120     {
  27.121         char tmp        = dest[j];
  27.122         dest[j]         = dest[i - 1 - j];
  27.123         dest[i - 1 - j] = tmp;
  27.124     }
  27.125     dest[i] = '\0';
  27.126 
  27.127     return dest;
  27.128 }
  27.129 
  27.130 #endif
  27.131 
  27.132 
  27.133 // String functions
  27.134 
  27.135 inline UPInt OVR_CDECL OVR_strlen(const char* str)
  27.136 {
  27.137     return strlen(str);
  27.138 }
  27.139 
  27.140 inline char* OVR_CDECL OVR_strcpy(char* dest, UPInt destsize, const char* src)
  27.141 {
  27.142 #if defined(OVR_MSVC_SAFESTRING)
  27.143     strcpy_s(dest, destsize, src);
  27.144     return dest;
  27.145 #else
  27.146     OVR_UNUSED(destsize);
  27.147     return strcpy(dest, src);
  27.148 #endif
  27.149 }
  27.150 
  27.151 inline char* OVR_CDECL OVR_strncpy(char* dest, UPInt destsize, const char* src, UPInt count)
  27.152 {
  27.153 #if defined(OVR_MSVC_SAFESTRING)
  27.154     strncpy_s(dest, destsize, src, count);
  27.155     return dest;
  27.156 #else
  27.157     OVR_UNUSED(destsize);
  27.158     return strncpy(dest, src, count);
  27.159 #endif
  27.160 }
  27.161 
  27.162 inline char * OVR_CDECL OVR_strcat(char* dest, UPInt destsize, const char* src)
  27.163 {
  27.164 #if defined(OVR_MSVC_SAFESTRING)
  27.165     strcat_s(dest, destsize, src);
  27.166     return dest;
  27.167 #else
  27.168     OVR_UNUSED(destsize);
  27.169     return strcat(dest, src);
  27.170 #endif
  27.171 }
  27.172 
  27.173 inline int OVR_CDECL OVR_strcmp(const char* dest, const char* src)
  27.174 {
  27.175     return strcmp(dest, src);
  27.176 }
  27.177 
  27.178 inline const char* OVR_CDECL OVR_strchr(const char* str, char c)
  27.179 {
  27.180     return strchr(str, c);
  27.181 }
  27.182 
  27.183 inline char* OVR_CDECL OVR_strchr(char* str, char c)
  27.184 {
  27.185     return strchr(str, c);
  27.186 }
  27.187 
  27.188 inline const char* OVR_strrchr(const char* str, char c)
  27.189 {
  27.190     UPInt len = OVR_strlen(str);
  27.191     for (UPInt i=len; i>0; i--)     
  27.192         if (str[i]==c) 
  27.193             return str+i;
  27.194     return 0;
  27.195 }
  27.196 
  27.197 inline const UByte* OVR_CDECL OVR_memrchr(const UByte* str, UPInt size, UByte c)
  27.198 {
  27.199     for (SPInt i = (SPInt)size - 1; i >= 0; i--)     
  27.200     {
  27.201         if (str[i] == c) 
  27.202             return str + i;
  27.203     }
  27.204     return 0;
  27.205 }
  27.206 
  27.207 inline char* OVR_CDECL OVR_strrchr(char* str, char c)
  27.208 {
  27.209     UPInt len = OVR_strlen(str);
  27.210     for (UPInt i=len; i>0; i--)     
  27.211         if (str[i]==c) 
  27.212             return str+i;
  27.213     return 0;
  27.214 }
  27.215 
  27.216 
  27.217 double OVR_CDECL OVR_strtod(const char* string, char** tailptr);
  27.218 
  27.219 inline long OVR_CDECL OVR_strtol(const char* string, char** tailptr, int radix)
  27.220 {
  27.221     return strtol(string, tailptr, radix);
  27.222 }
  27.223 
  27.224 inline long OVR_CDECL OVR_strtoul(const char* string, char** tailptr, int radix)
  27.225 {
  27.226     return strtoul(string, tailptr, radix);
  27.227 }
  27.228 
  27.229 inline int OVR_CDECL OVR_strncmp(const char* ws1, const char* ws2, UPInt size)
  27.230 {
  27.231     return strncmp(ws1, ws2, size);
  27.232 }
  27.233 
  27.234 inline UInt64 OVR_CDECL OVR_strtouq(const char *nptr, char **endptr, int base)
  27.235 {
  27.236 #if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE)
  27.237     return _strtoui64(nptr, endptr, base);
  27.238 #else
  27.239     return strtoull(nptr, endptr, base);
  27.240 #endif
  27.241 }
  27.242 
  27.243 inline SInt64 OVR_CDECL OVR_strtoq(const char *nptr, char **endptr, int base)
  27.244 {
  27.245 #if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE)
  27.246     return _strtoi64(nptr, endptr, base);
  27.247 #else
  27.248     return strtoll(nptr, endptr, base);
  27.249 #endif
  27.250 }
  27.251 
  27.252 
  27.253 inline SInt64 OVR_CDECL OVR_atoq(const char* string)
  27.254 {
  27.255 #if defined(OVR_CC_MSVC) && !defined(OVR_OS_WINCE)
  27.256     return _atoi64(string);
  27.257 #else
  27.258     return atoll(string);
  27.259 #endif
  27.260 }
  27.261 
  27.262 inline UInt64 OVR_CDECL OVR_atouq(const char* string)
  27.263 {
  27.264   return OVR_strtouq(string, NULL, 10);
  27.265 }
  27.266 
  27.267 
  27.268 // Implemented in GStd.cpp in platform-specific manner.
  27.269 int OVR_CDECL OVR_stricmp(const char* dest, const char* src);
  27.270 int OVR_CDECL OVR_strnicmp(const char* dest, const char* src, UPInt count);
  27.271 
  27.272 inline UPInt OVR_CDECL OVR_sprintf(char *dest, UPInt destsize, const char* format, ...)
  27.273 {
  27.274     va_list argList;
  27.275     va_start(argList,format);
  27.276     UPInt ret;
  27.277 #if defined(OVR_CC_MSVC)
  27.278     #if defined(OVR_MSVC_SAFESTRING)
  27.279         ret = _vsnprintf_s(dest, destsize, _TRUNCATE, format, argList);
  27.280         OVR_ASSERT(ret != -1);
  27.281     #else
  27.282         OVR_UNUSED(destsize);
  27.283         ret = _vsnprintf(dest, destsize - 1, format, argList); // -1 for space for the null character
  27.284         OVR_ASSERT(ret != -1);
  27.285         dest[destsize-1] = 0;
  27.286     #endif
  27.287 #else
  27.288     OVR_UNUSED(destsize);
  27.289     ret = vsprintf(dest, format, argList);
  27.290     OVR_ASSERT(ret < destsize);
  27.291 #endif
  27.292     va_end(argList);
  27.293     return ret;
  27.294 }
  27.295 
  27.296 inline UPInt OVR_CDECL OVR_vsprintf(char *dest, UPInt destsize, const char * format, va_list argList)
  27.297 {
  27.298     UPInt ret;
  27.299 #if defined(OVR_CC_MSVC)
  27.300     #if defined(OVR_MSVC_SAFESTRING)
  27.301         dest[0] = '\0';
  27.302         int rv = vsnprintf_s(dest, destsize, _TRUNCATE, format, argList);
  27.303         if (rv == -1)
  27.304         {
  27.305             dest[destsize - 1] = '\0';
  27.306             ret = destsize - 1;
  27.307         }
  27.308         else
  27.309             ret = (UPInt)rv;
  27.310     #else
  27.311         OVR_UNUSED(destsize);
  27.312         int rv = _vsnprintf(dest, destsize - 1, format, argList);
  27.313         OVR_ASSERT(rv != -1);
  27.314         ret = (UPInt)rv;
  27.315         dest[destsize-1] = 0;
  27.316     #endif
  27.317 #else
  27.318     OVR_UNUSED(destsize);
  27.319     ret = (UPInt)vsprintf(dest, format, argList);
  27.320     OVR_ASSERT(ret < destsize);
  27.321 #endif
  27.322     return ret;
  27.323 }
  27.324 
  27.325 // Returns the number of characters in the formatted string.
  27.326 inline UPInt OVR_CDECL OVR_vscprintf(const char * format, va_list argList)
  27.327 {
  27.328     UPInt ret;
  27.329 #if defined(OVR_CC_MSVC)
  27.330     ret = (UPInt) _vscprintf(format, argList);
  27.331 #else    
  27.332     ret = (UPInt) vsnprintf(NULL, 0, format, argList);
  27.333 #endif
  27.334     return ret;       
  27.335 }
  27.336 
  27.337 
  27.338 wchar_t* OVR_CDECL OVR_wcscpy(wchar_t* dest, UPInt destsize, const wchar_t* src);
  27.339 wchar_t* OVR_CDECL OVR_wcsncpy(wchar_t* dest, UPInt destsize, const wchar_t* src, UPInt count);
  27.340 wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, UPInt destsize, const wchar_t* src);
  27.341 UPInt    OVR_CDECL OVR_wcslen(const wchar_t* str);
  27.342 int      OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b);
  27.343 int      OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b);
  27.344 
  27.345 inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b)
  27.346 {
  27.347 #if defined(OVR_OS_WIN32)
  27.348 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
  27.349     return ::_wcsicoll(a, b);
  27.350 #else
  27.351     return ::wcsicoll(a, b);
  27.352 #endif
  27.353 #else
  27.354     // not supported, use regular wcsicmp
  27.355     return OVR_wcsicmp(a, b);
  27.356 #endif
  27.357 }
  27.358 
  27.359 inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b)
  27.360 {
  27.361 #if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX)
  27.362     return wcscoll(a, b);
  27.363 #else
  27.364     // not supported, use regular wcscmp
  27.365     return OVR_wcscmp(a, b);
  27.366 #endif
  27.367 }
  27.368 
  27.369 #ifndef OVR_NO_WCTYPE
  27.370 
  27.371 inline int OVR_CDECL UnicodeCharIs(const UInt16* table, wchar_t charCode)
  27.372 {
  27.373     unsigned offset = table[charCode >> 8];
  27.374     if (offset == 0) return 0;
  27.375     if (offset == 1) return 1;
  27.376     return (table[offset + ((charCode >> 4) & 15)] & (1 << (charCode & 15))) != 0;
  27.377 }
  27.378 
  27.379 extern const UInt16 UnicodeAlnumBits[];
  27.380 extern const UInt16 UnicodeAlphaBits[];
  27.381 extern const UInt16 UnicodeDigitBits[];
  27.382 extern const UInt16 UnicodeSpaceBits[];
  27.383 extern const UInt16 UnicodeXDigitBits[];
  27.384 
  27.385 // Uncomment if necessary
  27.386 //extern const UInt16 UnicodeCntrlBits[];
  27.387 //extern const UInt16 UnicodeGraphBits[];
  27.388 //extern const UInt16 UnicodeLowerBits[];
  27.389 //extern const UInt16 UnicodePrintBits[];
  27.390 //extern const UInt16 UnicodePunctBits[];
  27.391 //extern const UInt16 UnicodeUpperBits[];
  27.392 
  27.393 inline int OVR_CDECL OVR_iswalnum (wchar_t charCode) { return UnicodeCharIs(UnicodeAlnumBits,  charCode); }
  27.394 inline int OVR_CDECL OVR_iswalpha (wchar_t charCode) { return UnicodeCharIs(UnicodeAlphaBits,  charCode); }
  27.395 inline int OVR_CDECL OVR_iswdigit (wchar_t charCode) { return UnicodeCharIs(UnicodeDigitBits,  charCode); }
  27.396 inline int OVR_CDECL OVR_iswspace (wchar_t charCode) { return UnicodeCharIs(UnicodeSpaceBits,  charCode); }
  27.397 inline int OVR_CDECL OVR_iswxdigit(wchar_t charCode) { return UnicodeCharIs(UnicodeXDigitBits, charCode); }
  27.398 
  27.399 // Uncomment if necessary
  27.400 //inline int OVR_CDECL OVR_iswcntrl (wchar_t charCode) { return UnicodeCharIs(UnicodeCntrlBits,  charCode); }
  27.401 //inline int OVR_CDECL OVR_iswgraph (wchar_t charCode) { return UnicodeCharIs(UnicodeGraphBits,  charCode); }
  27.402 //inline int OVR_CDECL OVR_iswlower (wchar_t charCode) { return UnicodeCharIs(UnicodeLowerBits,  charCode); }
  27.403 //inline int OVR_CDECL OVR_iswprint (wchar_t charCode) { return UnicodeCharIs(UnicodePrintBits,  charCode); }
  27.404 //inline int OVR_CDECL OVR_iswpunct (wchar_t charCode) { return UnicodeCharIs(UnicodePunctBits,  charCode); }
  27.405 //inline int OVR_CDECL OVR_iswupper (wchar_t charCode) { return UnicodeCharIs(UnicodeUpperBits,  charCode); }
  27.406 
  27.407 int OVR_CDECL OVR_towupper(wchar_t charCode);
  27.408 int OVR_CDECL OVR_towlower(wchar_t charCode);
  27.409 
  27.410 #else // OVR_NO_WCTYPE
  27.411 
  27.412 inline int OVR_CDECL OVR_iswspace(wchar_t c)
  27.413 {
  27.414     return iswspace(c);
  27.415 }
  27.416 
  27.417 inline int OVR_CDECL OVR_iswdigit(wchar_t c)
  27.418 {
  27.419     return iswdigit(c);
  27.420 }
  27.421 
  27.422 inline int OVR_CDECL OVR_iswxdigit(wchar_t c)
  27.423 {
  27.424     return iswxdigit(c);
  27.425 }
  27.426 
  27.427 inline int OVR_CDECL OVR_iswalpha(wchar_t c)
  27.428 {
  27.429     return iswalpha(c);
  27.430 }
  27.431 
  27.432 inline int OVR_CDECL OVR_iswalnum(wchar_t c)
  27.433 {
  27.434     return iswalnum(c);
  27.435 }
  27.436 
  27.437 inline wchar_t OVR_CDECL OVR_towlower(wchar_t c)
  27.438 {
  27.439     return (wchar_t)towlower(c);
  27.440 }
  27.441 
  27.442 inline wchar_t OVR_towupper(wchar_t c)
  27.443 {
  27.444     return (wchar_t)towupper(c);
  27.445 }
  27.446 
  27.447 #endif // OVR_NO_WCTYPE
  27.448 
  27.449 // ASCII versions of tolower and toupper. Don't use "char"
  27.450 inline int OVR_CDECL OVR_tolower(int c)
  27.451 {
  27.452     return (c >= 'A' && c <= 'Z') ? c - 'A' + 'a' : c;
  27.453 }
  27.454 
  27.455 inline int OVR_CDECL OVR_toupper(int c)
  27.456 {
  27.457     return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
  27.458 }
  27.459 
  27.460 
  27.461 
  27.462 inline double OVR_CDECL OVR_wcstod(const wchar_t* string, wchar_t** tailptr)
  27.463 {
  27.464 #if defined(OVR_OS_OTHER)
  27.465     OVR_UNUSED(tailptr);
  27.466     char buffer[64];
  27.467     char* tp = NULL;
  27.468     UPInt max = OVR_wcslen(string);
  27.469     if (max > 63) max = 63;
  27.470     unsigned char c = 0;
  27.471     for (UPInt i=0; i < max; i++)
  27.472     {
  27.473         c = (unsigned char)string[i];
  27.474         buffer[i] = ((c) < 128 ? (char)c : '!');
  27.475     }
  27.476     buffer[max] = 0;
  27.477     return OVR_strtod(buffer, &tp);
  27.478 #else
  27.479     return wcstod(string, tailptr);
  27.480 #endif
  27.481 }
  27.482 
  27.483 inline long OVR_CDECL OVR_wcstol(const wchar_t* string, wchar_t** tailptr, int radix)
  27.484 {
  27.485 #if defined(OVR_OS_OTHER)
  27.486     OVR_UNUSED(tailptr);
  27.487     char buffer[64];
  27.488     char* tp = NULL;
  27.489     UPInt max = OVR_wcslen(string);
  27.490     if (max > 63) max = 63;
  27.491     unsigned char c = 0;
  27.492     for (UPInt i=0; i < max; i++)
  27.493     {
  27.494         c = (unsigned char)string[i];
  27.495         buffer[i] = ((c) < 128 ? (char)c : '!');
  27.496     }
  27.497     buffer[max] = 0;
  27.498     return strtol(buffer, &tp, radix);
  27.499 #else
  27.500     return wcstol(string, tailptr, radix);
  27.501 #endif
  27.502 }
  27.503 
  27.504 } // OVR
  27.505 
  27.506 #endif // OVR_Std_h
  27.507 \ No newline at end of file
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/libovr/Src/Kernel/OVR_String.cpp	Sat Sep 14 16:14:59 2013 +0300
    28.3 @@ -0,0 +1,1 @@
    28.4 +/************************************************************************************
    28.5 
    28.6 Filename    :   OVR_String.cpp
    28.7 Content     :   String UTF8 string implementation with copy-on-write semantics
    28.8                 (thread-safe for assignment but not modification).
    28.9 Created     :   September 19, 2012
   28.10 Notes       : 
   28.11 
   28.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   28.13 
   28.14 Use of this software is subject to the terms of the Oculus license
   28.15 agreement provided at the time of installation or download, or which
   28.16 otherwise accompanies this software in either electronic or hard copy form.
   28.17 
   28.18 ************************************************************************************/
   28.19 
   28.20 #include "OVR_String.h"
   28.21 
   28.22 #include <stdlib.h>
   28.23 #include <ctype.h>
   28.24 
   28.25 #ifdef OVR_OS_QNX
   28.26 # include <strings.h>
   28.27 #endif
   28.28 
   28.29 namespace OVR {
   28.30 
   28.31 #define String_LengthIsSize (UPInt(1) << String::Flag_LengthIsSizeShift)
   28.32 
   28.33 String::DataDesc String::NullData = {String_LengthIsSize, 1, {0} };
   28.34 
   28.35 
   28.36 String::String()
   28.37 {
   28.38     pData = &NullData;
   28.39     pData->AddRef();
   28.40 };
   28.41 
   28.42 String::String(const char* pdata)
   28.43 {
   28.44     // Obtain length in bytes; it doesn't matter if _data is UTF8.
   28.45     UPInt size = pdata ? OVR_strlen(pdata) : 0; 
   28.46     pData = AllocDataCopy1(size, 0, pdata, size);
   28.47 };
   28.48 
   28.49 String::String(const char* pdata1, const char* pdata2, const char* pdata3)
   28.50 {
   28.51     // Obtain length in bytes; it doesn't matter if _data is UTF8.
   28.52     UPInt size1 = pdata1 ? OVR_strlen(pdata1) : 0; 
   28.53     UPInt size2 = pdata2 ? OVR_strlen(pdata2) : 0; 
   28.54     UPInt size3 = pdata3 ? OVR_strlen(pdata3) : 0; 
   28.55 
   28.56     DataDesc *pdataDesc = AllocDataCopy2(size1 + size2 + size3, 0,
   28.57                                          pdata1, size1, pdata2, size2);
   28.58     memcpy(pdataDesc->Data + size1 + size2, pdata3, size3);   
   28.59     pData = pdataDesc;    
   28.60 }
   28.61 
   28.62 String::String(const char* pdata, UPInt size)
   28.63 {
   28.64     OVR_ASSERT((size == 0) || (pdata != 0));
   28.65     pData = AllocDataCopy1(size, 0, pdata, size);
   28.66 };
   28.67 
   28.68 
   28.69 String::String(const InitStruct& src, UPInt size)
   28.70 {
   28.71     pData = AllocData(size, 0);
   28.72     src.InitString(GetData()->Data, size);
   28.73 }
   28.74 
   28.75 String::String(const String& src)
   28.76 {    
   28.77     pData = src.GetData();
   28.78     pData->AddRef();
   28.79 }
   28.80 
   28.81 String::String(const StringBuffer& src)
   28.82 {
   28.83     pData = AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize());
   28.84 }
   28.85 
   28.86 String::String(const wchar_t* data)
   28.87 {
   28.88     pData = &NullData;
   28.89     pData->AddRef();
   28.90     // Simplified logic for wchar_t constructor.
   28.91     if (data)    
   28.92         *this = data;    
   28.93 }
   28.94 
   28.95 
   28.96 String::DataDesc* String::AllocData(UPInt size, UPInt lengthIsSize)
   28.97 {
   28.98     String::DataDesc* pdesc;
   28.99 
  28.100     if (size == 0)
  28.101     {
  28.102         pdesc = &NullData;
  28.103         pdesc->AddRef();
  28.104         return pdesc;
  28.105     }
  28.106 
  28.107     pdesc = (DataDesc*)OVR_ALLOC(sizeof(DataDesc)+ size);
  28.108     pdesc->Data[size] = 0;
  28.109     pdesc->RefCount = 1;
  28.110     pdesc->Size     = size | lengthIsSize;  
  28.111     return pdesc;
  28.112 }
  28.113 
  28.114 
  28.115 String::DataDesc* String::AllocDataCopy1(UPInt size, UPInt lengthIsSize,
  28.116                                          const char* pdata, UPInt copySize)
  28.117 {
  28.118     String::DataDesc* pdesc = AllocData(size, lengthIsSize);
  28.119     memcpy(pdesc->Data, pdata, copySize);
  28.120     return pdesc;
  28.121 }
  28.122 
  28.123 String::DataDesc* String::AllocDataCopy2(UPInt size, UPInt lengthIsSize,
  28.124                                          const char* pdata1, UPInt copySize1,
  28.125                                          const char* pdata2, UPInt copySize2)
  28.126 {
  28.127     String::DataDesc* pdesc = AllocData(size, lengthIsSize);
  28.128     memcpy(pdesc->Data, pdata1, copySize1);
  28.129     memcpy(pdesc->Data + copySize1, pdata2, copySize2);
  28.130     return pdesc;
  28.131 }
  28.132 
  28.133 
  28.134 UPInt String::GetLength() const 
  28.135 {
  28.136     // Optimize length accesses for non-UTF8 character strings. 
  28.137     DataDesc* pdata = GetData();
  28.138     UPInt     length, size = pdata->GetSize();
  28.139     
  28.140     if (pdata->LengthIsSize())
  28.141         return size;    
  28.142     
  28.143     length = (UPInt)UTF8Util::GetLength(pdata->Data, (UPInt)size);
  28.144     
  28.145     if (length == size)
  28.146         pdata->Size |= String_LengthIsSize;
  28.147     
  28.148     return length;
  28.149 }
  28.150 
  28.151 
  28.152 //static UInt32 String_CharSearch(const char* buf, )
  28.153 
  28.154 
  28.155 UInt32 String::GetCharAt(UPInt index) const 
  28.156 {  
  28.157     SPInt       i = (SPInt) index;
  28.158     DataDesc*   pdata = GetData();
  28.159     const char* buf = pdata->Data;
  28.160     UInt32      c;
  28.161     
  28.162     if (pdata->LengthIsSize())
  28.163     {
  28.164         OVR_ASSERT(index < pdata->GetSize());
  28.165         buf += i;
  28.166         return UTF8Util::DecodeNextChar_Advance0(&buf);
  28.167     }
  28.168 
  28.169     c = UTF8Util::GetCharAt(index, buf, pdata->GetSize());
  28.170     return c;
  28.171 }
  28.172 
  28.173 UInt32 String::GetFirstCharAt(UPInt index, const char** offset) const
  28.174 {
  28.175     DataDesc*   pdata = GetData();
  28.176     SPInt       i = (SPInt) index;
  28.177     const char* buf = pdata->Data;
  28.178     const char* end = buf + pdata->GetSize();
  28.179     UInt32      c;
  28.180 
  28.181     do 
  28.182     {
  28.183         c = UTF8Util::DecodeNextChar_Advance0(&buf);
  28.184         i--;
  28.185 
  28.186         if (buf >= end)
  28.187         {
  28.188             // We've hit the end of the string; don't go further.
  28.189             OVR_ASSERT(i == 0);
  28.190             return c;
  28.191         }
  28.192     } while (i >= 0);
  28.193 
  28.194     *offset = buf;
  28.195 
  28.196     return c;
  28.197 }
  28.198 
  28.199 UInt32 String::GetNextChar(const char** offset) const
  28.200 {
  28.201     return UTF8Util::DecodeNextChar(offset);
  28.202 }
  28.203 
  28.204 
  28.205 
  28.206 void String::AppendChar(UInt32 ch)
  28.207 {
  28.208     DataDesc*   pdata = GetData();
  28.209     UPInt       size = pdata->GetSize();
  28.210     char        buff[8];
  28.211     SPInt       encodeSize = 0;
  28.212 
  28.213     // Converts ch into UTF8 string and fills it into buff.   
  28.214     UTF8Util::EncodeChar(buff, &encodeSize, ch);
  28.215     OVR_ASSERT(encodeSize >= 0);
  28.216 
  28.217     SetData(AllocDataCopy2(size + (UPInt)encodeSize, 0,
  28.218                            pdata->Data, size, buff, (UPInt)encodeSize));
  28.219     pdata->Release();
  28.220 }
  28.221 
  28.222 
  28.223 void String::AppendString(const wchar_t* pstr, SPInt len)
  28.224 {
  28.225     if (!pstr)
  28.226         return;
  28.227 
  28.228     DataDesc*   pdata = GetData();
  28.229     UPInt       oldSize = pdata->GetSize();    
  28.230     UPInt       encodeSize = (UPInt)UTF8Util::GetEncodeStringSize(pstr, len);
  28.231 
  28.232     DataDesc*   pnewData = AllocDataCopy1(oldSize + (UPInt)encodeSize, 0,
  28.233                                           pdata->Data, oldSize);
  28.234     UTF8Util::EncodeString(pnewData->Data + oldSize,  pstr, len);
  28.235 
  28.236     SetData(pnewData);
  28.237     pdata->Release();
  28.238 }
  28.239 
  28.240 
  28.241 void String::AppendString(const char* putf8str, SPInt utf8StrSz)
  28.242 {
  28.243     if (!putf8str || !utf8StrSz)
  28.244         return;
  28.245     if (utf8StrSz == -1)
  28.246         utf8StrSz = (SPInt)OVR_strlen(putf8str);
  28.247 
  28.248     DataDesc*   pdata = GetData();
  28.249     UPInt       oldSize = pdata->GetSize();
  28.250 
  28.251     SetData(AllocDataCopy2(oldSize + (UPInt)utf8StrSz, 0,
  28.252                            pdata->Data, oldSize, putf8str, (UPInt)utf8StrSz));
  28.253     pdata->Release();
  28.254 }
  28.255 
  28.256 void    String::AssignString(const InitStruct& src, UPInt size)
  28.257 {
  28.258     DataDesc*   poldData = GetData();
  28.259     DataDesc*   pnewData = AllocData(size, 0);
  28.260     src.InitString(pnewData->Data, size);
  28.261     SetData(pnewData);
  28.262     poldData->Release();
  28.263 }
  28.264 
  28.265 void    String::AssignString(const char* putf8str, UPInt size)
  28.266 {
  28.267     DataDesc* poldData = GetData();
  28.268     SetData(AllocDataCopy1(size, 0, putf8str, size));
  28.269     poldData->Release();
  28.270 }
  28.271 
  28.272 void    String::operator = (const char* pstr)
  28.273 {
  28.274     AssignString(pstr, pstr ? OVR_strlen(pstr) : 0);
  28.275 }
  28.276 
  28.277 void    String::operator = (const wchar_t* pwstr)
  28.278 {
  28.279     DataDesc*   poldData = GetData();
  28.280     UPInt       size = pwstr ? (UPInt)UTF8Util::GetEncodeStringSize(pwstr) : 0;
  28.281 
  28.282     DataDesc*   pnewData = AllocData(size, 0);
  28.283     UTF8Util::EncodeString(pnewData->Data, pwstr);
  28.284     SetData(pnewData);
  28.285     poldData->Release();
  28.286 }
  28.287 
  28.288 
  28.289 void    String::operator = (const String& src)
  28.290 {     
  28.291     DataDesc*    psdata = src.GetData();
  28.292     DataDesc*    pdata = GetData();    
  28.293 
  28.294     SetData(psdata);
  28.295     psdata->AddRef();
  28.296     pdata->Release();
  28.297 }
  28.298 
  28.299 
  28.300 void    String::operator = (const StringBuffer& src)
  28.301 { 
  28.302     DataDesc* polddata = GetData();    
  28.303     SetData(AllocDataCopy1(src.GetSize(), 0, src.ToCStr(), src.GetSize()));
  28.304     polddata->Release();
  28.305 }
  28.306 
  28.307 void    String::operator += (const String& src)
  28.308 {
  28.309     DataDesc   *pourData = GetData(),
  28.310                *psrcData = src.GetData();
  28.311     UPInt       ourSize  = pourData->GetSize(),
  28.312                 srcSize  = psrcData->GetSize();
  28.313     UPInt       lflag    = pourData->GetLengthFlag() & psrcData->GetLengthFlag();
  28.314 
  28.315     SetData(AllocDataCopy2(ourSize + srcSize, lflag,
  28.316                            pourData->Data, ourSize, psrcData->Data, srcSize));
  28.317     pourData->Release();
  28.318 }
  28.319 
  28.320 
  28.321 String   String::operator + (const char* str) const
  28.322 {   
  28.323     String tmp1(*this);
  28.324     tmp1 += (str ? str : "");
  28.325     return tmp1;
  28.326 }
  28.327 
  28.328 String   String::operator + (const String& src) const
  28.329 { 
  28.330     String tmp1(*this);
  28.331     tmp1 += src;
  28.332     return tmp1;
  28.333 }
  28.334 
  28.335 void    String::Remove(UPInt posAt, SPInt removeLength)
  28.336 {
  28.337     DataDesc*   pdata = GetData();
  28.338     UPInt       oldSize = pdata->GetSize();    
  28.339     // Length indicates the number of characters to remove. 
  28.340     UPInt       length = GetLength();
  28.341 
  28.342     // If index is past the string, nothing to remove.
  28.343     if (posAt >= length)
  28.344         return;
  28.345     // Otherwise, cap removeLength to the length of the string.
  28.346     if ((posAt + removeLength) > length)
  28.347         removeLength = length - posAt;
  28.348 
  28.349     // Get the byte position of the UTF8 char at position posAt.
  28.350     SPInt bytePos    = UTF8Util::GetByteIndex(posAt, pdata->Data, oldSize);
  28.351     SPInt removeSize = UTF8Util::GetByteIndex(removeLength, pdata->Data + bytePos, oldSize-bytePos);
  28.352 
  28.353     SetData(AllocDataCopy2(oldSize - removeSize, pdata->GetLengthFlag(),
  28.354                            pdata->Data, bytePos,
  28.355                            pData->Data + bytePos + removeSize, (oldSize - bytePos - removeSize)));
  28.356     pdata->Release();
  28.357 }
  28.358 
  28.359 
  28.360 String   String::Substring(UPInt start, UPInt end) const
  28.361 {
  28.362     UPInt length = GetLength();
  28.363     if ((start >= length) || (start >= end))
  28.364         return String();   
  28.365 
  28.366     DataDesc* pdata = GetData();
  28.367     
  28.368     // If size matches, we know the exact index range.
  28.369     if (pdata->LengthIsSize())
  28.370         return String(pdata->Data + start, end - start);
  28.371     
  28.372     // Get position of starting character.
  28.373     SPInt byteStart = UTF8Util::GetByteIndex(start, pdata->Data, pdata->GetSize());
  28.374     SPInt byteSize  = UTF8Util::GetByteIndex(end - start, pdata->Data + byteStart, pdata->GetSize()-byteStart);
  28.375     return String(pdata->Data + byteStart, (UPInt)byteSize);
  28.376 }
  28.377 
  28.378 void String::Clear()
  28.379 {   
  28.380     NullData.AddRef();
  28.381     GetData()->Release();
  28.382     SetData(&NullData);
  28.383 }
  28.384 
  28.385 
  28.386 String   String::ToUpper() const 
  28.387 {       
  28.388     UInt32      c;
  28.389     const char* psource = GetData()->Data;
  28.390     const char* pend = psource + GetData()->GetSize();
  28.391     String      str;
  28.392     SPInt       bufferOffset = 0;
  28.393     char        buffer[512];
  28.394     
  28.395     while(psource < pend)
  28.396     {
  28.397         do {            
  28.398             c = UTF8Util::DecodeNextChar_Advance0(&psource);
  28.399             UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towupper(wchar_t(c)));
  28.400         } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
  28.401 
  28.402         // Append string a piece at a time.
  28.403         str.AppendString(buffer, bufferOffset);
  28.404         bufferOffset = 0;
  28.405     }
  28.406 
  28.407     return str;
  28.408 }
  28.409 
  28.410 String   String::ToLower() const 
  28.411 {
  28.412     UInt32      c;
  28.413     const char* psource = GetData()->Data;
  28.414     const char* pend = psource + GetData()->GetSize();
  28.415     String      str;
  28.416     SPInt       bufferOffset = 0;
  28.417     char        buffer[512];
  28.418 
  28.419     while(psource < pend)
  28.420     {
  28.421         do {
  28.422             c = UTF8Util::DecodeNextChar_Advance0(&psource);
  28.423             UTF8Util::EncodeChar(buffer, &bufferOffset, OVR_towlower(wchar_t(c)));
  28.424         } while ((psource < pend) && (bufferOffset < SPInt(sizeof(buffer)-8)));
  28.425 
  28.426         // Append string a piece at a time.
  28.427         str.AppendString(buffer, bufferOffset);
  28.428         bufferOffset = 0;
  28.429     }
  28.430 
  28.431     return str;
  28.432 }
  28.433 
  28.434 
  28.435 
  28.436 String& String::Insert(const char* substr, UPInt posAt, SPInt strSize)
  28.437 {
  28.438     DataDesc* poldData   = GetData();
  28.439     UPInt     oldSize    = poldData->GetSize();
  28.440     UPInt     insertSize = (strSize < 0) ? OVR_strlen(substr) : (UPInt)strSize;    
  28.441     UPInt     byteIndex  =  (poldData->LengthIsSize()) ?
  28.442                             posAt : (UPInt)UTF8Util::GetByteIndex(posAt, poldData->Data, oldSize);
  28.443 
  28.444     OVR_ASSERT(byteIndex <= oldSize);
  28.445     
  28.446     DataDesc* pnewData = AllocDataCopy2(oldSize + insertSize, 0,
  28.447                                         poldData->Data, byteIndex, substr, insertSize);
  28.448     memcpy(pnewData->Data + byteIndex + insertSize,
  28.449            poldData->Data + byteIndex, oldSize - byteIndex);
  28.450     SetData(pnewData);
  28.451     poldData->Release();
  28.452     return *this;
  28.453 }
  28.454 
  28.455 /*
  28.456 String& String::Insert(const UInt32* substr, UPInt posAt, SPInt len)
  28.457 {
  28.458     for (SPInt i = 0; i < len; ++i)
  28.459     {
  28.460         UPInt charw = InsertCharAt(substr[i], posAt);
  28.461         posAt += charw;
  28.462     }
  28.463     return *this;
  28.464 }
  28.465 */
  28.466 
  28.467 UPInt String::InsertCharAt(UInt32 c, UPInt posAt)
  28.468 {
  28.469     char    buf[8];
  28.470     SPInt   index = 0;
  28.471     UTF8Util::EncodeChar(buf, &index, c);
  28.472     OVR_ASSERT(index >= 0);
  28.473     buf[(UPInt)index] = 0;
  28.474 
  28.475     Insert(buf, posAt, index);
  28.476     return (UPInt)index;
  28.477 }
  28.478 
  28.479 
  28.480 int String::CompareNoCase(const char* a, const char* b)
  28.481 {
  28.482     return OVR_stricmp(a, b);
  28.483 }
  28.484 
  28.485 int String::CompareNoCase(const char* a, const char* b, SPInt len)
  28.486 {
  28.487     if (len)
  28.488     {
  28.489         SPInt f,l;
  28.490         SPInt slen = len;
  28.491         const char *s = b;
  28.492         do {
  28.493             f = (SPInt)OVR_tolower((int)(*(a++)));
  28.494             l = (SPInt)OVR_tolower((int)(*(b++)));
  28.495         } while (--len && f && (f == l) && *b != 0);
  28.496 
  28.497         if (f == l && (len != 0 || *b != 0))
  28.498         {
  28.499             f = (SPInt)slen;
  28.500             l = (SPInt)OVR_strlen(s);
  28.501             return int(f - l);
  28.502         }
  28.503 
  28.504         return int(f - l);
  28.505     }
  28.506     else
  28.507         return (0-(int)OVR_strlen(b));
  28.508 }
  28.509 
  28.510 // ***** Implement hash static functions
  28.511 
  28.512 // Hash function
  28.513 UPInt String::BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed)
  28.514 {
  28.515     const UByte*    pdata   = (const UByte*) pdataIn;
  28.516     UPInt           h       = seed;
  28.517     while (size > 0)
  28.518     {
  28.519         size--;
  28.520         h = ((h << 5) + h) ^ (unsigned) pdata[size];
  28.521     }
  28.522 
  28.523     return h;
  28.524 }
  28.525 
  28.526 // Hash function, case-insensitive
  28.527 UPInt String::BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed)
  28.528 {
  28.529     const UByte*    pdata = (const UByte*) pdataIn;
  28.530     UPInt           h = seed;
  28.531     while (size > 0)
  28.532     {
  28.533         size--;
  28.534         h = ((h << 5) + h) ^ OVR_tolower(pdata[size]);
  28.535     }
  28.536 
  28.537     // Alternative: "sdbm" hash function, suggested at same web page above.
  28.538     // h = 0;
  28.539     // for bytes { h = (h << 16) + (h << 6) - hash + *p; }
  28.540     return h;
  28.541 }
  28.542 
  28.543 
  28.544 
  28.545 // ***** String Buffer used for Building Strings
  28.546 
  28.547 
  28.548 #define OVR_SBUFF_DEFAULT_GROW_SIZE 512
  28.549 // Constructors / Destructor.
  28.550 StringBuffer::StringBuffer()
  28.551     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  28.552 {
  28.553 }
  28.554 
  28.555 StringBuffer::StringBuffer(UPInt growSize)
  28.556     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  28.557 {
  28.558     SetGrowSize(growSize);
  28.559 }
  28.560 
  28.561 StringBuffer::StringBuffer(const char* data)
  28.562     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  28.563 {
  28.564     *this = data;
  28.565 }
  28.566 
  28.567 StringBuffer::StringBuffer(const char* data, UPInt dataSize)
  28.568     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  28.569 {
  28.570     AppendString(data, dataSize);
  28.571 }
  28.572 
  28.573 StringBuffer::StringBuffer(const String& src)
  28.574     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  28.575 {
  28.576     AppendString(src.ToCStr(), src.GetSize());
  28.577 }
  28.578 
  28.579 StringBuffer::StringBuffer(const StringBuffer& src)
  28.580     : pData(NULL), Size(0), BufferSize(src.GetGrowSize()), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  28.581 {
  28.582     AppendString(src.ToCStr(), src.GetSize());
  28.583     LengthIsSize = src.LengthIsSize;
  28.584 }
  28.585 
  28.586 StringBuffer::StringBuffer(const wchar_t* data)
  28.587     : pData(NULL), Size(0), BufferSize(0), GrowSize(OVR_SBUFF_DEFAULT_GROW_SIZE), LengthIsSize(false)
  28.588 {
  28.589     *this = data;
  28.590 }
  28.591 
  28.592 StringBuffer::~StringBuffer()
  28.593 {
  28.594     if (pData)
  28.595         OVR_FREE(pData);
  28.596 }
  28.597 void StringBuffer::SetGrowSize(UPInt growSize) 
  28.598 { 
  28.599     if (growSize <= 16)
  28.600         GrowSize = 16;
  28.601     else
  28.602     {
  28.603         UByte bits = Alg::UpperBit(UInt32(growSize-1));
  28.604         UPInt size = 1<<bits;
  28.605         GrowSize = size == growSize ? growSize : size;
  28.606     }
  28.607 }
  28.608 
  28.609 UPInt StringBuffer::GetLength() const
  28.610 {
  28.611     UPInt length, size = GetSize();
  28.612     if (LengthIsSize)
  28.613         return size;
  28.614 
  28.615     length = (UPInt)UTF8Util::GetLength(pData, (UPInt)GetSize());
  28.616 
  28.617     if (length == GetSize())
  28.618         LengthIsSize = true;
  28.619     return length;
  28.620 }
  28.621 
  28.622 void    StringBuffer::Reserve(UPInt _size)
  28.623 {
  28.624     if (_size >= BufferSize) // >= because of trailing zero! (!AB)
  28.625     {
  28.626         BufferSize = (_size + 1 + GrowSize - 1)& ~(GrowSize-1);
  28.627         if (!pData)
  28.628             pData = (char*)OVR_ALLOC(BufferSize);
  28.629         else 
  28.630             pData = (char*)OVR_REALLOC(pData, BufferSize);
  28.631     }
  28.632 }
  28.633 void    StringBuffer::Resize(UPInt _size)
  28.634 {
  28.635     Reserve(_size);
  28.636     LengthIsSize = false;
  28.637     Size = _size;
  28.638     if (pData)
  28.639         pData[Size] = 0;
  28.640 }
  28.641 
  28.642 void StringBuffer::Clear()
  28.643 {
  28.644     Resize(0);
  28.645     /*
  28.646     if (pData != pEmptyNullData)
  28.647     {
  28.648         OVR_FREE(pHeap, pData);
  28.649         pData = pEmptyNullData;
  28.650         Size = BufferSize = 0;
  28.651         LengthIsSize = false;
  28.652     }
  28.653     */
  28.654 }
  28.655 // Appends a character
  28.656 void     StringBuffer::AppendChar(UInt32 ch)
  28.657 {
  28.658     char    buff[8];
  28.659     UPInt   origSize = GetSize();
  28.660 
  28.661     // Converts ch into UTF8 string and fills it into buff. Also increments index according to the number of bytes
  28.662     // in the UTF8 string.
  28.663     SPInt   srcSize = 0;
  28.664     UTF8Util::EncodeChar(buff, &srcSize, ch);
  28.665     OVR_ASSERT(srcSize >= 0);
  28.666     
  28.667     UPInt size = origSize + srcSize;
  28.668     Resize(size);
  28.669     memcpy(pData + origSize, buff, srcSize);
  28.670 }
  28.671 
  28.672 // Append a string
  28.673 void     StringBuffer::AppendString(const wchar_t* pstr, SPInt len)
  28.674 {
  28.675     if (!pstr)
  28.676         return;
  28.677 
  28.678     SPInt   srcSize     = UTF8Util::GetEncodeStringSize(pstr, len);
  28.679     UPInt   origSize    = GetSize();
  28.680     UPInt   size        = srcSize + origSize;
  28.681 
  28.682     Resize(size);
  28.683     UTF8Util::EncodeString(pData + origSize,  pstr, len);
  28.684 }
  28.685 
  28.686 void      StringBuffer::AppendString(const char* putf8str, SPInt utf8StrSz)
  28.687 {
  28.688     if (!putf8str || !utf8StrSz)
  28.689         return;
  28.690     if (utf8StrSz == -1)
  28.691         utf8StrSz = (SPInt)OVR_strlen(putf8str);
  28.692 
  28.693     UPInt   origSize    = GetSize();
  28.694     UPInt   size        = utf8StrSz + origSize;
  28.695 
  28.696     Resize(size);
  28.697     memcpy(pData + origSize, putf8str, utf8StrSz);
  28.698 }
  28.699 
  28.700 
  28.701 void      StringBuffer::operator = (const char* pstr)
  28.702 {
  28.703     pstr = pstr ? pstr : "";
  28.704     UPInt size = OVR_strlen(pstr);
  28.705     Resize(size);
  28.706     memcpy(pData, pstr, size);
  28.707 }
  28.708 
  28.709 void      StringBuffer::operator = (const wchar_t* pstr)
  28.710 {
  28.711     pstr = pstr ? pstr : L"";
  28.712     UPInt size = (UPInt)UTF8Util::GetEncodeStringSize(pstr);
  28.713     Resize(size);
  28.714     UTF8Util::EncodeString(pData, pstr);
  28.715 }
  28.716 
  28.717 void      StringBuffer::operator = (const String& src)
  28.718 {
  28.719     Resize(src.GetSize());
  28.720     memcpy(pData, src.ToCStr(), src.GetSize());
  28.721 }
  28.722 
  28.723 
  28.724 // Inserts substr at posAt
  28.725 void      StringBuffer::Insert(const char* substr, UPInt posAt, SPInt len)
  28.726 {
  28.727     UPInt     oldSize    = Size;
  28.728     UPInt     insertSize = (len < 0) ? OVR_strlen(substr) : (UPInt)len;    
  28.729     UPInt     byteIndex  = LengthIsSize ? posAt : 
  28.730                            (UPInt)UTF8Util::GetByteIndex(posAt, pData, (SPInt)Size);
  28.731 
  28.732     OVR_ASSERT(byteIndex <= oldSize);
  28.733     Reserve(oldSize + insertSize);
  28.734 
  28.735     memmove(pData + byteIndex + insertSize, pData + byteIndex, oldSize - byteIndex + 1);
  28.736     memcpy (pData + byteIndex, substr, insertSize);
  28.737     LengthIsSize = false;
  28.738     Size = oldSize + insertSize;
  28.739     pData[Size] = 0;
  28.740 }
  28.741 
  28.742 // Inserts character at posAt
  28.743 UPInt     StringBuffer::InsertCharAt(UInt32 c, UPInt posAt)
  28.744 {
  28.745     char    buf[8];
  28.746     SPInt   len = 0;
  28.747     UTF8Util::EncodeChar(buf, &len, c);
  28.748     OVR_ASSERT(len >= 0);
  28.749     buf[(UPInt)len] = 0;
  28.750 
  28.751     Insert(buf, posAt, len);
  28.752     return (UPInt)len;
  28.753 }
  28.754 
  28.755 } // OVR
  28.756 \ No newline at end of file
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/libovr/Src/Kernel/OVR_String.h	Sat Sep 14 16:14:59 2013 +0300
    29.3 @@ -0,0 +1,1 @@
    29.4 +/************************************************************************************
    29.5 
    29.6 PublicHeader:   OVR.h
    29.7 Filename    :   OVR_String.h
    29.8 Content     :   String UTF8 string implementation with copy-on-write semantics
    29.9                 (thread-safe for assignment but not modification).
   29.10 Created     :   September 19, 2012
   29.11 Notes       : 
   29.12 
   29.13 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   29.14 
   29.15 Use of this software is subject to the terms of the Oculus license
   29.16 agreement provided at the time of installation or download, or which
   29.17 otherwise accompanies this software in either electronic or hard copy form.
   29.18 
   29.19 ************************************************************************************/
   29.20 
   29.21 #ifndef OVR_String_h
   29.22 #define OVR_String_h
   29.23 
   29.24 #include "OVR_Types.h"
   29.25 #include "OVR_Allocator.h"
   29.26 #include "OVR_UTF8Util.h"
   29.27 #include "OVR_Atomic.h"
   29.28 #include "OVR_Std.h"
   29.29 #include "OVR_Alg.h"
   29.30 
   29.31 namespace OVR {
   29.32 
   29.33 // ***** Classes
   29.34 
   29.35 class String;
   29.36 class StringBuffer;
   29.37 
   29.38 
   29.39 //-----------------------------------------------------------------------------------
   29.40 // ***** String Class 
   29.41 
   29.42 // String is UTF8 based string class with copy-on-write implementation
   29.43 // for assignment.
   29.44 
   29.45 class String
   29.46 {
   29.47 protected:
   29.48 
   29.49     enum FlagConstants
   29.50     {
   29.51         //Flag_GetLength      = 0x7FFFFFFF,
   29.52         // This flag is set if GetLength() == GetSize() for a string.
   29.53         // Avoid extra scanning is Substring and indexing logic.
   29.54         Flag_LengthIsSizeShift   = (sizeof(UPInt)*8 - 1)
   29.55     };
   29.56 
   29.57 
   29.58     // Internal structure to hold string data
   29.59     struct DataDesc
   29.60     {
   29.61         // Number of bytes. Will be the same as the number of chars if the characters
   29.62         // are ascii, may not be equal to number of chars in case string data is UTF8.
   29.63         UPInt   Size;       
   29.64         volatile SInt32 RefCount;
   29.65         char    Data[1];
   29.66 
   29.67         void    AddRef()
   29.68         {
   29.69             AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, 1);
   29.70         }
   29.71         // Decrement ref count. This needs to be thread-safe, since
   29.72         // a different thread could have also decremented the ref count.
   29.73         // For example, if u start off with a ref count = 2. Now if u
   29.74         // decrement the ref count and check against 0 in different
   29.75         // statements, a different thread can also decrement the ref count
   29.76         // in between our decrement and checking against 0 and will find
   29.77         // the ref count = 0 and delete the object. This will lead to a crash
   29.78         // when context switches to our thread and we'll be trying to delete
   29.79         // an already deleted object. Hence decrementing the ref count and
   29.80         // checking against 0 needs to made an atomic operation.
   29.81         void    Release()
   29.82         {
   29.83             if ((AtomicOps<SInt32>::ExchangeAdd_NoSync(&RefCount, -1) - 1) == 0)
   29.84                 OVR_FREE(this);
   29.85         }
   29.86 
   29.87         static UPInt GetLengthFlagBit()     { return UPInt(1) << Flag_LengthIsSizeShift; }
   29.88         UPInt       GetSize() const         { return Size & ~GetLengthFlagBit() ; }
   29.89         UPInt       GetLengthFlag()  const  { return Size & GetLengthFlagBit(); }
   29.90         bool        LengthIsSize() const    { return GetLengthFlag() != 0; }
   29.91     };
   29.92 
   29.93     // Heap type of the string is encoded in the lower bits.
   29.94     enum HeapType
   29.95     {
   29.96         HT_Global   = 0,    // Heap is global.
   29.97         HT_Local    = 1,    // SF::String_loc: Heap is determined based on string's address.
   29.98         HT_Dynamic  = 2,    // SF::String_temp: Heap is stored as a part of the class.
   29.99         HT_Mask     = 3
  29.100     };
  29.101 
  29.102     union {
  29.103         DataDesc* pData;
  29.104         UPInt     HeapTypeBits;
  29.105     };
  29.106     typedef union {
  29.107         DataDesc* pData;
  29.108         UPInt     HeapTypeBits;
  29.109     } DataDescUnion;
  29.110 
  29.111     inline HeapType    GetHeapType() const { return (HeapType) (HeapTypeBits & HT_Mask); }
  29.112 
  29.113     inline DataDesc*   GetData() const
  29.114     {
  29.115         DataDescUnion u;
  29.116         u.pData    = pData;
  29.117         u.HeapTypeBits = (u.HeapTypeBits & ~(UPInt)HT_Mask);
  29.118         return u.pData;
  29.119     }
  29.120     
  29.121     inline void        SetData(DataDesc* pdesc)
  29.122     {
  29.123         HeapType ht = GetHeapType();
  29.124         pData = pdesc;
  29.125         OVR_ASSERT((HeapTypeBits & HT_Mask) == 0);
  29.126         HeapTypeBits |= ht;        
  29.127     }
  29.128 
  29.129     
  29.130     DataDesc*   AllocData(UPInt size, UPInt lengthIsSize);
  29.131     DataDesc*   AllocDataCopy1(UPInt size, UPInt lengthIsSize,
  29.132                                const char* pdata, UPInt copySize);
  29.133     DataDesc*   AllocDataCopy2(UPInt size, UPInt lengthIsSize,
  29.134                                const char* pdata1, UPInt copySize1,
  29.135                                const char* pdata2, UPInt copySize2);
  29.136 
  29.137     // Special constructor to avoid data initalization when used in derived class.
  29.138     struct NoConstructor { };
  29.139     String(const NoConstructor&) { }
  29.140 
  29.141 public:
  29.142 
  29.143     // For initializing string with dynamic buffer
  29.144     struct InitStruct
  29.145     {
  29.146         virtual ~InitStruct() { }
  29.147         virtual void InitString(char* pbuffer, UPInt size) const = 0;
  29.148     };
  29.149 
  29.150 
  29.151     // Constructors / Destructors.
  29.152     String();
  29.153     String(const char* data);
  29.154     String(const char* data1, const char* pdata2, const char* pdata3 = 0);
  29.155     String(const char* data, UPInt buflen);
  29.156     String(const String& src);
  29.157     String(const StringBuffer& src);
  29.158     String(const InitStruct& src, UPInt size);
  29.159     explicit String(const wchar_t* data);      
  29.160 
  29.161     // Destructor (Captain Obvious guarantees!)
  29.162     ~String()
  29.163     {
  29.164         GetData()->Release();
  29.165     }
  29.166 
  29.167     // Declaration of NullString
  29.168     static DataDesc NullData;
  29.169 
  29.170 
  29.171     // *** General Functions
  29.172 
  29.173     void        Clear();
  29.174 
  29.175     // For casting to a pointer to char.
  29.176     operator const char*() const        { return GetData()->Data; }
  29.177     // Pointer to raw buffer.
  29.178     const char* ToCStr() const          { return GetData()->Data; }
  29.179 
  29.180     // Returns number of bytes
  29.181     UPInt       GetSize() const         { return GetData()->GetSize() ; }
  29.182     // Tells whether or not the string is empty
  29.183     bool        IsEmpty() const         { return GetSize() == 0; }
  29.184 
  29.185     // Returns  number of characters
  29.186     UPInt       GetLength() const;
  29.187 
  29.188     // Returns  character at the specified index
  29.189     UInt32      GetCharAt(UPInt index) const;
  29.190     UInt32      GetFirstCharAt(UPInt index, const char** offset) const;
  29.191     UInt32      GetNextChar(const char** offset) const;
  29.192 
  29.193     // Appends a character
  29.194     void        AppendChar(UInt32 ch);
  29.195 
  29.196     // Append a string
  29.197     void        AppendString(const wchar_t* pstr, SPInt len = -1);
  29.198     void        AppendString(const char* putf8str, SPInt utf8StrSz = -1);
  29.199 
  29.200     // Assigned a string with dynamic data (copied through initializer).
  29.201     void        AssignString(const InitStruct& src, UPInt size);
  29.202     // Assigns string with known size.
  29.203     void        AssignString(const char* putf8str, UPInt size);
  29.204 
  29.205     //  Resize the string to the new size
  29.206 //  void        Resize(UPInt _size);
  29.207 
  29.208     // Removes the character at posAt
  29.209     void        Remove(UPInt posAt, SPInt len = 1);
  29.210 
  29.211     // Returns a String that's a substring of this.
  29.212     //  -start is the index of the first UTF8 character you want to include.
  29.213     //  -end is the index one past the last UTF8 character you want to include.
  29.214     String   Substring(UPInt start, UPInt end) const;
  29.215 
  29.216     // Case-conversion
  29.217     String   ToUpper() const;
  29.218     String   ToLower() const;
  29.219 
  29.220     // Inserts substr at posAt
  29.221     String&    Insert (const char* substr, UPInt posAt, SPInt len = -1);
  29.222 
  29.223     // Inserts character at posAt
  29.224     UPInt       InsertCharAt(UInt32 c, UPInt posAt);
  29.225 
  29.226     // Inserts substr at posAt, which is an index of a character (not byte).
  29.227     // Of size is specified, it is in bytes.
  29.228 //  String&    Insert(const UInt32* substr, UPInt posAt, SPInt size = -1);
  29.229 
  29.230     // Get Byte index of the character at position = index
  29.231     UPInt       GetByteIndex(UPInt index) const { return (UPInt)UTF8Util::GetByteIndex(index, GetData()->Data); }
  29.232 
  29.233     // Utility: case-insensitive string compare.  stricmp() & strnicmp() are not
  29.234     // ANSI or POSIX, do not seem to appear in Linux.
  29.235     static int OVR_STDCALL   CompareNoCase(const char* a, const char* b);
  29.236     static int OVR_STDCALL   CompareNoCase(const char* a, const char* b, SPInt len);
  29.237 
  29.238     // Hash function, case-insensitive
  29.239     static UPInt OVR_STDCALL BernsteinHashFunctionCIS(const void* pdataIn, UPInt size, UPInt seed = 5381);
  29.240 
  29.241     // Hash function, case-sensitive
  29.242     static UPInt OVR_STDCALL BernsteinHashFunction(const void* pdataIn, UPInt size, UPInt seed = 5381);
  29.243 
  29.244 
  29.245     // ***** File path parsing helper functions.
  29.246     // Implemented in OVR_String_FilePath.cpp.
  29.247 
  29.248     // Absolute paths can star with:
  29.249     //  - protocols:        'file://', 'http://'
  29.250     //  - windows drive:    'c:\'
  29.251     //  - UNC share name:   '\\share'
  29.252     //  - unix root         '/'
  29.253     static bool HasAbsolutePath(const char* path);
  29.254     static bool HasExtension(const char* path);
  29.255     static bool HasProtocol(const char* path);
  29.256 
  29.257     bool    HasAbsolutePath() const { return HasAbsolutePath(ToCStr()); }
  29.258     bool    HasExtension() const    { return HasExtension(ToCStr()); }
  29.259     bool    HasProtocol() const     { return HasProtocol(ToCStr()); }
  29.260 
  29.261     String  GetProtocol() const;    // Returns protocol, if any, with trailing '://'.
  29.262     String  GetPath() const;        // Returns path with trailing '/'.
  29.263     String  GetFilename() const;    // Returns filename, including extension.
  29.264     String  GetExtension() const;   // Returns extension with a dot.
  29.265 
  29.266     void    StripProtocol();        // Strips front protocol, if any, from the string.
  29.267     void    StripExtension();       // Strips off trailing extension.
  29.268     
  29.269 
  29.270     // Operators
  29.271     // Assignment
  29.272     void        operator =  (const char* str);
  29.273     void        operator =  (const wchar_t* str);
  29.274     void        operator =  (const String& src);
  29.275     void        operator =  (const StringBuffer& src);
  29.276 
  29.277     // Addition
  29.278     void        operator += (const String& src);
  29.279     void        operator += (const char* psrc)       { AppendString(psrc); }
  29.280     void        operator += (const wchar_t* psrc)    { AppendString(psrc); }
  29.281     void        operator += (char  ch)               { AppendChar(ch); }
  29.282     String      operator +  (const char* str) const;
  29.283     String      operator +  (const String& src)  const;
  29.284 
  29.285     // Comparison
  29.286     bool        operator == (const String& str) const
  29.287     {
  29.288         return (OVR_strcmp(GetData()->Data, str.GetData()->Data)== 0);
  29.289     }
  29.290 
  29.291     bool        operator != (const String& str) const
  29.292     {
  29.293         return !operator == (str);
  29.294     }
  29.295 
  29.296     bool        operator == (const char* str) const
  29.297     {
  29.298         return OVR_strcmp(GetData()->Data, str) == 0;
  29.299     }
  29.300 
  29.301     bool        operator != (const char* str) const
  29.302     {
  29.303         return !operator == (str);
  29.304     }
  29.305 
  29.306     bool        operator <  (const char* pstr) const
  29.307     {
  29.308         return OVR_strcmp(GetData()->Data, pstr) < 0;
  29.309     }
  29.310 
  29.311     bool        operator <  (const String& str) const
  29.312     {
  29.313         return *this < str.GetData()->Data;
  29.314     }
  29.315 
  29.316     bool        operator >  (const char* pstr) const
  29.317     {
  29.318         return OVR_strcmp(GetData()->Data, pstr) > 0;
  29.319     }
  29.320 
  29.321     bool        operator >  (const String& str) const
  29.322     {
  29.323         return *this > str.GetData()->Data;
  29.324     }
  29.325 
  29.326     int CompareNoCase(const char* pstr) const
  29.327     {
  29.328         return CompareNoCase(GetData()->Data, pstr);
  29.329     }
  29.330     int CompareNoCase(const String& str) const
  29.331     {
  29.332         return CompareNoCase(GetData()->Data, str.ToCStr());
  29.333     }
  29.334 
  29.335     // Accesses raw bytes
  29.336     const char&     operator [] (int index) const
  29.337     {
  29.338         OVR_ASSERT(index >= 0 && (UPInt)index < GetSize());
  29.339         return GetData()->Data[index];
  29.340     }
  29.341     const char&     operator [] (UPInt index) const
  29.342     {
  29.343         OVR_ASSERT(index < GetSize());
  29.344         return GetData()->Data[index];
  29.345     }
  29.346 
  29.347 
  29.348     // Case insensitive keys are used to look up insensitive string in hash tables
  29.349     // for SWF files with version before SWF 7.
  29.350     struct NoCaseKey
  29.351     {   
  29.352         const String* pStr;
  29.353         NoCaseKey(const String &str) : pStr(&str){};
  29.354     };
  29.355 
  29.356     bool    operator == (const NoCaseKey& strKey) const
  29.357     {
  29.358         return (CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
  29.359     }
  29.360     bool    operator != (const NoCaseKey& strKey) const
  29.361     {
  29.362         return !(CompareNoCase(ToCStr(), strKey.pStr->ToCStr()) == 0);
  29.363     }
  29.364 
  29.365     // Hash functor used for strings.
  29.366     struct HashFunctor
  29.367     {    
  29.368         UPInt  operator()(const String& data) const
  29.369         {
  29.370             UPInt  size = data.GetSize();
  29.371             return String::BernsteinHashFunction((const char*)data, size);
  29.372         }        
  29.373     };
  29.374     // Case-insensitive hash functor used for strings. Supports additional
  29.375     // lookup based on NoCaseKey.
  29.376     struct NoCaseHashFunctor
  29.377     {    
  29.378         UPInt  operator()(const String& data) const
  29.379         {
  29.380             UPInt  size = data.GetSize();
  29.381             return String::BernsteinHashFunctionCIS((const char*)data, size);
  29.382         }
  29.383         UPInt  operator()(const NoCaseKey& data) const
  29.384         {       
  29.385             UPInt  size = data.pStr->GetSize();
  29.386             return String::BernsteinHashFunctionCIS((const char*)data.pStr->ToCStr(), size);
  29.387         }
  29.388     };
  29.389 
  29.390 };
  29.391 
  29.392 
  29.393 //-----------------------------------------------------------------------------------
  29.394 // ***** String Buffer used for Building Strings
  29.395 
  29.396 class StringBuffer
  29.397 {
  29.398     char*           pData;
  29.399     UPInt           Size;
  29.400     UPInt           BufferSize;
  29.401     UPInt           GrowSize;    
  29.402     mutable bool    LengthIsSize;    
  29.403 
  29.404 public:
  29.405 
  29.406     // Constructors / Destructor.    
  29.407     StringBuffer();
  29.408     explicit StringBuffer(UPInt growSize);
  29.409     StringBuffer(const char* data);
  29.410     StringBuffer(const char* data, UPInt buflen);
  29.411     StringBuffer(const String& src);
  29.412     StringBuffer(const StringBuffer& src);
  29.413     explicit StringBuffer(const wchar_t* data);
  29.414     ~StringBuffer();
  29.415     
  29.416 
  29.417     // Modify grow size used for growing/shrinking the buffer.
  29.418     UPInt       GetGrowSize() const         { return GrowSize; }
  29.419     void        SetGrowSize(UPInt growSize);
  29.420     
  29.421 
  29.422     // *** General Functions
  29.423     // Does not release memory, just sets Size to 0
  29.424     void        Clear();
  29.425 
  29.426     // For casting to a pointer to char.
  29.427     operator const char*() const        { return (pData) ? pData : ""; }
  29.428     // Pointer to raw buffer.
  29.429     const char* ToCStr() const          { return (pData) ? pData : ""; }
  29.430 
  29.431     // Returns number of bytes.
  29.432     UPInt       GetSize() const         { return Size ; }
  29.433     // Tells whether or not the string is empty.
  29.434     bool        IsEmpty() const         { return GetSize() == 0; }
  29.435 
  29.436     // Returns  number of characters
  29.437     UPInt       GetLength() const;
  29.438 
  29.439     // Returns  character at the specified index
  29.440     UInt32      GetCharAt(UPInt index) const;
  29.441     UInt32      GetFirstCharAt(UPInt index, const char** offset) const;
  29.442     UInt32      GetNextChar(const char** offset) const;
  29.443 
  29.444 
  29.445     //  Resize the string to the new size
  29.446     void        Resize(UPInt _size);
  29.447     void        Reserve(UPInt _size);
  29.448 
  29.449     // Appends a character
  29.450     void        AppendChar(UInt32 ch);
  29.451 
  29.452     // Append a string
  29.453     void        AppendString(const wchar_t* pstr, SPInt len = -1);
  29.454     void        AppendString(const char* putf8str, SPInt utf8StrSz = -1);
  29.455     void        AppendFormat(const char* format, ...);
  29.456 
  29.457     // Assigned a string with dynamic data (copied through initializer).
  29.458     //void        AssignString(const InitStruct& src, UPInt size);
  29.459 
  29.460     // Inserts substr at posAt
  29.461     void        Insert (const char* substr, UPInt posAt, SPInt len = -1);
  29.462     // Inserts character at posAt
  29.463     UPInt       InsertCharAt(UInt32 c, UPInt posAt);
  29.464 
  29.465     // Assignment
  29.466     void        operator =  (const char* str);
  29.467     void        operator =  (const wchar_t* str);
  29.468     void        operator =  (const String& src);
  29.469 
  29.470     // Addition
  29.471     void        operator += (const String& src)      { AppendString(src.ToCStr(),src.GetSize()); }
  29.472     void        operator += (const char* psrc)       { AppendString(psrc); }
  29.473     void        operator += (const wchar_t* psrc)    { AppendString(psrc); }
  29.474     void        operator += (char  ch)               { AppendChar(ch); }
  29.475     //String   operator +  (const char* str) const ;
  29.476     //String   operator +  (const String& src)  const ;
  29.477 
  29.478     // Accesses raw bytes
  29.479     char&       operator [] (int index)
  29.480     {
  29.481         OVR_ASSERT(((UPInt)index) < GetSize());
  29.482         return pData[index];
  29.483     }
  29.484     char&       operator [] (UPInt index)
  29.485     {
  29.486         OVR_ASSERT(index < GetSize());
  29.487         return pData[index];
  29.488     }
  29.489 
  29.490     const char&     operator [] (int index) const 
  29.491     {
  29.492         OVR_ASSERT(((UPInt)index) < GetSize());
  29.493         return pData[index];
  29.494     }
  29.495     const char&     operator [] (UPInt index) const
  29.496     {
  29.497         OVR_ASSERT(index < GetSize());
  29.498         return pData[index];
  29.499     }
  29.500 };
  29.501 
  29.502 
  29.503 //
  29.504 // Wrapper for string data. The data must have a guaranteed 
  29.505 // lifespan throughout the usage of the wrapper. Not intended for 
  29.506 // cached usage. Not thread safe.
  29.507 //
  29.508 class StringDataPtr
  29.509 {
  29.510 public:
  29.511     StringDataPtr() : pStr(NULL), Size(0) {}
  29.512     StringDataPtr(const StringDataPtr& p)
  29.513         : pStr(p.pStr), Size(p.Size) {}
  29.514     StringDataPtr(const char* pstr, UPInt sz)
  29.515         : pStr(pstr), Size(sz) {}
  29.516     StringDataPtr(const char* pstr)
  29.517         : pStr(pstr), Size((pstr != NULL) ? OVR_strlen(pstr) : 0) {}
  29.518     explicit StringDataPtr(const String& str)
  29.519         : pStr(str.ToCStr()), Size(str.GetSize()) {}
  29.520     template <typename T, int N> 
  29.521     StringDataPtr(const T (&v)[N])
  29.522         : pStr(v), Size(N) {}
  29.523 
  29.524 public:
  29.525     const char* ToCStr() const { return pStr; }
  29.526     UPInt       GetSize() const { return Size; }
  29.527     bool        IsEmpty() const { return GetSize() == 0; }
  29.528 
  29.529     // value is a prefix of this string
  29.530     // Character's values are not compared.
  29.531     bool        IsPrefix(const StringDataPtr& value) const
  29.532     {
  29.533         return ToCStr() == value.ToCStr() && GetSize() >= value.GetSize();
  29.534     }
  29.535     // value is a suffix of this string
  29.536     // Character's values are not compared.
  29.537     bool        IsSuffix(const StringDataPtr& value) const
  29.538     {
  29.539         return ToCStr() <= value.ToCStr() && (End()) == (value.End());
  29.540     }
  29.541 
  29.542     // Find first character.
  29.543     // init_ind - initial index.
  29.544     SPInt       FindChar(char c, UPInt init_ind = 0) const 
  29.545     {
  29.546         for (UPInt i = init_ind; i < GetSize(); ++i)
  29.547             if (pStr[i] == c)
  29.548                 return static_cast<SPInt>(i);
  29.549 
  29.550         return -1; 
  29.551     }
  29.552 
  29.553     // Find last character.
  29.554     // init_ind - initial index.
  29.555     SPInt       FindLastChar(char c, UPInt init_ind = ~0) const 
  29.556     {
  29.557         if (init_ind == (UPInt)~0 || init_ind > GetSize())
  29.558             init_ind = GetSize();
  29.559         else
  29.560             ++init_ind;
  29.561 
  29.562         for (UPInt i = init_ind; i > 0; --i)
  29.563             if (pStr[i - 1] == c)
  29.564                 return static_cast<SPInt>(i - 1);
  29.565 
  29.566         return -1; 
  29.567     }
  29.568 
  29.569     // Create new object and trim size bytes from the left.
  29.570     StringDataPtr  GetTrimLeft(UPInt size) const
  29.571     {
  29.572         // Limit trim size to the size of the string.
  29.573         size = Alg::PMin(GetSize(), size);
  29.574 
  29.575         return StringDataPtr(ToCStr() + size, GetSize() - size);
  29.576     }
  29.577     // Create new object and trim size bytes from the right.
  29.578     StringDataPtr  GetTrimRight(UPInt size) const
  29.579     {
  29.580         // Limit trim to the size of the string.
  29.581         size = Alg::PMin(GetSize(), size);
  29.582 
  29.583         return StringDataPtr(ToCStr(), GetSize() - size);
  29.584     }
  29.585 
  29.586     // Create new object, which contains next token.
  29.587     // Useful for parsing.
  29.588     StringDataPtr GetNextToken(char separator = ':') const
  29.589     {
  29.590         UPInt cur_pos = 0;
  29.591         const char* cur_str = ToCStr();
  29.592 
  29.593         for (; cur_pos < GetSize() && cur_str[cur_pos]; ++cur_pos)
  29.594         {
  29.595             if (cur_str[cur_pos] == separator)
  29.596             {
  29.597                 break;
  29.598             }
  29.599         }
  29.600 
  29.601         return StringDataPtr(ToCStr(), cur_pos);
  29.602     }
  29.603 
  29.604     // Trim size bytes from the left.
  29.605     StringDataPtr& TrimLeft(UPInt size)
  29.606     {
  29.607         // Limit trim size to the size of the string.
  29.608         size = Alg::PMin(GetSize(), size);
  29.609         pStr += size;
  29.610         Size -= size;
  29.611 
  29.612         return *this;
  29.613     }
  29.614     // Trim size bytes from the right.
  29.615     StringDataPtr& TrimRight(UPInt size)
  29.616     {
  29.617         // Limit trim to the size of the string.
  29.618         size = Alg::PMin(GetSize(), size);
  29.619         Size -= size;
  29.620 
  29.621         return *this;
  29.622     }
  29.623 
  29.624     const char* Begin() const { return ToCStr(); }
  29.625     const char* End() const { return ToCStr() + GetSize(); }
  29.626 
  29.627     // Hash functor used string data pointers
  29.628     struct HashFunctor
  29.629     {    
  29.630         UPInt operator()(const StringDataPtr& data) const
  29.631         {
  29.632             return String::BernsteinHashFunction(data.ToCStr(), data.GetSize());
  29.633         }        
  29.634     };
  29.635 
  29.636     bool operator== (const StringDataPtr& data) const 
  29.637     {
  29.638         return (OVR_strncmp(pStr, data.pStr, data.Size) == 0);
  29.639     }
  29.640 
  29.641 protected:
  29.642     const char* pStr;
  29.643     UPInt       Size;
  29.644 };
  29.645 
  29.646 } // OVR
  29.647 
  29.648 #endif
  29.649 \ No newline at end of file
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/libovr/Src/Kernel/OVR_StringHash.h	Sat Sep 14 16:14:59 2013 +0300
    30.3 @@ -0,0 +1,1 @@
    30.4 +/************************************************************************************
    30.5 
    30.6 PublicHeader:   None
    30.7 Filename    :   OVR_StringHash.h
    30.8 Content     :   String hash table used when optional case-insensitive
    30.9                 lookup is required.
   30.10 Created     :   September 19, 2012
   30.11 Notes       : 
   30.12 
   30.13 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   30.14 
   30.15 Use of this software is subject to the terms of the Oculus license
   30.16 agreement provided at the time of installation or download, or which
   30.17 otherwise accompanies this software in either electronic or hard copy form.
   30.18 
   30.19 ************************************************************************************/
   30.20 
   30.21 #ifndef OVR_StringHash_h
   30.22 #define OVR_StringHash_h
   30.23 
   30.24 #include "OVR_String.h"
   30.25 #include "OVR_Hash.h"
   30.26 
   30.27 namespace OVR {
   30.28 
   30.29 //-----------------------------------------------------------------------------------
   30.30 // *** StringHash
   30.31 
   30.32 // This is a custom string hash table that supports case-insensitive
   30.33 // searches through special functions such as GetCaseInsensitive, etc.
   30.34 // This class is used for Flash labels, exports and other case-insensitive tables.
   30.35 
   30.36 template<class U, class Allocator = ContainerAllocator<U> >
   30.37 class StringHash : public Hash<String, U, String::NoCaseHashFunctor, Allocator>
   30.38 {
   30.39 public:
   30.40     typedef U                                                        ValueType;
   30.41     typedef StringHash<U, Allocator>                                 SelfType;
   30.42     typedef Hash<String, U, String::NoCaseHashFunctor, Allocator>    BaseType;
   30.43 
   30.44 public:    
   30.45 
   30.46     void    operator = (const SelfType& src) { BaseType::operator = (src); }
   30.47 
   30.48     bool    GetCaseInsensitive(const String& key, U* pvalue) const
   30.49     {
   30.50         String::NoCaseKey ikey(key);
   30.51         return BaseType::GetAlt(ikey, pvalue);
   30.52     }
   30.53     // Pointer-returning get variety.
   30.54     const U* GetCaseInsensitive(const String& key) const   
   30.55     {
   30.56         String::NoCaseKey ikey(key);
   30.57         return BaseType::GetAlt(ikey);
   30.58     }
   30.59     U*  GetCaseInsensitive(const String& key)
   30.60     {
   30.61         String::NoCaseKey ikey(key);
   30.62         return BaseType::GetAlt(ikey);
   30.63     }
   30.64 
   30.65     
   30.66     typedef typename BaseType::Iterator base_iterator;
   30.67 
   30.68     base_iterator    FindCaseInsensitive(const String& key)
   30.69     {
   30.70         String::NoCaseKey ikey(key);
   30.71         return BaseType::FindAlt(ikey);
   30.72     }
   30.73 
   30.74     // Set just uses a find and assigns value if found. The key is not modified;
   30.75     // this behavior is identical to Flash string variable assignment.    
   30.76     void    SetCaseInsensitive(const String& key, const U& value)
   30.77     {
   30.78         base_iterator it = FindCaseInsensitive(key);
   30.79         if (it != BaseType::End())
   30.80         {
   30.81             it->Second = value;
   30.82         }
   30.83         else
   30.84         {
   30.85             BaseType::Add(key, value);
   30.86         }
   30.87     } 
   30.88 };
   30.89 
   30.90 } // OVR 
   30.91 
   30.92 #endif
   30.93 \ No newline at end of file
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/libovr/Src/Kernel/OVR_String_FormatUtil.cpp	Sat Sep 14 16:14:59 2013 +0300
    31.3 @@ -0,0 +1,1 @@
    31.4 +/************************************************************************************
    31.5 
    31.6 Filename    :   OVR_String_FormatUtil.cpp
    31.7 Content     :   String format functions.
    31.8 Created     :   February 27, 2013
    31.9 Notes       : 
   31.10 
   31.11 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   31.12 
   31.13 Use of this software is subject to the terms of the Oculus license
   31.14 agreement provided at the time of installation or download, or which
   31.15 otherwise accompanies this software in either electronic or hard copy form.
   31.16 
   31.17 ************************************************************************************/
   31.18 
   31.19 #include "OVR_String.h"
   31.20 #include "OVR_Log.h"
   31.21 
   31.22 namespace OVR {
   31.23 
   31.24 void StringBuffer::AppendFormat(const char* format, ...)
   31.25 {       
   31.26     va_list argList;
   31.27 
   31.28     va_start(argList, format);
   31.29     UPInt size = OVR_vscprintf(format, argList);
   31.30     va_end(argList);
   31.31 
   31.32     char* buffer = (char*) OVR_ALLOC(sizeof(char) * (size+1));
   31.33 
   31.34     va_start(argList, format);
   31.35     UPInt result = OVR_vsprintf(buffer, size+1, format, argList);
   31.36     OVR_UNUSED1(result);
   31.37     va_end(argList);
   31.38     OVR_ASSERT_LOG(result == size, ("Error in OVR_vsprintf"));
   31.39 
   31.40     AppendString(buffer);
   31.41 
   31.42     OVR_FREE(buffer);
   31.43 }
   31.44 
   31.45 } // OVR
   31.46 \ No newline at end of file
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/libovr/Src/Kernel/OVR_String_PathUtil.cpp	Sat Sep 14 16:14:59 2013 +0300
    32.3 @@ -0,0 +1,1 @@
    32.4 +/************************************************************************************
    32.5 
    32.6 Filename    :   OVR_String_PathUtil.cpp
    32.7 Content     :   String filename/url helper function
    32.8 Created     :   September 19, 2012
    32.9 Notes       : 
   32.10 
   32.11 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   32.12 
   32.13 Use of this software is subject to the terms of the Oculus license
   32.14 agreement provided at the time of installation or download, or which
   32.15 otherwise accompanies this software in either electronic or hard copy form.
   32.16 
   32.17 ************************************************************************************/
   32.18 
   32.19 #include "OVR_String.h"
   32.20 #include "OVR_UTF8Util.h"
   32.21 
   32.22 namespace OVR {
   32.23 
   32.24 //--------------------------------------------------------------------
   32.25 // ***** Path-Scanner helper function 
   32.26 
   32.27 // Scans file path finding filename start and extension start, fills in their addess.
   32.28 void ScanFilePath(const char* url, const char** pfilename, const char** pext)
   32.29 { 
   32.30     const char* urlStart = url;
   32.31     const char *filename = 0;
   32.32     const char *lastDot = 0;
   32.33 
   32.34     UInt32 charVal = UTF8Util::DecodeNextChar(&url);
   32.35 
   32.36     while (charVal != 0)
   32.37     {
   32.38         if ((charVal == '/') || (charVal == '\\'))
   32.39         {
   32.40             filename = url;
   32.41             lastDot  = 0;
   32.42         }
   32.43         else if (charVal == '.')
   32.44         {
   32.45             lastDot = url - 1;
   32.46         }
   32.47         
   32.48         charVal = UTF8Util::DecodeNextChar(&url);
   32.49     }
   32.50 
   32.51     if (pfilename)
   32.52     {
   32.53         // It was a naked filename
   32.54         if (urlStart && (*urlStart != '.') && *urlStart)
   32.55             *pfilename = urlStart;
   32.56         else
   32.57             *pfilename = filename;
   32.58     }
   32.59 
   32.60     if (pext)
   32.61     {
   32.62         *pext = lastDot;
   32.63     }
   32.64 }
   32.65 
   32.66 // Scans till the end of protocol. Returns first character past protocol,
   32.67 // 0 if not found.
   32.68 //  - protocol: 'file://', 'http://'
   32.69 const char* ScanPathProtocol(const char* url)
   32.70 {    
   32.71     UInt32 charVal = UTF8Util::DecodeNextChar(&url);
   32.72     UInt32 charVal2;
   32.73    
   32.74     while (charVal != 0)
   32.75     {
   32.76         // Treat a colon followed by a slash as absolute.
   32.77         if (charVal == ':')
   32.78         {
   32.79             charVal2 = UTF8Util::DecodeNextChar(&url);
   32.80             charVal  = UTF8Util::DecodeNextChar(&url);
   32.81             if ((charVal == '/') && (charVal2 == '\\'))
   32.82                 return url;
   32.83         }
   32.84         charVal = UTF8Util::DecodeNextChar(&url);
   32.85     }
   32.86     return 0;
   32.87 }
   32.88 
   32.89 
   32.90 //--------------------------------------------------------------------
   32.91 // ***** String Path API implementation
   32.92 
   32.93 bool String::HasAbsolutePath(const char* url)
   32.94 {
   32.95     // Absolute paths can star with:
   32.96     //  - protocols:        'file://', 'http://'
   32.97     //  - windows drive:    'c:\'
   32.98     //  - UNC share name:   '\\share'
   32.99     //  - unix root         '/'
  32.100 
  32.101     // On the other hand, relative paths are:
  32.102     //  - directory:        'directory/file'
  32.103     //  - this directory:   './file'
  32.104     //  - parent directory: '../file'
  32.105     // 
  32.106     // For now, we don't parse '.' or '..' out, but instead let it be concatenated
  32.107     // to string and let the OS figure it out. This, however, is not good for file
  32.108     // name matching in library/etc, so it should be improved.
  32.109 
  32.110     if (!url || !*url)
  32.111         return true; // Treat empty strings as absolute.    
  32.112 
  32.113     UInt32 charVal = UTF8Util::DecodeNextChar(&url);
  32.114 
  32.115     // Fist character of '/' or '\\' means absolute url.
  32.116     if ((charVal == '/') || (charVal == '\\'))
  32.117         return true;
  32.118 
  32.119     while (charVal != 0)
  32.120     {
  32.121         // Treat a colon followed by a slash as absolute.
  32.122         if (charVal == ':')
  32.123         {
  32.124             charVal = UTF8Util::DecodeNextChar(&url);
  32.125             // Protocol or windows drive. Absolute.
  32.126             if ((charVal == '/') || (charVal == '\\'))
  32.127                 return true;
  32.128         }
  32.129         else if ((charVal == '/') || (charVal == '\\'))
  32.130         {
  32.131             // Not a first character (else 'if' above the loop would have caught it).
  32.132             // Must be a relative url.
  32.133             break;
  32.134         }
  32.135 
  32.136         charVal = UTF8Util::DecodeNextChar(&url);
  32.137     }
  32.138 
  32.139     // We get here for relative paths.
  32.140     return false;    
  32.141 }
  32.142 
  32.143 
  32.144 bool String::HasExtension(const char* path)
  32.145 {
  32.146     const char* ext = 0;
  32.147     ScanFilePath(path, 0, &ext);
  32.148     return ext != 0;
  32.149 }
  32.150 bool String::HasProtocol(const char* path)
  32.151 {
  32.152     return ScanPathProtocol(path) != 0;
  32.153 }
  32.154 
  32.155 
  32.156 String  String::GetPath() const
  32.157 {
  32.158     const char* filename = 0;
  32.159     ScanFilePath(ToCStr(), &filename, 0);
  32.160 
  32.161     // Technically we can have extra logic somewhere for paths,
  32.162     // such as enforcing protocol and '/' only based on flags,
  32.163     // but we keep it simple for now.
  32.164     return String(ToCStr(), filename ? (filename-ToCStr()) : GetSize());
  32.165 }
  32.166 
  32.167 String  String::GetProtocol() const
  32.168 {
  32.169     const char* protocolEnd = ScanPathProtocol(ToCStr());
  32.170     return String(ToCStr(), protocolEnd ? (protocolEnd-ToCStr()) : 0);
  32.171 }
  32.172 
  32.173 String  String::GetFilename() const
  32.174 {
  32.175     const char* filename = 0;
  32.176     ScanFilePath(ToCStr(), &filename, 0);
  32.177     return String(filename);
  32.178 }
  32.179 String  String::GetExtension() const
  32.180 {
  32.181     const char* ext = 0;
  32.182     ScanFilePath(ToCStr(), 0, &ext);
  32.183     return String(ext);
  32.184 }
  32.185 
  32.186 void    String::StripExtension()
  32.187 {
  32.188     const char* ext = 0;
  32.189     ScanFilePath(ToCStr(), 0, &ext);    
  32.190     if (ext)
  32.191     {
  32.192         *this = String(ToCStr(), ext-ToCStr());
  32.193     }
  32.194 }
  32.195 
  32.196 void    String::StripProtocol()
  32.197 {
  32.198     const char* protocol = ScanPathProtocol(ToCStr());
  32.199     if (protocol)
  32.200         AssignString(protocol, OVR_strlen(protocol));
  32.201 }
  32.202 
  32.203 } // OVR
  32.204 \ No newline at end of file
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/libovr/Src/Kernel/OVR_SysFile.cpp	Sat Sep 14 16:14:59 2013 +0300
    33.3 @@ -0,0 +1,1 @@
    33.4 +/**************************************************************************
    33.5 
    33.6 Filename    :   OVR_SysFile.cpp
    33.7 Content     :   File wrapper class implementation (Win32)
    33.8 
    33.9 Created     :   April 5, 1999
   33.10 Authors     :   Michael Antonov
   33.11 
   33.12 Copyright   :   Copyright 2011 Oculus VR, Inc. All Rights reserved.
   33.13 
   33.14 Use of this software is subject to the terms of the Oculus license
   33.15 agreement provided at the time of installation or download, or which
   33.16 otherwise accompanies this software in either electronic or hard copy form.
   33.17 
   33.18 **************************************************************************/
   33.19 
   33.20 #define  GFILE_CXX
   33.21 
   33.22 // Standard C library (Captain Obvious guarantees!)
   33.23 #include <stdio.h>
   33.24 
   33.25 #include "OVR_SysFile.h"
   33.26 
   33.27 namespace OVR {
   33.28 
   33.29 // This is - a dummy file that fails on all calls.
   33.30 
   33.31 class UnopenedFile : public File
   33.32 {
   33.33 public:
   33.34     UnopenedFile()  { }
   33.35     ~UnopenedFile() { }
   33.36 
   33.37     virtual const char* GetFilePath()               { return 0; }
   33.38 
   33.39     // ** File Information
   33.40     virtual bool        IsValid()                   { return 0; }
   33.41     virtual bool        IsWritable()                { return 0; }
   33.42 
   33.43     // Return position / file size
   33.44     virtual int         Tell()                      { return 0; }
   33.45     virtual SInt64      LTell()                     { return 0; }
   33.46     virtual int         GetLength()                 { return 0; }
   33.47     virtual SInt64      LGetLength()                { return 0; }
   33.48 
   33.49 //  virtual bool        Stat(FileStats *pfs)        { return 0; }
   33.50     virtual int         GetErrorCode()              { return Error_FileNotFound; }
   33.51 
   33.52     // ** Stream implementation & I/O
   33.53     virtual int         Write(const UByte *pbuffer, int numBytes)     { return -1; OVR_UNUSED2(pbuffer, numBytes); }
   33.54     virtual int         Read(UByte *pbuffer, int numBytes)            { return -1; OVR_UNUSED2(pbuffer, numBytes); }
   33.55     virtual int         SkipBytes(int numBytes)                       { return 0;  OVR_UNUSED(numBytes); }
   33.56     virtual int         BytesAvailable()                              { return 0; }
   33.57     virtual bool        Flush()                                       { return 0; }
   33.58     virtual int         Seek(int offset, int origin)                  { return -1; OVR_UNUSED2(offset, origin); }
   33.59     virtual SInt64      LSeek(SInt64 offset, int origin)              { return -1; OVR_UNUSED2(offset, origin); }
   33.60     
   33.61     virtual int         CopyFromStream(File *pstream, int byteSize)   { return -1; OVR_UNUSED2(pstream, byteSize); }
   33.62     virtual bool        Close()                                       { return 0; }    
   33.63 };
   33.64 
   33.65 
   33.66 
   33.67 // ***** System File
   33.68 
   33.69 // System file is created to access objects on file system directly
   33.70 // This file can refer directly to path
   33.71 
   33.72 // ** Constructor
   33.73 SysFile::SysFile() : DelegatedFile(0)
   33.74 {
   33.75     pFile = *new UnopenedFile;
   33.76 }
   33.77 
   33.78 File* FileFILEOpen(const String& path, int flags, int mode);
   33.79 
   33.80 // Opens a file
   33.81 SysFile::SysFile(const String& path, int flags, int mode) : DelegatedFile(0)
   33.82 {
   33.83     Open(path, flags, mode);
   33.84 }
   33.85 
   33.86 
   33.87 // ** Open & management
   33.88 // Will fail if file's already open
   33.89 bool SysFile::Open(const String& path, int flags, int mode)
   33.90 {
   33.91     pFile = *FileFILEOpen(path, flags, mode);
   33.92     if ((!pFile) || (!pFile->IsValid()))
   33.93     {
   33.94         pFile = *new UnopenedFile;
   33.95         return 0;
   33.96     }
   33.97     //pFile = *OVR_NEW DelegatedFile(pFile); // MA Testing
   33.98     if (flags & Open_Buffered)
   33.99         pFile = *new BufferedFile(pFile);
  33.100     return 1;
  33.101 }
  33.102 
  33.103 
  33.104 // ** Overrides
  33.105 
  33.106 int SysFile::GetErrorCode()
  33.107 {
  33.108     return pFile ? pFile->GetErrorCode() : Error_FileNotFound;
  33.109 }
  33.110 
  33.111 
  33.112 // Overrides to provide re-open support
  33.113 bool SysFile::IsValid()
  33.114 {
  33.115     return pFile && pFile->IsValid();
  33.116 }
  33.117 bool SysFile::Close()
  33.118 {
  33.119     if (IsValid())
  33.120     {
  33.121         DelegatedFile::Close();
  33.122         pFile = *new UnopenedFile;
  33.123         return 1;
  33.124     }
  33.125     return 0;
  33.126 }
  33.127 
  33.128 } // OVR
  33.129 \ No newline at end of file
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/libovr/Src/Kernel/OVR_SysFile.h	Sat Sep 14 16:14:59 2013 +0300
    34.3 @@ -0,0 +1,1 @@
    34.4 +/************************************************************************************
    34.5 
    34.6 PublicHeader:   Kernel
    34.7 Filename    :   OVR_SysFile.h
    34.8 Content     :   Header for all internal file management - functions and structures
    34.9                 to be inherited by OS specific subclasses.
   34.10 Created     :   September 19, 2012
   34.11 Notes       : 
   34.12 
   34.13 Notes       :   errno may not be preserved across use of GBaseFile member functions
   34.14             :   Directories cannot be deleted while files opened from them are in use
   34.15                 (For the GetFullName function)
   34.16 
   34.17 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   34.18 
   34.19 Use of this software is subject to the terms of the Oculus license
   34.20 agreement provided at the time of installation or download, or which
   34.21 otherwise accompanies this software in either electronic or hard copy form.
   34.22 
   34.23 ************************************************************************************/
   34.24 
   34.25 #ifndef OVR_SysFile_h
   34.26 #define OVR_SysFile_h
   34.27 
   34.28 #include "OVR_File.h"
   34.29 
   34.30 namespace OVR {
   34.31 
   34.32 // ***** Declared classes
   34.33 class   SysFile;
   34.34 
   34.35 //-----------------------------------------------------------------------------------
   34.36 // *** File Statistics
   34.37 
   34.38 // This class contents are similar to _stat, providing
   34.39 // creation, modify and other information about the file.
   34.40 struct FileStat
   34.41 {
   34.42     // No change or create time because they are not available on most systems
   34.43     SInt64  ModifyTime;
   34.44     SInt64  AccessTime;
   34.45     SInt64  FileSize;
   34.46 
   34.47     bool operator== (const FileStat& stat) const
   34.48     {
   34.49         return ( (ModifyTime == stat.ModifyTime) &&
   34.50                  (AccessTime == stat.AccessTime) &&
   34.51                  (FileSize == stat.FileSize) );
   34.52     }
   34.53 };
   34.54 
   34.55 //-----------------------------------------------------------------------------------
   34.56 // *** System File
   34.57 
   34.58 // System file is created to access objects on file system directly
   34.59 // This file can refer directly to path.
   34.60 // System file can be open & closed several times; however, such use is not recommended
   34.61 // This class is realy a wrapper around an implementation of File interface for a 
   34.62 // particular platform.
   34.63 
   34.64 class SysFile : public DelegatedFile
   34.65 {
   34.66 protected:
   34.67   SysFile(const SysFile &source) : DelegatedFile () { OVR_UNUSED(source); }
   34.68 public:
   34.69 
   34.70     // ** Constructor
   34.71     SysFile();
   34.72     // Opens a file
   34.73     SysFile(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite); 
   34.74 
   34.75     // ** Open & management 
   34.76     bool  Open(const String& path, int flags = Open_Read|Open_Buffered, int mode = Mode_ReadWrite);
   34.77         
   34.78     OVR_FORCE_INLINE bool  Create(const String& path, int mode = Mode_ReadWrite)
   34.79     { return Open(path, Open_ReadWrite|Open_Create, mode); }
   34.80 
   34.81     // Helper function: obtain file statistics information. In GFx, this is used to detect file changes.
   34.82     // Return 0 if function failed, most likely because the file doesn't exist.
   34.83     static bool OVR_CDECL GetFileStat(FileStat* pfileStats, const String& path);
   34.84     
   34.85     // ** Overrides
   34.86     // Overridden to provide re-open support
   34.87     virtual int   GetErrorCode();
   34.88 
   34.89     virtual bool  IsValid();
   34.90 
   34.91     virtual bool  Close();    
   34.92 };
   34.93 
   34.94 } // Scaleform
   34.95 
   34.96 #endif
   34.97 \ No newline at end of file
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/libovr/Src/Kernel/OVR_System.cpp	Sat Sep 14 16:14:59 2013 +0300
    35.3 @@ -0,0 +1,1 @@
    35.4 +/************************************************************************************
    35.5 
    35.6 Filename    :   OVR_System.cpp
    35.7 Content     :   General kernel initialization/cleanup, including that
    35.8                 of the memory allocator.
    35.9 Created     :   September 19, 2012
   35.10 Notes       : 
   35.11 
   35.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   35.13 
   35.14 Use of this software is subject to the terms of the Oculus license
   35.15 agreement provided at the time of installation or download, or which
   35.16 otherwise accompanies this software in either electronic or hard copy form.
   35.17 
   35.18 ************************************************************************************/
   35.19 
   35.20 #include "OVR_System.h"
   35.21 #include "OVR_Threads.h"
   35.22 #include "OVR_Timer.h"
   35.23 
   35.24 namespace OVR {
   35.25 
   35.26 // *****  OVR::System Implementation
   35.27 
   35.28 // Initializes System core, installing allocator.
   35.29 void System::Init(Log* log, Allocator *palloc)
   35.30 {    
   35.31     if (!Allocator::GetInstance())
   35.32     {
   35.33         Log::SetGlobalLog(log);
   35.34         Timer::initializeTimerSystem();
   35.35         Allocator::setInstance(palloc);
   35.36     }
   35.37     else
   35.38     {
   35.39         OVR_DEBUG_LOG(("System::Init failed - duplicate call."));
   35.40     }
   35.41 }
   35.42 
   35.43 void System::Destroy()
   35.44 {    
   35.45     if (Allocator::GetInstance())
   35.46     {
   35.47         // Wait for all threads to finish; this must be done so that memory
   35.48         // allocator and all destructors finalize correctly.
   35.49 #ifdef OVR_ENABLE_THREADS
   35.50         Thread::FinishAllThreads();
   35.51 #endif
   35.52 
   35.53         // Shutdown heap and destroy SysAlloc singleton, if any.
   35.54         Allocator::GetInstance()->onSystemShutdown();
   35.55         Allocator::setInstance(0);
   35.56 
   35.57         Timer::shutdownTimerSystem();
   35.58         Log::SetGlobalLog(Log::GetDefaultLog());
   35.59     }
   35.60     else
   35.61     {
   35.62         OVR_DEBUG_LOG(("System::Destroy failed - System not initialized."));
   35.63     }
   35.64 }
   35.65 
   35.66 // Returns 'true' if system was properly initialized.
   35.67 bool System::IsInitialized()
   35.68 {
   35.69     return Allocator::GetInstance() != 0;
   35.70 }
   35.71 
   35.72 } // OVR
   35.73 
   35.74 \ No newline at end of file
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/libovr/Src/Kernel/OVR_System.h	Sat Sep 14 16:14:59 2013 +0300
    36.3 @@ -0,0 +1,1 @@
    36.4 +/************************************************************************************
    36.5 
    36.6 PublicHeader:   OVR
    36.7 Filename    :   OVR_System.h
    36.8 Content     :   General kernel initialization/cleanup, including that
    36.9                 of the memory allocator.
   36.10 Created     :   September 19, 2012
   36.11 Notes       : 
   36.12 
   36.13 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   36.14 
   36.15 Use of this software is subject to the terms of the Oculus license
   36.16 agreement provided at the time of installation or download, or which
   36.17 otherwise accompanies this software in either electronic or hard copy form.
   36.18 
   36.19 ************************************************************************************/
   36.20 
   36.21 #ifndef OVR_System_h
   36.22 #define OVR_System_h
   36.23 
   36.24 #include "OVR_Allocator.h"
   36.25 #include "OVR_Log.h"
   36.26 
   36.27 namespace OVR {
   36.28 
   36.29 // ***** System Core Initialization class
   36.30 
   36.31 // System initialization must take place before any other OVR_Kernel objects are used;
   36.32 // this is done my calling System::Init(). Among other things, this is necessary to
   36.33 // initialize the memory allocator. Similarly, System::Destroy must be
   36.34 // called before program exist for proper cleanup. Both of these tasks can be achieved by
   36.35 // simply creating System object first, allowing its constructor/destructor do the work.
   36.36 
   36.37 // TBD: Require additional System class for Oculus Rift API?
   36.38 
   36.39 class System
   36.40 {
   36.41 public:
   36.42 
   36.43     // System constructor expects allocator to be specified, if it is being substituted.
   36.44     System(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
   36.45            Allocator* palloc = DefaultAllocator::InitSystemSingleton())
   36.46     {
   36.47         Init(log, palloc);
   36.48     }
   36.49 
   36.50     ~System()
   36.51     {
   36.52         Destroy();
   36.53     }
   36.54 
   36.55     // Returns 'true' if system was properly initialized.
   36.56     static bool OVR_CDECL IsInitialized();
   36.57 
   36.58     // Initializes System core.  Users can override memory implementation by passing
   36.59     // a different Allocator here.
   36.60     static void OVR_CDECL Init(Log* log = Log::ConfigureDefaultLog(LogMask_Debug),
   36.61                                Allocator *palloc = DefaultAllocator::InitSystemSingleton());
   36.62 
   36.63     // De-initializes System more, finalizing the threading system and destroying
   36.64     // the global memory allocator.
   36.65     static void OVR_CDECL Destroy();    
   36.66 };
   36.67 
   36.68 } // OVR
   36.69 
   36.70 #endif
   36.71 \ No newline at end of file
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/libovr/Src/Kernel/OVR_Threads.h	Sat Sep 14 16:14:59 2013 +0300
    37.3 @@ -0,0 +1,1 @@
    37.4 +/************************************************************************************
    37.5 
    37.6 PublicHeader:   None
    37.7 Filename    :   OVR_Threads.h
    37.8 Content     :   Contains thread-related (safe) functionality
    37.9 Created     :   September 19, 2012
   37.10 Notes       : 
   37.11 
   37.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   37.13 
   37.14 Use of this software is subject to the terms of the Oculus license
   37.15 agreement provided at the time of installation or download, or which
   37.16 otherwise accompanies this software in either electronic or hard copy form.
   37.17 
   37.18 ************************************************************************************/
   37.19 #ifndef OVR_Threads_h
   37.20 #define OVR_Threads_h
   37.21 
   37.22 #include "OVR_Types.h"
   37.23 #include "OVR_Atomic.h"
   37.24 #include "OVR_RefCount.h"
   37.25 #include "OVR_Array.h"
   37.26 
   37.27 // Defines the infinite wait delay timeout
   37.28 #define OVR_WAIT_INFINITE 0xFFFFFFFF
   37.29 
   37.30 // To be defined in the project configuration options
   37.31 #ifdef OVR_ENABLE_THREADS
   37.32 
   37.33 
   37.34 namespace OVR {
   37.35 
   37.36 //-----------------------------------------------------------------------------------
   37.37 // ****** Declared classes
   37.38 
   37.39 // Declared with thread support only
   37.40 class   Mutex;
   37.41 class   WaitCondition;
   37.42 class   Event;
   37.43 // Implementation forward declarations
   37.44 class MutexImpl;
   37.45 class WaitConditionImpl;
   37.46 
   37.47 
   37.48 
   37.49 //-----------------------------------------------------------------------------------
   37.50 // ***** Mutex
   37.51 
   37.52 // Mutex class represents a system Mutex synchronization object that provides access 
   37.53 // serialization between different threads, allowing one thread mutually exclusive access 
   37.54 // to a resource. Mutex is more heavy-weight then Lock, but supports WaitCondition.
   37.55 
   37.56 class Mutex
   37.57 {
   37.58     friend class WaitConditionImpl;    
   37.59     friend class MutexImpl;
   37.60 
   37.61     MutexImpl  *pImpl; 
   37.62 
   37.63 public:
   37.64     // Constructor/destructor
   37.65     Mutex(bool recursive = 1);
   37.66     ~Mutex();
   37.67 
   37.68     // Locking functions
   37.69     void  DoLock();
   37.70     bool  TryLock();
   37.71     void  Unlock();
   37.72 
   37.73     // Returns 1 if the mutes is currently locked by another thread
   37.74     // Returns 0 if the mutex is not locked by another thread, and can therefore be acquired. 
   37.75     bool  IsLockedByAnotherThread();
   37.76     
   37.77     // Locker class; Used for automatic locking of a mutex withing scope    
   37.78     class Locker
   37.79     {
   37.80     public:
   37.81         Mutex *pMutex;
   37.82         Locker(Mutex *pmutex)
   37.83             { pMutex = pmutex; pMutex->DoLock(); }
   37.84         ~Locker()
   37.85             { pMutex->Unlock(); }
   37.86     };
   37.87 };
   37.88 
   37.89 
   37.90 //-----------------------------------------------------------------------------------
   37.91 // ***** WaitCondition
   37.92 
   37.93 /*
   37.94     WaitCondition is a synchronization primitive that can be used to implement what is known as a monitor.
   37.95     Dependent threads wait on a wait condition by calling Wait(), and get woken up by other threads that
   37.96     call Notify() or NotifyAll().
   37.97 
   37.98     The unique feature of this class is that it provides an atomic way of first releasing a Mutex, and then 
   37.99     starting a wait on a wait condition. If both the mutex and the wait condition are associated with the same
  37.100     resource, this ensures that any condition checked for while the mutex was locked does not change before
  37.101     the wait on the condition is actually initiated.
  37.102 */
  37.103 
  37.104 class WaitCondition
  37.105 {
  37.106     friend class WaitConditionImpl;
  37.107     // Internal implementation structure
  37.108     WaitConditionImpl *pImpl;
  37.109 
  37.110 public:
  37.111     // Constructor/destructor
  37.112     WaitCondition();
  37.113     ~WaitCondition();
  37.114 
  37.115     // Release mutex and wait for condition. The mutex is re-aquired after the wait.
  37.116     // Delay is specified in milliseconds (1/1000 of a second).
  37.117     bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
  37.118 
  37.119     // Notify a condition, releasing at one object waiting
  37.120     void    Notify();
  37.121     // Notify a condition, releasing all objects waiting
  37.122     void    NotifyAll();
  37.123 };
  37.124 
  37.125 
  37.126 //-----------------------------------------------------------------------------------
  37.127 // ***** Event
  37.128 
  37.129 // Event is a wait-able synchronization object similar to Windows event.
  37.130 // Event can be waited on until it's signaled by another thread calling
  37.131 // either SetEvent or PulseEvent.
  37.132 
  37.133 class Event
  37.134 {
  37.135     // Event state, its mutex and the wait condition
  37.136     volatile bool   State;
  37.137     volatile bool   Temporary;  
  37.138     mutable Mutex   StateMutex;
  37.139     WaitCondition   StateWaitCondition;
  37.140 
  37.141     void updateState(bool newState, bool newTemp, bool mustNotify);
  37.142 
  37.143 public:    
  37.144     Event(bool setInitially = 0) : State(setInitially), Temporary(false) { }
  37.145     ~Event() { }
  37.146 
  37.147     // Wait on an event condition until it is set
  37.148     // Delay is specified in milliseconds (1/1000 of a second).
  37.149     bool  Wait(unsigned delay = OVR_WAIT_INFINITE);
  37.150     
  37.151     // Set an event, releasing objects waiting on it
  37.152     void  SetEvent()
  37.153     { updateState(true, false, true); }
  37.154 
  37.155     // Reset an event, un-signaling it
  37.156     void  ResetEvent()
  37.157     { updateState(false, false, false); }
  37.158 
  37.159     // Set and then reset an event once a waiter is released.
  37.160     // If threads are already waiting, they will be notified and released
  37.161     // If threads are not waiting, the event is set until the first thread comes in
  37.162     void  PulseEvent()
  37.163     { updateState(true, true, true); }
  37.164 };
  37.165 
  37.166 
  37.167 //-----------------------------------------------------------------------------------
  37.168 // ***** Thread class
  37.169 
  37.170 // ThreadId uniquely identifies a thread; returned by GetCurrentThreadId() and
  37.171 // Thread::GetThreadId.
  37.172 typedef void* ThreadId;
  37.173 
  37.174 
  37.175 // *** Thread flags
  37.176 
  37.177 // Indicates that the thread is has been started, i.e. Start method has been called, and threads
  37.178 // OnExit() method has not yet been called/returned.
  37.179 #define OVR_THREAD_STARTED               0x01
  37.180 // This flag is set once the thread has ran, and finished.
  37.181 #define OVR_THREAD_FINISHED              0x02
  37.182 // This flag is set temporarily if this thread was started suspended. It is used internally.
  37.183 #define OVR_THREAD_START_SUSPENDED       0x08
  37.184 // This flag is used to ask a thread to exit. Message driven threads will usually check this flag
  37.185 // and finish once it is set.
  37.186 #define OVR_THREAD_EXIT                  0x10
  37.187 
  37.188 
  37.189 class Thread : public RefCountBase<Thread>
  37.190 { // NOTE: Waitable must be the first base since it implements RefCountImpl.    
  37.191 
  37.192 public:
  37.193 
  37.194     // *** Callback functions, can be used instead of overriding Run
  37.195 
  37.196     // Run function prototypes.    
  37.197     // Thread function and user handle passed to it, executed by the default
  37.198     // Thread::Run implementation if not null.
  37.199     typedef int (*ThreadFn)(Thread *pthread, void* h);
  37.200     
  37.201     // Thread ThreadFunction1 is executed if not 0, otherwise ThreadFunction2 is tried
  37.202     ThreadFn    ThreadFunction;    
  37.203     // User handle passes to a thread
  37.204     void*       UserHandle;
  37.205 
  37.206     // Thread state to start a thread with
  37.207     enum ThreadState
  37.208     {
  37.209         NotRunning  = 0,
  37.210         Running     = 1,
  37.211         Suspended   = 2
  37.212     };
  37.213 
  37.214     // Thread priority
  37.215     enum ThreadPriority
  37.216     {
  37.217         CriticalPriority,
  37.218         HighestPriority,
  37.219         AboveNormalPriority,
  37.220         NormalPriority,
  37.221         BelowNormalPriority,
  37.222         LowestPriority,
  37.223         IdlePriority,
  37.224     };
  37.225 
  37.226     // Thread constructor parameters
  37.227     struct CreateParams
  37.228     {
  37.229         CreateParams(ThreadFn func = 0, void* hand = 0, UPInt ssize = 128 * 1024, 
  37.230                      int proc = -1, ThreadState state = NotRunning, ThreadPriority prior = NormalPriority)
  37.231                      : threadFunction(func), userHandle(hand), stackSize(ssize), 
  37.232                        processor(proc), initialState(state), priority(prior) {}
  37.233         ThreadFn       threadFunction;   // Thread function
  37.234         void*          userHandle;       // User handle passes to a thread
  37.235         UPInt          stackSize;        // Thread stack size
  37.236         int            processor;        // Thread hardware processor
  37.237         ThreadState    initialState;     // 
  37.238         ThreadPriority priority;         // Thread priority
  37.239     };
  37.240 
  37.241     // *** Constructors
  37.242 
  37.243     // A default constructor always creates a thread in NotRunning state, because
  37.244     // the derived class has not yet been initialized. The derived class can call Start explicitly.
  37.245     // "processor" parameter specifies which hardware processor this thread will be run on. 
  37.246     // -1 means OS decides this. Implemented only on Win32
  37.247     Thread(UPInt stackSize = 128 * 1024, int processor = -1);
  37.248     // Constructors that initialize the thread with a pointer to function.
  37.249     // An option to start a thread is available, but it should not be used if classes are derived from Thread.
  37.250     // "processor" parameter specifies which hardware processor this thread will be run on. 
  37.251     // -1 means OS decides this. Implemented only on Win32
  37.252     Thread(ThreadFn threadFunction, void*  userHandle = 0, UPInt stackSize = 128 * 1024,
  37.253            int processor = -1, ThreadState initialState = NotRunning);
  37.254     // Constructors that initialize the thread with a create parameters structure.
  37.255     explicit Thread(const CreateParams& params);
  37.256 
  37.257     // Destructor.
  37.258     virtual ~Thread();
  37.259 
  37.260     // Waits for all Threads to finish; should be called only from the root
  37.261     // application thread. Once this function returns, we know that all other
  37.262     // thread's references to Thread object have been released.
  37.263     static  void OVR_CDECL FinishAllThreads();
  37.264 
  37.265 
  37.266     // *** Overridable Run function for thread processing
  37.267 
  37.268     // - returning from this method will end the execution of the thread
  37.269     // - return value is usually 0 for success 
  37.270     virtual int   Run();
  37.271     // Called after return/exit function
  37.272     virtual void  OnExit();
  37.273 
  37.274 
  37.275     // *** Thread management
  37.276 
  37.277     // Starts the thread if its not already running
  37.278     // - internally sets up the threading and calls Run()
  37.279     // - initial state can either be Running or Suspended, NotRunning will just fail and do nothing
  37.280     // - returns the exit code
  37.281     virtual bool  Start(ThreadState initialState = Running);
  37.282 
  37.283     // Quits with an exit code
  37.284     virtual void  Exit(int exitCode=0);
  37.285 
  37.286     // Suspend the thread until resumed
  37.287     // Returns 1 for success, 0 for failure.
  37.288     bool  Suspend();
  37.289     // Resumes currently suspended thread
  37.290     // Returns 1 for success, 0 for failure.
  37.291     bool  Resume();
  37.292 
  37.293     // Static function to return a pointer to the current thread
  37.294     //static Thread* GetThread();
  37.295 
  37.296 
  37.297     // *** Thread status query functions
  37.298 
  37.299     bool          GetExitFlag() const;
  37.300     void          SetExitFlag(bool exitFlag);
  37.301 
  37.302     // Determines whether the thread was running and is now finished
  37.303     bool          IsFinished() const;
  37.304     // Determines if the thread is currently suspended
  37.305     bool          IsSuspended() const;
  37.306     // Returns current thread state
  37.307     ThreadState   GetThreadState() const;
  37.308 
  37.309     // Returns the number of available CPUs on the system 
  37.310     static int    GetCPUCount();
  37.311 
  37.312     // Returns the thread exit code. Exit code is initialized to 0,
  37.313     // and set to the return value if Run function after the thread is finished.
  37.314     inline int    GetExitCode() const { return ExitCode; }
  37.315     // Returns an OS handle 
  37.316 #if defined(OVR_OS_WIN32)
  37.317     void*          GetOSHandle() const { return ThreadHandle; }
  37.318 #else
  37.319     pthread_t      GetOSHandle() const { return ThreadHandle; }
  37.320 #endif
  37.321 
  37.322 #if defined(OVR_OS_WIN32)
  37.323     ThreadId       GetThreadId() const { return IdValue; }
  37.324 #else
  37.325     ThreadId       GetThreadId() const { return (ThreadId)GetOSHandle(); }
  37.326 #endif
  37.327 
  37.328     static int      GetOSPriority(ThreadPriority);
  37.329     // *** Sleep
  37.330 
  37.331     // Sleep secs seconds
  37.332     static bool    Sleep(unsigned secs);
  37.333     // Sleep msecs milliseconds
  37.334     static bool    MSleep(unsigned msecs);
  37.335 
  37.336 
  37.337     // *** Debugging functionality
  37.338 #if defined(OVR_OS_WIN32)
  37.339     virtual void    SetThreadName( const char* name );
  37.340 #else
  37.341     virtual void    SetThreadName( const char* name ) { OVR_UNUSED(name); }
  37.342 #endif
  37.343 
  37.344 private:
  37.345 #if defined(OVR_OS_WIN32)
  37.346     friend unsigned WINAPI Thread_Win32StartFn(void *pthread);
  37.347 
  37.348 #else
  37.349     friend void *Thread_PthreadStartFn(void * phandle);
  37.350 
  37.351     static int            InitAttr;
  37.352     static pthread_attr_t Attr;
  37.353 #endif
  37.354 
  37.355 protected:    
  37.356     // Thread state flags
  37.357     AtomicInt<UInt32>   ThreadFlags;
  37.358     AtomicInt<SInt32>   SuspendCount;
  37.359     UPInt               StackSize;
  37.360 
  37.361     // Hardware processor which this thread is running on.
  37.362     int            Processor;
  37.363     ThreadPriority Priority;
  37.364 
  37.365 #if defined(OVR_OS_WIN32)
  37.366     void*               ThreadHandle;
  37.367     volatile ThreadId   IdValue;
  37.368 
  37.369     // System-specific cleanup function called from destructor
  37.370     void                CleanupSystemThread();
  37.371 
  37.372 #else
  37.373     pthread_t           ThreadHandle;
  37.374 #endif
  37.375 
  37.376     // Exit code of the thread, as returned by Run.
  37.377     int                 ExitCode;
  37.378 
  37.379     // Internal run function.
  37.380     int                 PRun();    
  37.381     // Finishes the thread and releases internal reference to it.
  37.382     void                FinishAndRelease();
  37.383 
  37.384     void                Init(const CreateParams& params);
  37.385 
  37.386     // Protected copy constructor
  37.387     Thread(const Thread &source) { OVR_UNUSED(source); }
  37.388 
  37.389 };
  37.390 
  37.391 // Returns the unique Id of a thread it is called on, intended for
  37.392 // comparison purposes.
  37.393 ThreadId GetCurrentThreadId();
  37.394 
  37.395 
  37.396 } // OVR
  37.397 
  37.398 #endif // OVR_ENABLE_THREADS
  37.399 #endif // OVR_Threads_h
  37.400 \ No newline at end of file
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/libovr/Src/Kernel/OVR_Timer.cpp	Sat Sep 14 16:14:59 2013 +0300
    38.3 @@ -0,0 +1,1 @@
    38.4 +/************************************************************************************
    38.5 
    38.6 Filename    :   OVR_Timer.cpp
    38.7 Content     :   Provides static functions for precise timing
    38.8 Created     :   September 19, 2012
    38.9 Notes       : 
   38.10 
   38.11 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   38.12 
   38.13 Use of this software is subject to the terms of the Oculus license
   38.14 agreement provided at the time of installation or download, or which
   38.15 otherwise accompanies this software in either electronic or hard copy form.
   38.16 
   38.17 ************************************************************************************/
   38.18 
   38.19 #include "OVR_Timer.h"
   38.20 
   38.21 #if defined (OVR_OS_WIN32)
   38.22 #include <windows.h>
   38.23 
   38.24 #else
   38.25 #include <sys/time.h>
   38.26 #endif
   38.27 
   38.28 namespace OVR {
   38.29 
   38.30 //-----------------------------------------------------------------------------------
   38.31 // ***** Timer Class
   38.32 
   38.33 UInt64 Timer::GetProfileTicks()
   38.34 {
   38.35     return (GetRawTicks() * MksPerSecond) / GetRawFrequency();
   38.36 }
   38.37 double Timer::GetProfileSeconds()
   38.38 {
   38.39     static UInt64 StartTime = GetProfileTicks();
   38.40     return TicksToSeconds(GetProfileTicks()-StartTime);
   38.41 }
   38.42 
   38.43 
   38.44 //------------------------------------------------------------------------
   38.45 // *** Win32 Specific Timer
   38.46 
   38.47 #if (defined (OVR_OS_WIN32))
   38.48 
   38.49 CRITICAL_SECTION WinAPI_GetTimeCS;
   38.50 volatile UInt32  WinAPI_OldTime = 0;
   38.51 volatile UInt32  WinAPI_WrapCounter = 0;
   38.52 
   38.53 
   38.54 UInt32 Timer::GetTicksMs()
   38.55 {
   38.56     return timeGetTime();
   38.57 }
   38.58 
   38.59 UInt64 Timer::GetTicks()
   38.60 {
   38.61     DWORD  ticks = timeGetTime();
   38.62     UInt64 result;
   38.63 
   38.64     // On Win32 QueryPerformanceFrequency is unreliable due to SMP and
   38.65     // performance levels, so use this logic to detect wrapping and track
   38.66     // high bits.
   38.67     ::EnterCriticalSection(&WinAPI_GetTimeCS);
   38.68 
   38.69     if (WinAPI_OldTime > ticks)
   38.70         WinAPI_WrapCounter++;
   38.71     WinAPI_OldTime = ticks;
   38.72 
   38.73     result = (UInt64(WinAPI_WrapCounter) << 32) | ticks;
   38.74     ::LeaveCriticalSection(&WinAPI_GetTimeCS);
   38.75 
   38.76     return result * MksPerMs;
   38.77 }
   38.78 
   38.79 UInt64 Timer::GetRawTicks()
   38.80 {
   38.81     LARGE_INTEGER li;
   38.82     QueryPerformanceCounter(&li);
   38.83     return li.QuadPart;
   38.84 }
   38.85 
   38.86 UInt64 Timer::GetRawFrequency()
   38.87 {
   38.88     static UInt64 perfFreq = 0;
   38.89     if (perfFreq == 0)
   38.90     {
   38.91         LARGE_INTEGER freq;
   38.92         QueryPerformanceFrequency(&freq);
   38.93         perfFreq = freq.QuadPart;
   38.94     }
   38.95     return perfFreq;
   38.96 }
   38.97 
   38.98 void Timer::initializeTimerSystem()
   38.99 {
  38.100     timeBeginPeriod(1);
  38.101     InitializeCriticalSection(&WinAPI_GetTimeCS);
  38.102 
  38.103 }
  38.104 void Timer::shutdownTimerSystem()
  38.105 {
  38.106     DeleteCriticalSection(&WinAPI_GetTimeCS);
  38.107     timeEndPeriod(1);
  38.108 }
  38.109 
  38.110 #else   // !OVR_OS_WIN32
  38.111 
  38.112 
  38.113 //------------------------------------------------------------------------
  38.114 // *** Standard OS Timer     
  38.115 
  38.116 UInt32 Timer::GetTicksMs()
  38.117 {
  38.118     return (UInt32)(GetProfileTicks() / 1000);
  38.119 }
  38.120 // The profile ticks implementation is just fine for a normal timer.
  38.121 UInt64 Timer::GetTicks()
  38.122 {
  38.123     return GetProfileTicks();
  38.124 }
  38.125 
  38.126 void Timer::initializeTimerSystem()
  38.127 {
  38.128 }
  38.129 void Timer::shutdownTimerSystem()
  38.130 {
  38.131 }
  38.132 
  38.133 UInt64  Timer::GetRawTicks()
  38.134 {
  38.135     // TODO: prefer rdtsc when available?
  38.136 
  38.137     // Return microseconds.
  38.138     struct timeval tv;
  38.139     UInt64 result;
  38.140 
  38.141     gettimeofday(&tv, 0);
  38.142 
  38.143     result = (UInt64)tv.tv_sec * 1000000;
  38.144     result += tv.tv_usec;
  38.145 
  38.146     return result;
  38.147 }
  38.148 
  38.149 UInt64 Timer::GetRawFrequency()
  38.150 {
  38.151     return MksPerSecond;
  38.152 }
  38.153 
  38.154 #endif  // !OVR_OS_WIN32
  38.155 
  38.156 
  38.157 
  38.158 } // OVR
  38.159 
  38.160 \ No newline at end of file
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/libovr/Src/Kernel/OVR_Timer.h	Sat Sep 14 16:14:59 2013 +0300
    39.3 @@ -0,0 +1,1 @@
    39.4 +/************************************************************************************
    39.5 
    39.6 PublicHeader:   OVR
    39.7 Filename    :   OVR_Timer.h
    39.8 Content     :   Provides static functions for precise timing
    39.9 Created     :   September 19, 2012
   39.10 Notes       : 
   39.11 
   39.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   39.13 
   39.14 Use of this software is subject to the terms of the Oculus license
   39.15 agreement provided at the time of installation or download, or which
   39.16 otherwise accompanies this software in either electronic or hard copy form.
   39.17 
   39.18 ************************************************************************************/
   39.19 
   39.20 #ifndef OVR_Timer_h
   39.21 #define OVR_Timer_h
   39.22 
   39.23 #include "OVR_Types.h"
   39.24 
   39.25 namespace OVR {
   39.26     
   39.27 //-----------------------------------------------------------------------------------
   39.28 // ***** Timer
   39.29 
   39.30 // Timer class defines a family of static functions used for application
   39.31 // timing and profiling.
   39.32 
   39.33 class Timer
   39.34 {
   39.35 public:
   39.36     enum {
   39.37         MsPerSecond     = 1000, // Milliseconds in one second.
   39.38         MksPerMs        = 1000, // Microseconds in one millisecond.
   39.39         MksPerSecond    = MsPerSecond * MksPerMs
   39.40     };
   39.41 
   39.42 
   39.43     // ***** Timing APIs for Application    
   39.44     // These APIs should be used to guide animation and other program functions
   39.45     // that require precision.
   39.46 
   39.47     // Returns ticks in milliseconds, as a 32-bit number. May wrap around every
   39.48     // 49.2 days. Use either time difference of two values of GetTicks to avoid
   39.49     // wrap-around.  GetTicksMs may perform better then GetTicks.
   39.50     static UInt32  OVR_STDCALL GetTicksMs();
   39.51 
   39.52     // GetTicks returns general-purpose high resolution application timer value,
   39.53     // measured in microseconds (mks, or 1/1000000 of a second). The actual precision
   39.54     // is system-specific and may be much lower, such as 1 ms.
   39.55     static UInt64  OVR_STDCALL GetTicks();
   39.56 
   39.57     
   39.58     // ***** Profiling APIs.
   39.59     // These functions should be used for profiling, but may have system specific
   39.60     // artifacts that make them less appropriate for general system use.
   39.61     // On Win32, for example these rely on QueryPerformanceConter  may have
   39.62     // problems with thread-core switching and power modes.
   39.63 
   39.64     // Return a hi-res timer value in mks (1/1000000 of a sec).
   39.65     // Generally you want to call this at the start and end of an
   39.66     // operation, and pass the difference to
   39.67     // TicksToSeconds() to find out how long the operation took. 
   39.68     static UInt64  OVR_STDCALL GetProfileTicks();
   39.69 
   39.70     // More convenient zero-based profile timer in seconds. First call initializes 
   39.71     // the "zero" value; future calls return the difference. Not thread safe for first call.
   39.72     // Due to low precision of Double, may malfunction after long runtime.
   39.73     static double  OVR_STDCALL GetProfileSeconds();
   39.74 
   39.75     // Get the raw cycle counter value, providing the maximum possible timer resolution.
   39.76     static UInt64  OVR_STDCALL GetRawTicks();
   39.77     static UInt64  OVR_STDCALL GetRawFrequency();
   39.78 
   39.79     
   39.80     // ***** Tick and time unit conversion.
   39.81 
   39.82     // Convert micro-second ticks value into seconds value.
   39.83     static inline double TicksToSeconds(UInt64 ticks)
   39.84     {
   39.85         return static_cast<double>(ticks) * (1.0 / (double)MksPerSecond);
   39.86     }
   39.87     // Convert Raw or frequency-unit ticks to seconds based on specified frequency.
   39.88     static inline double RawTicksToSeconds(UInt64 rawTicks, UInt64 rawFrequency)
   39.89     {
   39.90         return static_cast<double>(rawTicks) * rawFrequency;
   39.91     }
   39.92 
   39.93 private:
   39.94     friend class System;
   39.95     // System called during program startup/shutdown.
   39.96     static void initializeTimerSystem();
   39.97     static void shutdownTimerSystem();
   39.98 };
   39.99 
  39.100 
  39.101 } // Scaleform::Timer
  39.102 
  39.103 #endif
  39.104 \ No newline at end of file
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/libovr/Src/Kernel/OVR_Types.h	Sat Sep 14 16:14:59 2013 +0300
    40.3 @@ -0,0 +1,1 @@
    40.4 +/************************************************************************************
    40.5 
    40.6 PublicHeader:   OVR.h
    40.7 Filename    :   OVR_Types.h
    40.8 Content     :   Standard library defines and simple types
    40.9 Created     :   September 19, 2012
   40.10 Notes       : 
   40.11 
   40.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   40.13 
   40.14 Use of this software is subject to the terms of the Oculus license
   40.15 agreement provided at the time of installation or download, or which
   40.16 otherwise accompanies this software in either electronic or hard copy form.
   40.17 
   40.18 ************************************************************************************/
   40.19 
   40.20 #ifndef OVR_Types_H
   40.21 #define OVR_Types_H
   40.22 
   40.23 //-----------------------------------------------------------------------------------
   40.24 // ****** Operating System
   40.25 //
   40.26 // Type definitions exist for the following operating systems: (OVR_OS_x)
   40.27 //
   40.28 //    WIN32    - Win32 (Windows 95/98/ME and Windows NT/2000/XP)
   40.29 //    DARWIN   - Darwin OS (Mac OS X)
   40.30 //    LINUX    - Linux
   40.31 //    ANDROID  - Android
   40.32 //    IPHONE   - iPhone
   40.33 
   40.34 #if (defined(__APPLE__) && (defined(__GNUC__) ||\
   40.35      defined(__xlC__) || defined(__xlc__))) || defined(__MACOS__)
   40.36 #  if (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) || defined(__IPHONE_OS_VERSION_MIN_REQUIRED))
   40.37 #    define OVR_OS_IPHONE
   40.38 #  else
   40.39 #    define OVR_OS_DARWIN
   40.40 #    define OVR_OS_MAC
   40.41 #  endif
   40.42 #elif (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
   40.43 #  define OVR_OS_WIN32
   40.44 #elif (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
   40.45 #  define OVR_OS_WIN32
   40.46 #elif defined(__linux__) || defined(__linux)
   40.47 #  define OVR_OS_LINUX
   40.48 #else
   40.49 #  define OVR_OS_OTHER
   40.50 #endif
   40.51 
   40.52 #if defined(ANDROID)
   40.53 #  define OVR_OS_ANDROID
   40.54 #endif
   40.55 
   40.56 
   40.57 //-----------------------------------------------------------------------------------
   40.58 // ***** CPU Architecture
   40.59 //
   40.60 // The following CPUs are defined: (OVR_CPU_x)
   40.61 //
   40.62 //    X86        - x86 (IA-32)
   40.63 //    X86_64     - x86_64 (amd64)
   40.64 //    PPC        - PowerPC
   40.65 //    PPC64      - PowerPC64
   40.66 //    MIPS       - MIPS
   40.67 //    OTHER      - CPU for which no special support is present or needed
   40.68 
   40.69 
   40.70 #if defined(__x86_64__) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
   40.71 #  define OVR_CPU_X86_64
   40.72 #  define OVR_64BIT_POINTERS
   40.73 #elif defined(__i386__) || defined(OVR_OS_WIN32)
   40.74 #  define OVR_CPU_X86
   40.75 #elif defined(__powerpc64__)
   40.76 #  define OVR_CPU_PPC64
   40.77 #elif defined(__ppc__)
   40.78 #  define OVR_CPU_PPC
   40.79 #elif defined(__mips__) || defined(__MIPSEL__)
   40.80 #  define OVR_CPU_MIPS
   40.81 #elif defined(__arm__)
   40.82 #  define OVR_CPU_ARM
   40.83 #else
   40.84 #  define OVR_CPU_OTHER
   40.85 #endif
   40.86 
   40.87 //-----------------------------------------------------------------------------------
   40.88 // ***** Co-Processor Architecture
   40.89 //
   40.90 // The following co-processors are defined: (OVR_CPU_x)
   40.91 //
   40.92 //    SSE        - Available on all modern x86 processors.
   40.93 //    Altivec    - Available on all modern ppc processors.
   40.94 //    Neon       - Available on some armv7+ processors.
   40.95 
   40.96 #if defined(__SSE__) || defined(OVR_OS_WIN32)
   40.97 #  define  OVR_CPU_SSE
   40.98 #endif // __SSE__
   40.99 
  40.100 #if defined( __ALTIVEC__ )
  40.101 #  define OVR_CPU_ALTIVEC
  40.102 #endif // __ALTIVEC__
  40.103 
  40.104 #if defined(__ARM_NEON__)
  40.105 #  define OVR_CPU_ARM_NEON
  40.106 #endif // __ARM_NEON__
  40.107 
  40.108 
  40.109 //-----------------------------------------------------------------------------------
  40.110 // ***** Compiler
  40.111 //
  40.112 //  The following compilers are defined: (OVR_CC_x)
  40.113 //
  40.114 //     MSVC     - Microsoft Visual C/C++
  40.115 //     INTEL    - Intel C++ for Linux / Windows
  40.116 //     GNU      - GNU C++
  40.117 //     ARM      - ARM C/C++
  40.118 
  40.119 #if defined(__INTEL_COMPILER)
  40.120 // Intel 4.0                    = 400
  40.121 // Intel 5.0                    = 500
  40.122 // Intel 6.0                    = 600
  40.123 // Intel 8.0                    = 800
  40.124 // Intel 9.0                    = 900
  40.125 #  define OVR_CC_INTEL       __INTEL_COMPILER
  40.126 
  40.127 #elif defined(_MSC_VER)
  40.128 // MSVC 5.0                     = 1100
  40.129 // MSVC 6.0                     = 1200
  40.130 // MSVC 7.0 (VC2002)            = 1300
  40.131 // MSVC 7.1 (VC2003)            = 1310
  40.132 // MSVC 8.0 (VC2005)            = 1400
  40.133 // MSVC 9.0 (VC2008)            = 1500
  40.134 // MSVC 10.0 (VC2010)           = 1600
  40.135 #  define OVR_CC_MSVC        _MSC_VER
  40.136 
  40.137 #elif defined(__GNUC__)
  40.138 #  define OVR_CC_GNU
  40.139 
  40.140 #elif defined(__CC_ARM)
  40.141 #  define OVR_CC_ARM
  40.142 
  40.143 #else
  40.144 #  error "Oculus does not support this Compiler"
  40.145 #endif
  40.146 
  40.147 
  40.148 //-----------------------------------------------------------------------------------
  40.149 // ***** Compiler Warnings
  40.150 
  40.151 // Disable MSVC warnings
  40.152 #if defined(OVR_CC_MSVC)
  40.153 #  pragma warning(disable : 4127)    // Inconsistent dll linkage
  40.154 #  pragma warning(disable : 4530)    // Exception handling
  40.155 #  if (OVR_CC_MSVC<1300)
  40.156 #    pragma warning(disable : 4514)  // Unreferenced inline function has been removed
  40.157 #    pragma warning(disable : 4710)  // Function not inlined
  40.158 #    pragma warning(disable : 4714)  // _force_inline not inlined
  40.159 #    pragma warning(disable : 4786)  // Debug variable name longer than 255 chars
  40.160 #  endif // (OVR_CC_MSVC<1300)
  40.161 #endif // (OVR_CC_MSVC)
  40.162 
  40.163 
  40.164 
  40.165 // *** Linux Unicode - must come before Standard Includes
  40.166 
  40.167 #ifdef OVR_OS_LINUX
  40.168 // Use glibc unicode functions on linux.
  40.169 #  ifndef  _GNU_SOURCE
  40.170 #    define _GNU_SOURCE
  40.171 #  endif
  40.172 #endif
  40.173 
  40.174 //-----------------------------------------------------------------------------------
  40.175 // ***** Standard Includes
  40.176 //
  40.177 #include    <stddef.h>
  40.178 #include    <limits.h>
  40.179 #include    <float.h>
  40.180 
  40.181 
  40.182 // MSVC Based Memory Leak checking - for now
  40.183 #if defined(OVR_CC_MSVC) && defined(OVR_BUILD_DEBUG)
  40.184 #  define _CRTDBG_MAP_ALLOC
  40.185 #  include <stdlib.h>
  40.186 #  include <crtdbg.h>
  40.187 
  40.188 // Uncomment this to help debug memory leaks under Visual Studio in OVR apps only.
  40.189 // This shouldn't be defined in customer releases.
  40.190 #  ifndef OVR_DEFINE_NEW
  40.191 #    define OVR_DEFINE_NEW new(__FILE__, __LINE__)
  40.192 #    define new OVR_DEFINE_NEW
  40.193 #  endif
  40.194 
  40.195 #endif
  40.196 
  40.197 
  40.198 //-----------------------------------------------------------------------------------
  40.199 // ***** Type definitions for Common Systems
  40.200 
  40.201 namespace OVR {
  40.202 
  40.203 typedef char            Char;
  40.204 
  40.205 // Pointer-sized integer
  40.206 typedef size_t          UPInt;
  40.207 typedef ptrdiff_t       SPInt;
  40.208 
  40.209 
  40.210 #if defined(OVR_OS_WIN32)
  40.211 
  40.212 typedef char            SByte;  // 8 bit Integer (Byte)
  40.213 typedef unsigned char   UByte;
  40.214 typedef short           SInt16; // 16 bit Integer (Word)
  40.215 typedef unsigned short  UInt16;
  40.216 typedef long            SInt32; // 32 bit Integer
  40.217 typedef unsigned long   UInt32;
  40.218 typedef __int64         SInt64; // 64 bit Integer (QWord)
  40.219 typedef unsigned __int64 UInt64;
  40.220 
  40.221  
  40.222 #elif defined(OVR_OS_MAC) || defined(OVR_OS_IPHONE) || defined(OVR_CC_GNU)
  40.223 
  40.224 typedef int             SByte  __attribute__((__mode__ (__QI__)));
  40.225 typedef unsigned int    UByte  __attribute__((__mode__ (__QI__)));
  40.226 typedef int             SInt16 __attribute__((__mode__ (__HI__)));
  40.227 typedef unsigned int    UInt16 __attribute__((__mode__ (__HI__)));
  40.228 typedef int             SInt32 __attribute__((__mode__ (__SI__)));
  40.229 typedef unsigned int    UInt32 __attribute__((__mode__ (__SI__)));
  40.230 typedef int             SInt64 __attribute__((__mode__ (__DI__)));
  40.231 typedef unsigned int    UInt64 __attribute__((__mode__ (__DI__)));
  40.232 
  40.233 #else
  40.234 
  40.235 #include <sys/types.h>
  40.236 typedef int8_t          SByte;
  40.237 typedef uint8_t         UByte;
  40.238 typedef int16_t         SInt16;
  40.239 typedef uint16_t        UInt16;
  40.240 typedef int32_t         SInt32;
  40.241 typedef uint32_t        UInt32;
  40.242 typedef int64_t         SInt64;
  40.243 typedef uint64_t        UInt64;
  40.244 
  40.245 #endif
  40.246 
  40.247 
  40.248 // ***** BaseTypes Namespace
  40.249 
  40.250 // BaseTypes namespace is explicitly declared to allow base types to be used
  40.251 // by customers directly without other contents of OVR namespace.
  40.252 //
  40.253 // Its is expected that GFx samples will declare 'using namespace OVR::BaseTypes'
  40.254 // to allow using these directly without polluting the target scope with other
  40.255 // OVR declarations, such as Ptr<>, String or Mutex.
  40.256 namespace BaseTypes
  40.257 {
  40.258     using OVR::UPInt;
  40.259     using OVR::SPInt;
  40.260     using OVR::UByte;
  40.261     using OVR::SByte;
  40.262     using OVR::UInt16;
  40.263     using OVR::SInt16;
  40.264     using OVR::UInt32;
  40.265     using OVR::SInt32;
  40.266     using OVR::UInt64;
  40.267     using OVR::SInt64;
  40.268 } // OVR::BaseTypes
  40.269 
  40.270 } // OVR
  40.271 
  40.272 
  40.273 //-----------------------------------------------------------------------------------
  40.274 // ***** Macro Definitions
  40.275 //
  40.276 // We define the following:
  40.277 //
  40.278 //  OVR_BYTE_ORDER      - Defined to either OVR_LITTLE_ENDIAN or OVR_BIG_ENDIAN
  40.279 //  OVR_FORCE_INLINE    - Forces inline expansion of function
  40.280 //  OVR_ASM             - Assembly language prefix
  40.281 //  OVR_STR             - Prefixes string with L"" if building unicode
  40.282 // 
  40.283 //  OVR_STDCALL         - Use stdcall calling convention (Pascal arg order)
  40.284 //  OVR_CDECL           - Use cdecl calling convention (C argument order)
  40.285 //  OVR_FASTCALL        - Use fastcall calling convention (registers)
  40.286 //
  40.287 
  40.288 // Byte order constants, OVR_BYTE_ORDER is defined to be one of these.
  40.289 #define OVR_LITTLE_ENDIAN       1
  40.290 #define OVR_BIG_ENDIAN          2
  40.291 
  40.292 
  40.293 // Force inline substitute - goes before function declaration
  40.294 #if defined(OVR_CC_MSVC)
  40.295 #  define OVR_FORCE_INLINE  __forceinline
  40.296 #elif defined(OVR_CC_GNU)
  40.297 #  define OVR_FORCE_INLINE  __attribute__((always_inline)) inline
  40.298 #else
  40.299 #  define OVR_FORCE_INLINE  inline
  40.300 #endif  // OVR_CC_MSVC
  40.301 
  40.302 
  40.303 #if defined(OVR_OS_WIN32)
  40.304     
  40.305     // ***** Win32
  40.306 
  40.307     // Byte order
  40.308     #define OVR_BYTE_ORDER    OVR_LITTLE_ENDIAN
  40.309 
  40.310     // Calling convention - goes after function return type but before function name
  40.311     #ifdef __cplusplus_cli
  40.312     #  define OVR_FASTCALL      __stdcall
  40.313     #else
  40.314     #  define OVR_FASTCALL      __fastcall
  40.315     #endif
  40.316 
  40.317     #define OVR_STDCALL         __stdcall
  40.318     #define OVR_CDECL           __cdecl
  40.319 
  40.320 
  40.321     // Assembly macros
  40.322     #if defined(OVR_CC_MSVC)
  40.323     #  define OVR_ASM           _asm
  40.324     #else
  40.325     #  define OVR_ASM           asm
  40.326     #endif // (OVR_CC_MSVC)
  40.327 
  40.328     #ifdef UNICODE
  40.329     #  define OVR_STR(str)      L##str
  40.330     #else
  40.331     #  define OVR_STR(str)      str
  40.332     #endif // UNICODE
  40.333 
  40.334 #else
  40.335 
  40.336     // **** Standard systems
  40.337 
  40.338     #if (defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN))|| \
  40.339         (defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN))
  40.340     #  define OVR_BYTE_ORDER    OVR_BIG_ENDIAN
  40.341     #elif (defined(__ARMEB__) || defined(OVR_CPU_PPC) || defined(OVR_CPU_PPC64))
  40.342     #  define OVR_BYTE_ORDER    OVR_BIG_ENDIAN
  40.343     #else
  40.344     #  define OVR_BYTE_ORDER    OVR_LITTLE_ENDIAN
  40.345     #endif
  40.346     
  40.347     // Assembly macros
  40.348     #define OVR_ASM                  __asm__
  40.349     #define OVR_ASM_PROC(procname)   OVR_ASM
  40.350     #define OVR_ASM_END              OVR_ASM
  40.351     
  40.352     // Calling convention - goes after function return type but before function name
  40.353     #define OVR_FASTCALL
  40.354     #define OVR_STDCALL
  40.355     #define OVR_CDECL
  40.356 
  40.357 #endif // defined(OVR_OS_WIN32)
  40.358 
  40.359 
  40.360 
  40.361 //-----------------------------------------------------------------------------------
  40.362 // ***** OVR_DEBUG_BREAK, OVR_ASSERT
  40.363 //
  40.364 // If not in debug build, macros do nothing
  40.365 #ifndef OVR_BUILD_DEBUG
  40.366 
  40.367 #  define OVR_DEBUG_BREAK  ((void)0)
  40.368 #  define OVR_ASSERT(p)    ((void)0)
  40.369 
  40.370 #else 
  40.371 
  40.372 // Microsoft Win32 specific debugging support
  40.373 #if defined(OVR_OS_WIN32)
  40.374 #  ifdef OVR_CPU_X86
  40.375 #    if defined(__cplusplus_cli)
  40.376 #      define OVR_DEBUG_BREAK   do { __debugbreak(); } while(0)
  40.377 #    elif defined(OVR_CC_GNU)
  40.378 #      define OVR_DEBUG_BREAK   do { OVR_ASM("int $3\n\t"); } while(0)
  40.379 #    else
  40.380 #      define OVR_DEBUG_BREAK   do { OVR_ASM int 3 } while (0)
  40.381 #    endif
  40.382 #  else
  40.383 #    define OVR_DEBUG_BREAK     do { __debugbreak(); } while(0)
  40.384 #  endif
  40.385 // Unix specific debugging support
  40.386 #elif defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64)
  40.387 #  define OVR_DEBUG_BREAK       do { OVR_ASM("int $3\n\t"); } while(0)
  40.388 #else
  40.389 #  define OVR_DEBUG_BREAK       do { *((int *) 0) = 1; } while(0)
  40.390 #endif
  40.391 
  40.392 // This will cause compiler breakpoint
  40.393 #define OVR_ASSERT(p)           do { if (!(p))  { OVR_DEBUG_BREAK; } } while(0)
  40.394 
  40.395 #endif // OVR_BUILD_DEBUG
  40.396 
  40.397 
  40.398 // Compile-time assert; produces compiler error if condition is false
  40.399 #define OVR_COMPILER_ASSERT(x)  { int zero = 0; switch(zero) {case 0: case x:;} }
  40.400 
  40.401 
  40.402 
  40.403 //-----------------------------------------------------------------------------------
  40.404 // ***** OVR_UNUSED - Unused Argument handling
  40.405 
  40.406 // Macro to quiet compiler warnings about unused parameters/variables.
  40.407 #if defined(OVR_CC_GNU)
  40.408 #  define   OVR_UNUSED(a)   do {__typeof__ (&a) __attribute__ ((unused)) __tmp = &a; } while(0)
  40.409 #else
  40.410 #  define   OVR_UNUSED(a)   (a)
  40.411 #endif
  40.412 
  40.413 #define     OVR_UNUSED1(a1) OVR_UNUSED(a1)
  40.414 #define     OVR_UNUSED2(a1,a2) OVR_UNUSED(a1); OVR_UNUSED(a2)
  40.415 #define     OVR_UNUSED3(a1,a2,a3) OVR_UNUSED2(a1,a2); OVR_UNUSED(a3)
  40.416 #define     OVR_UNUSED4(a1,a2,a3,a4) OVR_UNUSED3(a1,a2,a3); OVR_UNUSED(a4)
  40.417 #define     OVR_UNUSED5(a1,a2,a3,a4,a5) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED(a5)
  40.418 #define     OVR_UNUSED6(a1,a2,a3,a4,a5,a6) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED2(a5,a6)
  40.419 #define     OVR_UNUSED7(a1,a2,a3,a4,a5,a6,a7) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED3(a5,a6,a7)
  40.420 #define     OVR_UNUSED8(a1,a2,a3,a4,a5,a6,a7,a8) OVR_UNUSED4(a1,a2,a3,a4); OVR_UNUSED4(a5,a6,a7,a8)
  40.421 #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)
  40.422 
  40.423 
  40.424 //-----------------------------------------------------------------------------------
  40.425 // ***** Configuration Macros
  40.426 
  40.427 // SF Build type
  40.428 #ifdef OVR_BUILD_DEBUG
  40.429 #  define OVR_BUILD_STRING  "Debug"
  40.430 #else
  40.431 #  define OVR_BUILD_STRING  "Release"
  40.432 #endif
  40.433 
  40.434 
  40.435 //// Enables SF Debugging information
  40.436 //# define OVR_BUILD_DEBUG
  40.437 
  40.438 // OVR_DEBUG_STATEMENT injects a statement only in debug builds.
  40.439 // OVR_DEBUG_SELECT injects first argument in debug builds, second argument otherwise.
  40.440 #ifdef OVR_BUILD_DEBUG
  40.441 #define OVR_DEBUG_STATEMENT(s)   s
  40.442 #define OVR_DEBUG_SELECT(d, nd)  d
  40.443 #else
  40.444 #define OVR_DEBUG_STATEMENT(s)
  40.445 #define OVR_DEBUG_SELECT(d, nd)  nd
  40.446 #endif
  40.447 
  40.448 
  40.449 #define OVR_ENABLE_THREADS
  40.450 //
  40.451 // Prevents OVR from defining new within
  40.452 // type macros, so developers can override
  40.453 // new using the #define new new(...) trick
  40.454 // - used with OVR_DEFINE_NEW macro
  40.455 //# define OVR_BUILD_DEFINE_NEW
  40.456 //
  40.457 
  40.458 
  40.459 #endif  // OVR_Types_h
  40.460 \ No newline at end of file
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/libovr/Src/Kernel/OVR_UTF8Util.cpp	Sat Sep 14 16:14:59 2013 +0300
    41.3 @@ -0,0 +1,1 @@
    41.4 +/**************************************************************************
    41.5 
    41.6 Filename    :   OVR_UTF8Util.cpp
    41.7 Content     :   UTF8 Unicode character encoding/decoding support
    41.8 Created     :   September 19, 2012
    41.9 Notes       : 
   41.10 Notes       :   Much useful info at "UTF-8 and Unicode FAQ"
   41.11                 http://www.cl.cam.ac.uk/~mgk25/unicode.html
   41.12 
   41.13 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   41.14 
   41.15 Use of this software is subject to the terms of the Oculus license
   41.16 agreement provided at the time of installation or download, or which
   41.17 otherwise accompanies this software in either electronic or hard copy form.
   41.18 
   41.19 ************************************************************************************/
   41.20 
   41.21 #include "OVR_UTF8Util.h"
   41.22 
   41.23 namespace OVR { namespace UTF8Util {
   41.24 
   41.25 SPInt OVR_STDCALL GetLength(const char* buf, SPInt buflen)
   41.26 {
   41.27     const char* p = buf;
   41.28     SPInt length = 0;
   41.29 
   41.30     if (buflen != -1)
   41.31     {
   41.32         while (p - buf < buflen)
   41.33         {
   41.34             // We should be able to have ASStrings with 0 in the middle.
   41.35             UTF8Util::DecodeNextChar_Advance0(&p);
   41.36             length++;
   41.37         }
   41.38     }
   41.39     else
   41.40     {
   41.41         while (UTF8Util::DecodeNextChar_Advance0(&p))
   41.42             length++;
   41.43     }
   41.44     
   41.45     return length;
   41.46 }
   41.47 
   41.48 UInt32 OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length)
   41.49 {
   41.50     const char* buf = putf8str;
   41.51     UInt32  c = 0;
   41.52 
   41.53     if (length != -1)
   41.54     {
   41.55         while (buf - putf8str < length)
   41.56         {           
   41.57             c = UTF8Util::DecodeNextChar_Advance0(&buf);
   41.58             if (index == 0)
   41.59                 return c;
   41.60             index--;
   41.61         }
   41.62 
   41.63         return c;
   41.64     }
   41.65 
   41.66     do 
   41.67     {
   41.68         c = UTF8Util::DecodeNextChar_Advance0(&buf);
   41.69         index--;
   41.70 
   41.71         if (c == 0)
   41.72         {
   41.73             // We've hit the end of the string; don't go further.
   41.74             OVR_ASSERT(index == 0);
   41.75             return c;
   41.76         }
   41.77     } while (index >= 0);
   41.78 
   41.79     return c;
   41.80 }
   41.81 
   41.82 SPInt OVR_STDCALL GetByteIndex(SPInt index, const char *putf8str, SPInt length)
   41.83 {
   41.84     const char* buf = putf8str;
   41.85 
   41.86     if (length != -1)
   41.87     {
   41.88         while ((buf - putf8str) < length && index > 0)
   41.89         {
   41.90             UTF8Util::DecodeNextChar_Advance0(&buf);
   41.91             index--;
   41.92         }
   41.93 
   41.94         return buf-putf8str;
   41.95     }
   41.96 
   41.97     while (index > 0) 
   41.98     {
   41.99         UInt32 c = UTF8Util::DecodeNextChar_Advance0(&buf);
  41.100         index--;
  41.101 
  41.102         if (c == 0)
  41.103             return buf-putf8str;
  41.104     };
  41.105 
  41.106     return buf-putf8str;
  41.107 }
  41.108 
  41.109 int OVR_STDCALL GetEncodeCharSize(UInt32 ucs_character)
  41.110 {
  41.111     if (ucs_character <= 0x7F)
  41.112         return 1;
  41.113     else if (ucs_character <= 0x7FF)
  41.114         return 2;
  41.115     else if (ucs_character <= 0xFFFF)
  41.116         return 3;
  41.117     else if (ucs_character <= 0x1FFFFF)
  41.118         return 4;
  41.119     else if (ucs_character <= 0x3FFFFFF)
  41.120         return 5;
  41.121     else if (ucs_character <= 0x7FFFFFFF)
  41.122         return 6;
  41.123     else
  41.124         return 0;
  41.125 }
  41.126 
  41.127 UInt32 OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer)
  41.128 {
  41.129     UInt32  uc;
  41.130     char    c;
  41.131     
  41.132     // Security considerations:
  41.133     //
  41.134     // Changed, this is now only the case for DecodeNextChar:
  41.135     //  - If we hit a zero byte, we want to return 0 without stepping
  41.136     //    the buffer pointer past the 0. th
  41.137     //
  41.138     // If we hit an "overlong sequence"; i.e. a character encoded
  41.139     // in a longer multibyte string than is necessary, then we
  41.140     // need to discard the character.  This is so attackers can't
  41.141     // disguise dangerous characters or character sequences --
  41.142     // there is only one valid encoding for each character.
  41.143     //
  41.144     // If we decode characters { 0xD800 .. 0xDFFF } or { 0xFFFE,
  41.145     // 0xFFFF } then we ignore them; they are not valid in UTF-8.
  41.146     
  41.147     // This isn't actually an invalid character; it's a valid char that
  41.148     // looks like an inverted question mark.
  41.149 #define INVALID_CHAR 0x0FFFD
  41.150     
  41.151 #define FIRST_BYTE(mask, shift)     \
  41.152     uc = (c & (mask)) << (shift);
  41.153     
  41.154 #define NEXT_BYTE(shift) \
  41.155     c = **putf8Buffer;   \
  41.156     if (c == 0) return 0; /* end of buffer, do not advance */   \
  41.157     if ((c & 0xC0) != 0x80) return INVALID_CHAR; /* standard check */  \
  41.158     (*putf8Buffer)++;    \
  41.159     uc |= (c & 0x3F) << shift;
  41.160     
  41.161     c = **putf8Buffer;
  41.162     (*putf8Buffer)++;
  41.163     if (c == 0)
  41.164         return 0;   // End of buffer.
  41.165     
  41.166     if ((c & 0x80) == 0) return (UInt32) c; // Conventional 7-bit ASCII.
  41.167     
  41.168     // Multi-byte sequences.
  41.169     if ((c & 0xE0) == 0xC0)
  41.170     {
  41.171         // Two-byte sequence.
  41.172         FIRST_BYTE(0x1F, 6);
  41.173         NEXT_BYTE(0);
  41.174         if (uc < 0x80) return INVALID_CHAR;  // overlong
  41.175         return uc;
  41.176     }
  41.177     else if ((c & 0xF0) == 0xE0)
  41.178     {
  41.179         // Three-byte sequence.
  41.180         FIRST_BYTE(0x0F, 12);
  41.181         NEXT_BYTE(6);
  41.182         NEXT_BYTE(0);
  41.183         if (uc < 0x800) return INVALID_CHAR; // overlong
  41.184         // Not valid ISO 10646, but Flash requires these to work
  41.185         // see AS3 test e15_5_3_2_3 for String.fromCharCode().charCodeAt(0)
  41.186         // if (uc >= 0x0D800 && uc <= 0x0DFFF) return INVALID_CHAR;
  41.187         // if (uc == 0x0FFFE || uc == 0x0FFFF) return INVALID_CHAR; // not valid ISO 10646
  41.188         return uc;
  41.189     }
  41.190     else if ((c & 0xF8) == 0xF0)
  41.191     {
  41.192         // Four-byte sequence.
  41.193         FIRST_BYTE(0x07, 18);
  41.194         NEXT_BYTE(12);
  41.195         NEXT_BYTE(6);
  41.196         NEXT_BYTE(0);
  41.197         if (uc < 0x010000) return INVALID_CHAR;  // overlong
  41.198         return uc;
  41.199     }
  41.200     else if ((c & 0xFC) == 0xF8)
  41.201     {
  41.202         // Five-byte sequence.
  41.203         FIRST_BYTE(0x03, 24);
  41.204         NEXT_BYTE(18);
  41.205         NEXT_BYTE(12);
  41.206         NEXT_BYTE(6);
  41.207         NEXT_BYTE(0);
  41.208         if (uc < 0x0200000) return INVALID_CHAR; // overlong
  41.209         return uc;
  41.210     }
  41.211     else if ((c & 0xFE) == 0xFC)
  41.212     {
  41.213         // Six-byte sequence.
  41.214         FIRST_BYTE(0x01, 30);
  41.215         NEXT_BYTE(24);
  41.216         NEXT_BYTE(18);
  41.217         NEXT_BYTE(12);
  41.218         NEXT_BYTE(6);
  41.219         NEXT_BYTE(0);
  41.220         if (uc < 0x04000000) return INVALID_CHAR;    // overlong
  41.221         return uc;
  41.222     }
  41.223     else
  41.224     {
  41.225         // Invalid.
  41.226         return INVALID_CHAR;
  41.227     }
  41.228 }
  41.229 
  41.230 
  41.231 void OVR_STDCALL EncodeChar(char* pbuffer, SPInt* pindex, UInt32 ucs_character)
  41.232 {
  41.233     if (ucs_character <= 0x7F)
  41.234     {
  41.235         // Plain single-byte ASCII.
  41.236         pbuffer[(*pindex)++] = (char) ucs_character;
  41.237     }
  41.238     else if (ucs_character <= 0x7FF)
  41.239     {
  41.240         // Two bytes.
  41.241         pbuffer[(*pindex)++] = 0xC0 | (char)(ucs_character >> 6);
  41.242         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  41.243     }
  41.244     else if (ucs_character <= 0xFFFF)
  41.245     {
  41.246         // Three bytes.
  41.247         pbuffer[(*pindex)++] = 0xE0 | (char)(ucs_character >> 12);
  41.248         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
  41.249         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  41.250     }
  41.251     else if (ucs_character <= 0x1FFFFF)
  41.252     {
  41.253         // Four bytes.
  41.254         pbuffer[(*pindex)++] = 0xF0 | (char)(ucs_character >> 18);
  41.255         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F);
  41.256         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
  41.257         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  41.258     }
  41.259     else if (ucs_character <= 0x3FFFFFF)
  41.260     {
  41.261         // Five bytes.
  41.262         pbuffer[(*pindex)++] = 0xF8 | (char)(ucs_character >> 24);
  41.263         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F);
  41.264         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F);
  41.265         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
  41.266         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  41.267     }
  41.268     else if (ucs_character <= 0x7FFFFFFF)
  41.269     {
  41.270         // Six bytes.
  41.271         pbuffer[(*pindex)++] = 0xFC | (char)(ucs_character >> 30);
  41.272         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 24) & 0x3F);
  41.273         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 18) & 0x3F);
  41.274         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 12) & 0x3F);
  41.275         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 6) & 0x3F);
  41.276         pbuffer[(*pindex)++] = 0x80 | (char)((ucs_character >> 0) & 0x3F);
  41.277     }
  41.278     else
  41.279     {
  41.280         // Invalid char; don't encode anything.
  41.281     }
  41.282 }
  41.283 
  41.284 SPInt OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length)
  41.285 {
  41.286     SPInt len = 0;
  41.287     if (length != -1)
  41.288         for (int i = 0; i < length; i++)
  41.289         {
  41.290             len += GetEncodeCharSize(pchar[i]);
  41.291         }
  41.292     else
  41.293         for (int i = 0;; i++)
  41.294         {
  41.295             if (pchar[i] == 0)
  41.296                 return len;
  41.297             len += GetEncodeCharSize(pchar[i]);
  41.298         }
  41.299     return len;
  41.300 }
  41.301 
  41.302 void OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length)
  41.303 {
  41.304     SPInt ofs = 0;
  41.305     if (length != -1)
  41.306     {
  41.307         for (int i = 0; i < length; i++)
  41.308         {            
  41.309             EncodeChar(pbuff, &ofs, pchar[i]);
  41.310         }
  41.311     }
  41.312     else
  41.313     {
  41.314         for (int i = 0;; i++)
  41.315         {
  41.316             if (pchar[i] == 0)
  41.317                 break;
  41.318             EncodeChar(pbuff, &ofs, pchar[i]);
  41.319         }
  41.320     }
  41.321     pbuff[ofs] = 0;
  41.322 }
  41.323 
  41.324 UPInt OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen)
  41.325 {
  41.326     wchar_t *pbegin = pbuff;
  41.327     if (bytesLen == -1)
  41.328     {
  41.329         while (1)
  41.330         {
  41.331             UInt32 ch = DecodeNextChar_Advance0(&putf8str);
  41.332             if (ch == 0)
  41.333                 break;
  41.334             else if (ch >= 0xFFFF)
  41.335                 ch = 0xFFFD;
  41.336             *pbuff++ = wchar_t(ch);
  41.337         }
  41.338     }
  41.339     else
  41.340     {
  41.341         const char* p = putf8str;
  41.342         while ((p - putf8str) < bytesLen)
  41.343         {
  41.344             UInt32 ch = DecodeNextChar_Advance0(&p);
  41.345             if (ch >= 0xFFFF)
  41.346                 ch = 0xFFFD;
  41.347             *pbuff++ = wchar_t(ch);
  41.348         }
  41.349     }
  41.350 
  41.351     *pbuff = 0;
  41.352     return pbuff - pbegin;
  41.353 }
  41.354 
  41.355 
  41.356 #ifdef UTF8_UNIT_TEST
  41.357 
  41.358 // Compile this test case with something like:
  41.359 //
  41.360 // gcc utf8.cpp -g -I.. -DUTF8_UNIT_TEST -lstdc++ -o utf8_test
  41.361 //
  41.362 //    or
  41.363 //
  41.364 // cl utf8.cpp -Zi -Od -DUTF8_UNIT_TEST -I..
  41.365 //
  41.366 // If possible, try running the test program with the first arg
  41.367 // pointing at the file:
  41.368 //
  41.369 // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
  41.370 // 
  41.371 // and examine the results by eye to make sure they are acceptable to
  41.372 // you.
  41.373 
  41.374 
  41.375 #include "base/utility.h"
  41.376 #include <stdio.h>
  41.377 
  41.378 
  41.379 bool    check_equal(const char* utf8_in, const UInt32* ucs_in)
  41.380 {
  41.381     for (;;)
  41.382     {
  41.383         UInt32  next_ucs = *ucs_in++;
  41.384         UInt32  next_ucs_from_utf8 = utf8::decode_next_unicode_character(&utf8_in);
  41.385         if (next_ucs != next_ucs_from_utf8)
  41.386         {
  41.387             return false;
  41.388         }
  41.389         if (next_ucs == 0)
  41.390         {
  41.391             OVR_ASSERT(next_ucs_from_utf8 == 0);
  41.392             break;
  41.393         }
  41.394     }
  41.395     
  41.396     return true;
  41.397 }
  41.398 
  41.399 
  41.400 void    log_ascii(const char* line)
  41.401 {
  41.402     for (;;)
  41.403     {
  41.404         unsigned char   c = (unsigned char) *line++;
  41.405         if (c == 0)
  41.406         {
  41.407             // End of line.
  41.408             return;
  41.409         }
  41.410         else if (c != '\n'
  41.411             && (c < 32 || c > 127))
  41.412         {
  41.413             // Non-printable as plain ASCII.
  41.414             printf("<0x%02X>", (int) c);
  41.415         }
  41.416         else
  41.417         {
  41.418             printf("%c", c);
  41.419         }
  41.420     }
  41.421 }
  41.422 
  41.423 
  41.424 void    log_ucs(const UInt32* line)
  41.425 {
  41.426     for (;;)
  41.427     {
  41.428         UInt32  uc = *line++;
  41.429         if (uc == 0)
  41.430         {
  41.431             // End of line.
  41.432             return;
  41.433         }
  41.434         else if (uc != '\n'
  41.435             && (uc < 32 || uc > 127))
  41.436         {
  41.437             // Non-printable as plain ASCII.
  41.438             printf("<U-%04X>", uc);
  41.439         }
  41.440         else
  41.441         {
  41.442             printf("%c", (char) uc);
  41.443         }
  41.444     }
  41.445 }
  41.446 
  41.447 
  41.448 // Simple canned test.
  41.449 int main(int argc, const char* argv[])
  41.450 {
  41.451     {
  41.452         const char* test8 = "Ignacio Castaño";
  41.453         const UInt32    test32[] =
  41.454         {
  41.455             0x49, 0x67, 0x6E, 0x61, 0x63,
  41.456                 0x69, 0x6F, 0x20, 0x43, 0x61,
  41.457                 0x73, 0x74, 0x61, 0xF1, 0x6F,
  41.458                 0x00
  41.459         };
  41.460         
  41.461         OVR_ASSERT(check_equal(test8, test32));
  41.462     }
  41.463         
  41.464         // If user passed an arg, try reading the file as UTF-8 encoded text.
  41.465         if (argc > 1)
  41.466         {
  41.467             const char* filename = argv[1];
  41.468             FILE*   fp = fopen(filename, "rb");
  41.469             if (fp == NULL)
  41.470             {
  41.471                 printf("Can't open file '%s'\n", filename);
  41.472                 return 1;
  41.473             }
  41.474             
  41.475             // Read lines from the file, encode/decode them, and highlight discrepancies.
  41.476             const int LINE_SIZE = 200;  // max line size
  41.477             char    line_buffer_utf8[LINE_SIZE];
  41.478             char    reencoded_utf8[6 * LINE_SIZE];
  41.479             UInt32  line_buffer_ucs[LINE_SIZE];
  41.480             
  41.481             int byte_counter = 0;
  41.482             for (;;)
  41.483             {
  41.484                 int c = fgetc(fp);
  41.485                 if (c == EOF)
  41.486                 {
  41.487                     // Done.
  41.488                     break;
  41.489                 }
  41.490                 line_buffer_utf8[byte_counter++] = c;
  41.491                 if (c == '\n' || byte_counter >= LINE_SIZE - 2)
  41.492                 {
  41.493                     // End of line.  Process the line.
  41.494                     line_buffer_utf8[byte_counter++] = 0;   // terminate.
  41.495                     
  41.496                     // Decode into UCS.
  41.497                     const char* p = line_buffer_utf8;
  41.498                     UInt32* q = line_buffer_ucs;
  41.499                     for (;;)
  41.500                     {
  41.501                         UInt32  uc = UTF8Util::DecodeNextChar(&p);
  41.502                         *q++ = uc;
  41.503                         
  41.504                         OVR_ASSERT(q < line_buffer_ucs + LINE_SIZE);
  41.505                         OVR_ASSERT(p < line_buffer_utf8 + LINE_SIZE);
  41.506                         
  41.507                         if (uc == 0) break;
  41.508                     }
  41.509                     
  41.510                     // Encode back into UTF-8.
  41.511                     q = line_buffer_ucs;
  41.512                     int index = 0;
  41.513                     for (;;)
  41.514                     {
  41.515                         UInt32  uc = *q++;
  41.516                         OVR_ASSERT(index < LINE_SIZE * 6 - 6);
  41.517                         int last_index = index;
  41.518                         UTF8Util::EncodeChar(reencoded_utf8, &index, uc);
  41.519                         OVR_ASSERT(index <= last_index + 6);
  41.520                         if (uc == 0) break;
  41.521                     }
  41.522                     
  41.523                     // This can be useful for debugging.
  41.524 #if 0
  41.525                     // Show the UCS and the re-encoded UTF-8.
  41.526                     log_ucs(line_buffer_ucs);
  41.527                     log_ascii(reencoded_utf8);
  41.528 #endif // 0
  41.529                     
  41.530                     OVR_ASSERT(check_equal(line_buffer_utf8, line_buffer_ucs));
  41.531                     OVR_ASSERT(check_equal(reencoded_utf8, line_buffer_ucs));
  41.532                     
  41.533                     // Start next line.
  41.534                     byte_counter = 0;
  41.535                 }
  41.536             }
  41.537             
  41.538             fclose(fp);
  41.539         }
  41.540         
  41.541         return 0;
  41.542 }
  41.543 
  41.544 
  41.545 #endif // UTF8_UNIT_TEST
  41.546 
  41.547 }} // namespace UTF8Util::OVR
  41.548 
  41.549 \ No newline at end of file
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/libovr/Src/Kernel/OVR_UTF8Util.h	Sat Sep 14 16:14:59 2013 +0300
    42.3 @@ -0,0 +1,1 @@
    42.4 +/************************************************************************************
    42.5 
    42.6 PublicHeader:   OVR.h
    42.7 Filename    :   OVR_UTF8Util.h
    42.8 Content     :   UTF8 Unicode character encoding/decoding support
    42.9 Created     :   September 19, 2012
   42.10 Notes       : 
   42.11 
   42.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   42.13 
   42.14 Use of this software is subject to the terms of the Oculus license
   42.15 agreement provided at the time of installation or download, or which
   42.16 otherwise accompanies this software in either electronic or hard copy form.
   42.17 
   42.18 ************************************************************************************/
   42.19 
   42.20 #ifndef OVR_UTF8Util_h
   42.21 #define OVR_UTF8Util_h
   42.22 
   42.23 #include "OVR_Types.h"
   42.24 
   42.25 namespace OVR { namespace UTF8Util {
   42.26 
   42.27 //-----------------------------------------------------------------------------------
   42.28 
   42.29 // *** UTF8 string length and indexing.
   42.30 
   42.31 // Determines the length of UTF8 string in characters.
   42.32 // If source length is specified (in bytes), null 0 character is counted properly.
   42.33 SPInt    OVR_STDCALL GetLength(const char* putf8str, SPInt length = -1);
   42.34 
   42.35 // Gets a decoded UTF8 character at index; you can access up to the index returned
   42.36 // by GetLength. 0 will be returned for out of bounds access.
   42.37 UInt32   OVR_STDCALL GetCharAt(SPInt index, const char* putf8str, SPInt length = -1);
   42.38 
   42.39 // Converts UTF8 character index into byte offset.
   42.40 // -1 is returned if index was out of bounds.
   42.41 SPInt    OVR_STDCALL GetByteIndex(SPInt index, const char* putf8str, SPInt length = -1);
   42.42 
   42.43 
   42.44 // *** 16-bit Unicode string Encoding/Decoding routines.
   42.45 
   42.46 // Determines the number of bytes necessary to encode a string.
   42.47 // Does not count the terminating 0 (null) character.
   42.48 SPInt    OVR_STDCALL GetEncodeStringSize(const wchar_t* pchar, SPInt length = -1);
   42.49 
   42.50 // Encodes a unicode (UCS-2 only) string into a buffer. The size of buffer must be at
   42.51 // least GetEncodeStringSize() + 1.
   42.52 void     OVR_STDCALL EncodeString(char *pbuff, const wchar_t* pchar, SPInt length = -1);
   42.53 
   42.54 // Decode UTF8 into a wchar_t buffer. Must have GetLength()+1 characters available.
   42.55 // Characters over 0xFFFF are replaced with 0xFFFD.
   42.56 // Returns the length of resulting string (number of characters)
   42.57 UPInt    OVR_STDCALL DecodeString(wchar_t *pbuff, const char* putf8str, SPInt bytesLen = -1);
   42.58 
   42.59 
   42.60 // *** Individual character Encoding/Decoding.
   42.61 
   42.62 // Determined the number of bytes necessary to encode a UCS character.
   42.63 int      OVR_STDCALL GetEncodeCharSize(UInt32 ucsCharacter);
   42.64 
   42.65 // Encodes the given UCS character into the given UTF-8 buffer.
   42.66 // Writes the data starting at buffer[offset], and 
   42.67 // increments offset by the number of bytes written.
   42.68 // May write up to 6 bytes, so make sure there's room in the buffer
   42.69 void     OVR_STDCALL EncodeChar(char* pbuffer, SPInt* poffset, UInt32 ucsCharacter);
   42.70 
   42.71 // Return the next Unicode character in the UTF-8 encoded buffer.
   42.72 // Invalid UTF-8 sequences produce a U+FFFD character as output.
   42.73 // Advances *utf8_buffer past the character returned. Pointer advance
   42.74 // occurs even if the terminating 0 character is hit, since that allows
   42.75 // strings with middle '\0' characters to be supported.
   42.76 UInt32   OVR_STDCALL DecodeNextChar_Advance0(const char** putf8Buffer);
   42.77 
   42.78 // Safer version of DecodeNextChar, which doesn't advance pointer if
   42.79 // null character is hit.
   42.80 inline UInt32 DecodeNextChar(const char** putf8Buffer)
   42.81 {
   42.82     UInt32 ch = DecodeNextChar_Advance0(putf8Buffer);
   42.83     if (ch == 0)
   42.84         (*putf8Buffer)--;
   42.85     return ch;
   42.86 }
   42.87 
   42.88 
   42.89 }} // OVR::UTF8Util
   42.90 
   42.91 #endif
   42.92 \ No newline at end of file
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/libovr/Src/OVR_Device.h	Sat Sep 14 16:14:59 2013 +0300
    43.3 @@ -0,0 +1,619 @@
    43.4 +/************************************************************************************
    43.5 +
    43.6 +PublicHeader:   OVR.h
    43.7 +Filename    :   OVR_Device.h
    43.8 +Content     :   Definition of HMD-related Device interfaces
    43.9 +Created     :   September 21, 2012
   43.10 +Authors     :   Michael Antonov
   43.11 +
   43.12 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   43.13 +
   43.14 +Use of this software is subject to the terms of the Oculus license
   43.15 +agreement provided at the time of installation or download, or which
   43.16 +otherwise accompanies this software in either electronic or hard copy form.
   43.17 +
   43.18 +*************************************************************************************/
   43.19 +
   43.20 +#ifndef OVR_Device_h
   43.21 +#define OVR_Device_h
   43.22 +
   43.23 +#include "OVR_DeviceConstants.h"
   43.24 +#include "OVR_DeviceHandle.h"
   43.25 +#include "OVR_DeviceMessages.h"
   43.26 +#include "OVR_HIDDeviceBase.h"
   43.27 +
   43.28 +#include "Kernel/OVR_Atomic.h"
   43.29 +#include "Kernel/OVR_RefCount.h"
   43.30 +#include "Kernel/OVR_String.h"
   43.31 +
   43.32 +namespace OVR {
   43.33 +
   43.34 +// Declared externally
   43.35 +class Profile;
   43.36 +class ProfileManager; // << Should be renamed for consistency
   43.37 +
   43.38 +// Forward declarations
   43.39 +class SensorDevice;
   43.40 +class DeviceCommon;
   43.41 +class DeviceManager;
   43.42 +
   43.43 +// MessageHandler is a base class from which users derive to receive messages,
   43.44 +// its OnMessage handler will be called for messages once it is installed on
   43.45 +// a device. Same message handler can be installed on multiple devices.
   43.46 +class MessageHandler
   43.47 +{
   43.48 +    friend class MessageHandlerImpl;
   43.49 +public:
   43.50 +    MessageHandler();
   43.51 +    virtual ~MessageHandler();
   43.52 +
   43.53 +    // Returns 'true' if handler is currently installed on any devices.
   43.54 +    bool        IsHandlerInstalled() const;
   43.55 +
   43.56 +    // Should be called from derived class destructor to avoid handler
   43.57 +    // being called after it exits.
   43.58 +    void        RemoveHandlerFromDevices();
   43.59 +
   43.60 +    // Returns a pointer to the internal lock object that is locked by a
   43.61 +    // background thread while OnMessage() is called.
   43.62 +    // This lock guaranteed to survive until ~MessageHandler.
   43.63 +    Lock*       GetHandlerLock() const;
   43.64 +
   43.65 +
   43.66 +    virtual void OnMessage(const Message&) { }
   43.67 +
   43.68 +    // Determines if handler supports a specific message type. Can
   43.69 +    // be used to filter out entire message groups. The result
   43.70 +    // returned by this function shouldn't change after handler creation.
   43.71 +    virtual bool SupportsMessageType(MessageType) const { return true; }    
   43.72 +
   43.73 +private:    
   43.74 +    UPInt Internal[4];
   43.75 +};
   43.76 +
   43.77 +
   43.78 +//-------------------------------------------------------------------------------------
   43.79 +// ***** DeviceBase
   43.80 +
   43.81 +// DeviceBase is the base class for all OVR Devices. It provides the following basic
   43.82 +// functionality:
   43.83 +//   - Reports device type, manager, and associated parent (if any).
   43.84 +//   - Supports installable message handlers, which are notified of device events.
   43.85 +//   - Device objects are created through DeviceHandle::CreateDevice or more commonly
   43.86 +//     through DeviceEnumerator<>::CreateDevice.
   43.87 +//   - Created devices are reference counted, starting with RefCount of 1.
   43.88 +//   - Device is resources are cleaned up when it is Released, although its handles
   43.89 +//     may survive longer if referenced.
   43.90 +
   43.91 +class DeviceBase : public NewOverrideBase
   43.92 +{    
   43.93 +    friend class DeviceHandle;  
   43.94 +    friend class DeviceManagerImpl;
   43.95 +public:
   43.96 +
   43.97 +    // Enumerating DeviceBase enumerates all devices.
   43.98 +    enum { EnumDeviceType = Device_All };
   43.99 +
  43.100 +    virtual ~DeviceBase() { }
  43.101 +    virtual void            AddRef();
  43.102 +    virtual void            Release();
  43.103 +    
  43.104 +    virtual DeviceBase*     GetParent() const;
  43.105 +    virtual DeviceManager*  GetManager() const;  
  43.106 +
  43.107 +    virtual void            SetMessageHandler(MessageHandler* handler);
  43.108 +    virtual MessageHandler* GetMessageHandler() const;
  43.109 +
  43.110 +    virtual DeviceType      GetType() const;
  43.111 +    virtual bool            GetDeviceInfo(DeviceInfo* info) const;
  43.112 +
  43.113 +    // returns the MessageHandler's lock
  43.114 +    Lock*                   GetHandlerLock() const;
  43.115 +protected:
  43.116 +    // Internal
  43.117 +    virtual DeviceCommon*   getDeviceCommon() const = 0;
  43.118 +};
  43.119 +
  43.120 +
  43.121 +//-------------------------------------------------------------------------------------
  43.122 +// ***** DeviceInfo
  43.123 +
  43.124 +// DeviceInfo describes a device and its capabilities, obtained by calling
  43.125 +// GetDeviceInfo. This base class only contains device-independent functionality;
  43.126 +// users will normally use a derived HMDInfo or SensorInfo classes for more
  43.127 +// extensive device info.
  43.128 +
  43.129 +class DeviceInfo
  43.130 +{
  43.131 +public:
  43.132 +    DeviceInfo() : InfoClassType(Device_None), Type(Device_None), Version(0)
  43.133 +    {  ProductName[0] = Manufacturer[0] = 0; }
  43.134 +
  43.135 +    enum { MaxNameLength = 32 };
  43.136 +    
  43.137 +    // Type of device for which DeviceInfo is intended.
  43.138 +    // This will be set to Device_HMD for HMDInfo structure, note that this may be
  43.139 +    // different form the actual device type since (Device_None) is valid.
  43.140 +    const DeviceType InfoClassType;
  43.141 +    // Type of device this describes. This must be the same as InfoClassType when
  43.142 +    // InfoClassType != Device_None.
  43.143 +    DeviceType       Type;
  43.144 +    // Name string describing the product: "Oculus Rift DK1", etc.
  43.145 +    char             ProductName[MaxNameLength];    
  43.146 +    char             Manufacturer[MaxNameLength];
  43.147 +    unsigned         Version;
  43.148 +    
  43.149 +protected:
  43.150 +    DeviceInfo(DeviceType type) : InfoClassType(type), Type(type), Version(0)
  43.151 +    { ProductName[0] = Manufacturer[0] = 0; }
  43.152 +    void operator = (const DeviceInfo&) { OVR_ASSERT(0); } // Assignment not allowed.
  43.153 +};
  43.154 +
  43.155 +
  43.156 +//-------------------------------------------------------------------------------------
  43.157 +// DeviceEnumerationArgs provides device enumeration argumenrs for DeviceManager::EnumerateDevicesEx.
  43.158 +class DeviceEnumerationArgs
  43.159 +{
  43.160 +public:
  43.161 +    DeviceEnumerationArgs(DeviceType enumType, bool availableOnly)
  43.162 +        : EnumType(enumType), AvailableOnly(availableOnly)
  43.163 +    { }
  43.164 +
  43.165 +    // Helper; returns true if args match our enumeration criteria.
  43.166 +    bool         MatchRule(DeviceType type, bool available) const
  43.167 +    {
  43.168 +        return ((EnumType == type) || (EnumType == Device_All)) &&
  43.169 +                (available || !AvailableOnly);
  43.170 +    }
  43.171 +
  43.172 +protected:    
  43.173 +    DeviceType   EnumType;
  43.174 +    bool         AvailableOnly;
  43.175 +};
  43.176 +
  43.177 +
  43.178 +// DeviceEnumerator<> is used to enumerate and create devices of specified class,
  43.179 +// it is returned by calling MeviceManager::EnumerateDevices. Initially, the enumerator will
  43.180 +// refer to the first device of specified type. Additional devices can be accessed by
  43.181 +// calling Next().
  43.182 +
  43.183 +template<class T = DeviceBase>
  43.184 +class DeviceEnumerator : public DeviceHandle
  43.185 +{
  43.186 +    friend class DeviceManager;
  43.187 +    friend class DeviceManagerImpl;
  43.188 +public:
  43.189 +    DeviceEnumerator()
  43.190 +        : DeviceHandle(), EnumArgs(Device_None, true) { }
  43.191 +
  43.192 +    // Next advances enumeration to the next device that first criteria.
  43.193 +    // Returns false if no more devices exist that match enumeration criteria.
  43.194 +    bool    Next()          { return enumerateNext(EnumArgs); }
  43.195 +
  43.196 +    // Creates an instance of the device referenced by enumerator; returns null
  43.197 +    // if enumerator does not refer to a valid device or device is unavailable.
  43.198 +    // If device was already created, the same object with incremented ref-count is returned.
  43.199 +    T*      CreateDevice()  { return static_cast<T*>(DeviceHandle::CreateDevice()); }
  43.200 +
  43.201 +protected:
  43.202 +    DeviceEnumerator(const DeviceHandle &dev, const DeviceEnumerationArgs& args)
  43.203 +        : DeviceHandle(dev), EnumArgs(args)
  43.204 +    { }
  43.205 +
  43.206 +    DeviceEnumerationArgs EnumArgs;
  43.207 +};
  43.208 +
  43.209 +//-------------------------------------------------------------------------------------
  43.210 +// ***** DeviceManager
  43.211 +
  43.212 +// DeviceManager maintains and provides access to devices supported by OVR, such as
  43.213 +// HMDs and sensors. A single instance of DeviceManager is normally created at
  43.214 +// program startup, allowing devices to be enumerated and created. DeviceManager is
  43.215 +// reference counted and is AddRefed by its created child devices, causing it to
  43.216 +// always be the last object that is released.
  43.217 +//
  43.218 +// Install MessageHandler on DeviceManager to detect when devices are inserted or removed.
  43.219 +//
  43.220 +// The following code will create the manager and its first available HMDDevice,
  43.221 +// and then release it when not needed:
  43.222 +//
  43.223 +//  DeviceManager* manager = DeviceManager::Create();
  43.224 +//  HMDDevice*     hmd = manager->EnumerateDevices<HMDDevice>().CreateDevice();
  43.225 +//
  43.226 +//  if (hmd) hmd->Release();
  43.227 +//  if (manager) manager->Release();
  43.228 +
  43.229 +
  43.230 +class DeviceManager : public DeviceBase
  43.231 +{
  43.232 +public:
  43.233 +  
  43.234 +    DeviceManager()
  43.235 +    { }
  43.236 +
  43.237 +    // DeviceBase implementation.
  43.238 +    virtual DeviceType      GetType() const     { return Device_Manager; }
  43.239 +    virtual DeviceManager*  GetManager() const  { return const_cast<DeviceManager*>(this); }
  43.240 +
  43.241 +    // Every DeviceManager has an associated profile manager, which us used to store
  43.242 +    // user settings that may affect device behavior. 
  43.243 +    virtual ProfileManager* GetProfileManager() const = 0;
  43.244 +
  43.245 +
  43.246 +    // EnumerateDevices enumerates all of the available devices of the specified class,
  43.247 +    // returning an enumerator that references the first device. An empty enumerator is
  43.248 +    // returned if no devices are available. The following APIs are exposed through
  43.249 +    // DeviceEnumerator:
  43.250 +    //   DeviceEnumerator::GetType()        - Check device type. Returns Device_None 
  43.251 +    //                                        if no device was found/pointed to.
  43.252 +    //   DeviceEnumerator::GetDeviceInfo()  - Get more information on device.
  43.253 +    //   DeviceEnumerator::CreateDevice()   - Create an instance of device.
  43.254 +    //   DeviceEnumerator::Next()           - Move onto next device.
  43.255 +    template<class D>
  43.256 +    DeviceEnumerator<D>     EnumerateDevices(bool availableOnly = true)
  43.257 +    {
  43.258 +        // TBD: A cleaner (but less efficient) alternative is though enumeratorFromHandle.
  43.259 +        DeviceEnumerator<> e = EnumerateDevicesEx(DeviceEnumerationArgs((DeviceType)D::EnumDeviceType, availableOnly));
  43.260 +        return *reinterpret_cast<DeviceEnumerator<D>*>(&e);
  43.261 +    }
  43.262 +  
  43.263 +    // EnumerateDevicesEx provides internal implementation for device enumeration, enumerating
  43.264 +    // devices based on dynamically specified DeviceType in DeviceEnumerationArgs.
  43.265 +    // End users should call DeumerateDevices<>() instead.
  43.266 +    virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args) = 0;
  43.267 +
  43.268 +    // Creates a new DeviceManager. Only one instance of DeviceManager should be created at a time.
  43.269 +    static   DeviceManager* Create();
  43.270 +
  43.271 +    // Static constant for this device type, used in template cast type checks.
  43.272 +    enum { EnumDeviceType = Device_Manager };
  43.273 +
  43.274 +
  43.275 +
  43.276 +    // Adds a device (DeviceCreateDesc*) into Devices. Returns NULL, 
  43.277 +    // if unsuccessful or device is already in the list.
  43.278 +    virtual Ptr<DeviceCreateDesc> AddDevice_NeedsLock(const DeviceCreateDesc& createDesc) = 0;
  43.279 +
  43.280 +protected:
  43.281 +    DeviceEnumerator<> enumeratorFromHandle(const DeviceHandle& h, const DeviceEnumerationArgs& args)
  43.282 +    { return DeviceEnumerator<>(h, args); }
  43.283 +
  43.284 +    DeviceManager* getThis() { return this; }
  43.285 +};
  43.286 +
  43.287 +
  43.288 +
  43.289 +//-------------------------------------------------------------------------------------
  43.290 +// ***** HMDInfo 
  43.291 +
  43.292 +// This structure describes various aspects of the HMD allowing us to configure rendering.
  43.293 +//
  43.294 +//  Currently included data:
  43.295 +//   - Physical screen dimensions, resolution, and eye distances.
  43.296 +//     (some of these will be configurable with a tool in the future).
  43.297 +//     These arguments allow us to properly setup projection across HMDs.
  43.298 +//   - DisplayDeviceName for identifying HMD screen; system-specific interpretation.
  43.299 +//
  43.300 +// TBD:
  43.301 +//  - Power on/ off?
  43.302 +//  - Sensor rates and capabilities
  43.303 +//  - Distortion radius/variables    
  43.304 +//  - Screen update frequency
  43.305 +//  - Distortion needed flag
  43.306 +//  - Update modes:
  43.307 +//      Set update mode: Stereo (both sides together), mono (same in both eyes),
  43.308 +//                       Alternating, Alternating scan-lines.
  43.309 +
  43.310 +class HMDInfo : public DeviceInfo
  43.311 +{
  43.312 +public:
  43.313 +    // Size of the entire screen, in pixels.
  43.314 +    unsigned  HResolution, VResolution; 
  43.315 +    // Physical dimensions of the active screen in meters. Can be used to calculate
  43.316 +    // projection center while considering IPD.
  43.317 +    float     HScreenSize, VScreenSize;
  43.318 +    // Physical offset from the top of the screen to the eye center, in meters.
  43.319 +    // This will usually, but not necessarily be half of VScreenSize.
  43.320 +    float     VScreenCenter;
  43.321 +    // Distance from the eye to screen surface, in meters.
  43.322 +    // Useful for calculating FOV and projection.
  43.323 +    float     EyeToScreenDistance;
  43.324 +    // Distance between physical lens centers useful for calculating distortion center.
  43.325 +    float     LensSeparationDistance;
  43.326 +    // Configured distance between the user's eye centers, in meters. Defaults to 0.064.
  43.327 +    float     InterpupillaryDistance;
  43.328 +    
  43.329 +    // Radial distortion correction coefficients.
  43.330 +    // The distortion assumes that the input texture coordinates will be scaled
  43.331 +    // by the following equation:    
  43.332 +    //   uvResult = uvInput * (K0 + K1 * uvLength^2 + K2 * uvLength^4)
  43.333 +    // Where uvInput is the UV vector from the center of distortion in direction
  43.334 +    // of the mapped pixel, uvLength is the magnitude of that vector, and uvResult
  43.335 +    // the corresponding location after distortion.
  43.336 +    float     DistortionK[4];
  43.337 +
  43.338 +    float     ChromaAbCorrection[4];
  43.339 +
  43.340 +    // Desktop coordinate position of the screen (can be negative; may not be present on all platforms)
  43.341 +    int       DesktopX, DesktopY;
  43.342 +    
  43.343 +    // Windows:
  43.344 +    // "\\\\.\\DISPLAY3", etc. Can be used in EnumDisplaySettings/CreateDC.
  43.345 +    char      DisplayDeviceName[32];
  43.346 +    
  43.347 +    // MacOS:
  43.348 +    long      DisplayId;
  43.349 +
  43.350 +
  43.351 +    HMDInfo()
  43.352 +        : DeviceInfo(Device_HMD),          
  43.353 +          HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0),
  43.354 +          VScreenCenter(0), EyeToScreenDistance(0),
  43.355 +          LensSeparationDistance(0), InterpupillaryDistance(0),
  43.356 +          DesktopX(0), DesktopY(0), DisplayId(0)
  43.357 +    {
  43.358 +        DisplayDeviceName[0] = 0;
  43.359 +        memset(DistortionK, 0, sizeof(DistortionK));
  43.360 +        DistortionK[0] = 1;
  43.361 +        ChromaAbCorrection[0] = ChromaAbCorrection[2] = 1;
  43.362 +        ChromaAbCorrection[1] = ChromaAbCorrection[3] = 0;
  43.363 +    }
  43.364 +
  43.365 +    // Operator = copies local fields only (base class must be correct already)
  43.366 +    void operator = (const HMDInfo& src)
  43.367 +    {        
  43.368 +        HResolution             = src.HResolution;
  43.369 +        VResolution             = src.VResolution;
  43.370 +        HScreenSize             = src.HScreenSize;
  43.371 +        VScreenSize             = src.VScreenSize;
  43.372 +        VScreenCenter           = src.VScreenCenter;
  43.373 +        EyeToScreenDistance     = src.EyeToScreenDistance;
  43.374 +        LensSeparationDistance  = src.LensSeparationDistance;
  43.375 +        InterpupillaryDistance  = src.InterpupillaryDistance;
  43.376 +        DistortionK[0]          = src.DistortionK[0];
  43.377 +        DistortionK[1]          = src.DistortionK[1];
  43.378 +        DistortionK[2]          = src.DistortionK[2];
  43.379 +        DistortionK[3]          = src.DistortionK[3];
  43.380 +        ChromaAbCorrection[0]   = src.ChromaAbCorrection[0];
  43.381 +        ChromaAbCorrection[1]   = src.ChromaAbCorrection[1];
  43.382 +        ChromaAbCorrection[2]   = src.ChromaAbCorrection[2];
  43.383 +        ChromaAbCorrection[3]   = src.ChromaAbCorrection[3];
  43.384 +        DesktopX                = src.DesktopX;
  43.385 +        DesktopY                = src.DesktopY;
  43.386 +        memcpy(DisplayDeviceName, src.DisplayDeviceName, sizeof(DisplayDeviceName));
  43.387 +        DisplayId               = src.DisplayId;
  43.388 +    }
  43.389 +
  43.390 +    bool IsSameDisplay(const HMDInfo& o) const
  43.391 +    {
  43.392 +        return DisplayId == o.DisplayId &&
  43.393 +               String::CompareNoCase(DisplayDeviceName, 
  43.394 +                                     o.DisplayDeviceName) == 0;
  43.395 +    }
  43.396 +
  43.397 +};
  43.398 +
  43.399 +
  43.400 +// HMDDevice represents an Oculus HMD device unit. An instance of this class
  43.401 +// is typically created from the DeviceManager.
  43.402 +//  After HMD device is created, we its sensor data can be obtained by 
  43.403 +//  first creating a Sensor object and then.
  43.404 +
  43.405 +//  TBD:
  43.406 +//  - Configure Sensor
  43.407 +//  - APIs to set On-Screen message, other states?
  43.408 +
  43.409 +class HMDDevice : public DeviceBase
  43.410 +{
  43.411 +public:
  43.412 +    HMDDevice()
  43.413 +    { }
  43.414 +
  43.415 +    // Static constant for this device type, used in template cast type checks.
  43.416 +    enum { EnumDeviceType = Device_HMD };
  43.417 +
  43.418 +    virtual DeviceType      GetType() const   { return Device_HMD; }  
  43.419 +
  43.420 +    // Creates a sensor associated with this HMD.
  43.421 +    virtual SensorDevice*   GetSensor() = 0;
  43.422 +
  43.423 +
  43.424 +    // Requests the currently used profile. This profile affects the
  43.425 +    // settings reported by HMDInfo. 
  43.426 +    virtual Profile*    GetProfile() const = 0;
  43.427 +    // Obtains the currently used profile name. This is initialized to the default
  43.428 +    // profile name, if any; it can then be changed per-device by SetProfileName.    
  43.429 +    virtual const char* GetProfileName() const = 0;
  43.430 +    // Sets the profile user name, changing the data returned by GetProfileInfo.
  43.431 +    virtual bool        SetProfileName(const char* name) = 0;
  43.432 +
  43.433 +
  43.434 +    // Disconnects from real HMD device. This HMDDevice remains as 'fake' HMD.
  43.435 +    // SensorDevice ptr is used to restore the 'fake' HMD (can be NULL).
  43.436 +    HMDDevice*  Disconnect(SensorDevice*);
  43.437 +    
  43.438 +    // Returns 'true' if HMD device is a 'fake' HMD (was created this way or 
  43.439 +    // 'Disconnect' method was called).
  43.440 +    bool        IsDisconnected() const;
  43.441 +};
  43.442 +
  43.443 +
  43.444 +//-------------------------------------------------------------------------------------
  43.445 +// ***** SensorRange & SensorInfo
  43.446 +
  43.447 +// SensorRange specifies maximum value ranges that SensorDevice hardware is configured
  43.448 +// to detect. Although this range doesn't affect the scale of MessageBodyFrame values,
  43.449 +// physical motions whose positive or negative magnitude is outside the specified range
  43.450 +// may get clamped or misreported. Setting lower values may result in higher precision
  43.451 +// tracking.
  43.452 +struct SensorRange
  43.453 +{
  43.454 +    SensorRange(float maxAcceleration = 0.0f, float maxRotationRate = 0.0f,
  43.455 +                float maxMagneticField = 0.0f)
  43.456 +        : MaxAcceleration(maxAcceleration), MaxRotationRate(maxRotationRate),
  43.457 +          MaxMagneticField(maxMagneticField)
  43.458 +    { }
  43.459 +
  43.460 +    // Maximum detected acceleration in m/s^2. Up to 8*G equivalent support guaranteed,
  43.461 +    // where G is ~9.81 m/s^2.
  43.462 +    // Oculus DK1 HW has thresholds near: 2, 4 (default), 8, 16 G.
  43.463 +    float   MaxAcceleration;  
  43.464 +    // Maximum detected angular velocity in rad/s. Up to 8*Pi support guaranteed.
  43.465 +    // Oculus DK1 HW thresholds near: 1, 2, 4, 8 Pi (default).
  43.466 +    float   MaxRotationRate;
  43.467 +    // Maximum detectable Magnetic field strength in Gauss. Up to 2.5 Gauss support guaranteed.
  43.468 +    // Oculus DK1 HW thresholds near: 0.88, 1.3, 1.9, 2.5 gauss.
  43.469 +    float   MaxMagneticField;
  43.470 +};
  43.471 +
  43.472 +// SensorInfo describes capabilities of the sensor device.
  43.473 +class SensorInfo : public DeviceInfo
  43.474 +{
  43.475 +public:
  43.476 +    SensorInfo() : DeviceInfo(Device_Sensor), VendorId(0), ProductId(0)
  43.477 +    {
  43.478 +        SerialNumber[0] = 0;
  43.479 +    }
  43.480 +
  43.481 +    // HID Vendor and ProductId of the device.
  43.482 +    UInt16      VendorId;
  43.483 +    UInt16      ProductId;
  43.484 +    // MaxRanges report maximum sensor range values supported by HW.
  43.485 +    SensorRange MaxRanges;
  43.486 +    // Sensor (and display) serial number.
  43.487 +    char        SerialNumber[20];
  43.488 +
  43.489 +private:
  43.490 +    void operator = (const SensorInfo&) { OVR_ASSERT(0); } // Assignment not allowed.
  43.491 +};
  43.492 +
  43.493 +
  43.494 +//-------------------------------------------------------------------------------------
  43.495 +// ***** SensorDevice
  43.496 +
  43.497 +// SensorDevice is an interface to sensor data.
  43.498 +// Install a MessageHandler of SensorDevice instance to receive MessageBodyFrame
  43.499 +// notifications.
  43.500 +//
  43.501 +// TBD: Add Polling API? More HID interfaces?
  43.502 +
  43.503 +class SensorDevice : public HIDDeviceBase, public DeviceBase
  43.504 +{
  43.505 +public:
  43.506 +    SensorDevice() 
  43.507 +    { }
  43.508 +
  43.509 +    // Static constant for this device type, used in template cast type checks.
  43.510 +    enum { EnumDeviceType = Device_Sensor };
  43.511 +
  43.512 +    virtual DeviceType GetType() const   { return Device_Sensor; }
  43.513 +
  43.514 +    
  43.515 +    // CoordinateFrame defines whether messages come in the coordinate frame
  43.516 +    // of the sensor device or HMD, which has a different internal sensor.
  43.517 +    // Sensors obtained form the HMD will automatically use HMD coordinates.
  43.518 +    enum CoordinateFrame
  43.519 +    {
  43.520 +        Coord_Sensor = 0,
  43.521 +        Coord_HMD    = 1
  43.522 +    };
  43.523 +
  43.524 +    virtual void            SetCoordinateFrame(CoordinateFrame coordframe) = 0;
  43.525 +    virtual CoordinateFrame GetCoordinateFrame() const = 0;
  43.526 +
  43.527 +    // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call). 
  43.528 +    // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be 
  43.529 +    // called twice or thrice at the same 'tick'. 
  43.530 +    // If the rate is  < 333 then the OnMessage / MessageBodyFrame will be called three
  43.531 +    // times for each 'tick': the first call will contain averaged values, the second
  43.532 +    // and third calls will provide with most recent two recorded samples.
  43.533 +    virtual void        SetReportRate(unsigned rateHz) = 0;
  43.534 +    // Returns currently set report rate, in Hz. If 0 - error occurred.
  43.535 +    // Note, this value may be different from the one provided for SetReportRate. The return
  43.536 +    // value will contain the actual rate.
  43.537 +    virtual unsigned    GetReportRate() const = 0;
  43.538 +
  43.539 +    // Sets maximum range settings for the sensor described by SensorRange.    
  43.540 +    // The function will fail if you try to pass values outside Maximum supported
  43.541 +    // by the HW, as described by SensorInfo.
  43.542 +    // Pass waitFlag == true to wait for command completion. For waitFlag == true,
  43.543 +    // returns true if the range was applied successfully (no HW error).
  43.544 +    // For waitFlag = false, return 'true' means that command was enqueued successfully.
  43.545 +    virtual bool       SetRange(const SensorRange& range, bool waitFlag = false) = 0;
  43.546 +
  43.547 +    // Return the current sensor range settings for the device. These may not exactly
  43.548 +    // match the values applied through SetRange.
  43.549 +    virtual void       GetRange(SensorRange* range) const = 0;
  43.550 +};
  43.551 +
  43.552 +//-------------------------------------------------------------------------------------
  43.553 +// ***** LatencyTestConfiguration
  43.554 +// LatencyTestConfiguration specifies configuration information for the Oculus Latency Tester device.
  43.555 +struct LatencyTestConfiguration
  43.556 +{
  43.557 +    LatencyTestConfiguration(const Color& threshold, bool sendSamples = false)
  43.558 +        : Threshold(threshold), SendSamples(sendSamples) 
  43.559 +    {
  43.560 +    }
  43.561 +
  43.562 +    // The color threshold for triggering a detected display change.
  43.563 +    Color    Threshold;
  43.564 +    // Flag specifying whether we wish to receive a stream of color values from the sensor.
  43.565 +    bool        SendSamples;
  43.566 +};
  43.567 +
  43.568 +//-------------------------------------------------------------------------------------
  43.569 +// ***** LatencyTestDisplay
  43.570 +// LatencyTestDisplay sets the mode and contents of the Latency Tester LED display.
  43.571 +// See the 'Latency Tester Specification' document for more details.
  43.572 +struct LatencyTestDisplay
  43.573 +{
  43.574 +    LatencyTestDisplay(UByte mode, UInt32 value)
  43.575 +        : Mode(mode), Value(value)
  43.576 +    {
  43.577 +    }
  43.578 +
  43.579 +    UByte       Mode;       // The display mode that we wish to select.
  43.580 +    UInt32      Value;      // The value to display.
  43.581 +};
  43.582 +
  43.583 +//-------------------------------------------------------------------------------------
  43.584 +// ***** LatencyTestDevice
  43.585 +
  43.586 +// LatencyTestDevice provides an interface to the Oculus Latency Tester which is used to test 'motion to photon' latency.
  43.587 +class LatencyTestDevice : public HIDDeviceBase, public DeviceBase
  43.588 +{
  43.589 +public:
  43.590 +    LatencyTestDevice()
  43.591 +    { }
  43.592 +
  43.593 +    // Static constant for this device type, used in template cast type checks.
  43.594 +    enum { EnumDeviceType = Device_LatencyTester };
  43.595 +
  43.596 +    virtual DeviceType GetType() const { return Device_LatencyTester; }
  43.597 +
  43.598 +    // Specifies configuration information including the threshold for triggering a detected color change,
  43.599 +    // and a flag to enable a stream of sensor values (typically used for debugging).
  43.600 +    virtual bool SetConfiguration(const LatencyTestConfiguration& configuration, bool waitFlag = false) = 0;
  43.601 +
  43.602 +    // Get configuration information from device.
  43.603 +    virtual bool GetConfiguration(LatencyTestConfiguration* configuration) = 0;
  43.604 +
  43.605 +    // Used to calibrate the latency tester at the start of a test. Display the specified color on the screen
  43.606 +    // beneath the latency tester and then call this method. Calibration information is lost
  43.607 +    // when power is removed from the device.
  43.608 +    virtual bool SetCalibrate(const Color& calibrationColor, bool waitFlag = false) = 0;
  43.609 +
  43.610 +    // Triggers the start of a measurement. This starts the millisecond timer on the device and 
  43.611 +    // causes it to respond with the 'MessageLatencyTestStarted' message.
  43.612 +    virtual bool SetStartTest(const Color& targetColor, bool waitFlag = false) = 0;
  43.613 +
  43.614 +    // Used to set the value displayed on the LED display panel.
  43.615 +    virtual bool SetDisplay(const LatencyTestDisplay& display, bool waitFlag = false) = 0;
  43.616 +
  43.617 +    virtual DeviceBase* GetDevice() { return this; }
  43.618 +};
  43.619 +
  43.620 +} // namespace OVR
  43.621 +
  43.622 +#endif
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/libovr/Src/OVR_DeviceConstants.h	Sat Sep 14 16:14:59 2013 +0300
    44.3 @@ -0,0 +1,38 @@
    44.4 +/************************************************************************************
    44.5 +
    44.6 +PublicHeader:   OVR.h
    44.7 +Filename    :   OVR_DeviceConstants.h
    44.8 +Content     :   Device constants
    44.9 +Created     :   February 5, 2013
   44.10 +Authors     :   Lee Cooper
   44.11 +
   44.12 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   44.13 +
   44.14 +Use of this software is subject to the terms of the Oculus license
   44.15 +agreement provided at the time of installation or download, or which
   44.16 +otherwise accompanies this software in either electronic or hard copy form.
   44.17 +
   44.18 +*************************************************************************************/
   44.19 +
   44.20 +#ifndef OVR_DeviceConstants_h
   44.21 +#define OVR_DeviceConstants_h
   44.22 +
   44.23 +namespace OVR {
   44.24 +
   44.25 +
   44.26 +//-------------------------------------------------------------------------------------
   44.27 +// Different device types supported by OVR; this type is reported by DeviceBase::GetType.
   44.28 +// 
   44.29 +enum DeviceType
   44.30 +{
   44.31 +    Device_None             = 0,
   44.32 +    Device_Manager          = 1,
   44.33 +    Device_HMD              = 2,
   44.34 +    Device_Sensor           = 3,
   44.35 +    Device_LatencyTester    = 4,
   44.36 +    Device_All              = 0xFF // Set for enumeration only, to enumerate all device types.
   44.37 +};
   44.38 +
   44.39 +} // namespace OVR
   44.40 +
   44.41 +#endif
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/libovr/Src/OVR_DeviceHandle.cpp	Sat Sep 14 16:14:59 2013 +0300
    45.3 @@ -0,0 +1,174 @@
    45.4 +/************************************************************************************
    45.5 +
    45.6 +Filename    :   OVR_DeviceHandle.cpp
    45.7 +Content     :   Implementation of device handle class
    45.8 +Created     :   February 5, 2013
    45.9 +Authors     :   Lee Cooper
   45.10 +
   45.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   45.12 +
   45.13 +Use of this software is subject to the terms of the Oculus license
   45.14 +agreement provided at the time of installation or download, or which
   45.15 +otherwise accompanies this software in either electronic or hard copy form.
   45.16 +
   45.17 +*************************************************************************************/
   45.18 +
   45.19 +#include "OVR_DeviceHandle.h"
   45.20 +
   45.21 +#include "OVR_DeviceImpl.h"
   45.22 +
   45.23 +namespace OVR {
   45.24 +
   45.25 +//-------------------------------------------------------------------------------------
   45.26 +// ***** DeviceHandle
   45.27 +
   45.28 +DeviceHandle::DeviceHandle(DeviceCreateDesc* impl) : pImpl(impl)
   45.29 +{
   45.30 +    if (pImpl)
   45.31 +        pImpl->AddRef();
   45.32 +}
   45.33 +
   45.34 +DeviceHandle::DeviceHandle(const DeviceHandle& src) : pImpl(src.pImpl)
   45.35 +{
   45.36 +    if (pImpl)
   45.37 +        pImpl->AddRef();
   45.38 +}    
   45.39 +
   45.40 +DeviceHandle::~DeviceHandle()
   45.41 +{
   45.42 +    if (pImpl)
   45.43 +        pImpl->Release();
   45.44 +}
   45.45 +
   45.46 +void DeviceHandle::operator = (const DeviceHandle& src)
   45.47 +{
   45.48 +    if (src.pImpl)
   45.49 +        src.pImpl->AddRef();
   45.50 +    if (pImpl)
   45.51 +        pImpl->Release();
   45.52 +    pImpl = src.pImpl;
   45.53 +}
   45.54 +
   45.55 +DeviceBase* DeviceHandle::GetDevice_AddRef() const
   45.56 +{ 
   45.57 +    if (pImpl && pImpl->pDevice)
   45.58 +    {
   45.59 +        pImpl->pDevice->AddRef();
   45.60 +        return pImpl->pDevice;
   45.61 +    }
   45.62 +    return NULL;
   45.63 +}
   45.64 +
   45.65 +// Returns true, if the handle contains the same device ptr
   45.66 +// as specified in the parameter.
   45.67 +bool DeviceHandle::IsDevice(DeviceBase* pdev) const
   45.68 +{
   45.69 +    return (pdev && pImpl && pImpl->pDevice) ? 
   45.70 +        pImpl->pDevice == pdev : false;
   45.71 +}
   45.72 +
   45.73 +DeviceType  DeviceHandle::GetType() const
   45.74 +{
   45.75 +    return pImpl ? pImpl->Type : Device_None;
   45.76 +}
   45.77 +
   45.78 +bool DeviceHandle::GetDeviceInfo(DeviceInfo* info) const
   45.79 +{
   45.80 +    return pImpl ? pImpl->GetDeviceInfo(info) : false;
   45.81 +}
   45.82 +bool DeviceHandle::IsAvailable() const
   45.83 +{
   45.84 +    // This isn't "atomically safe", but the function only returns the
   45.85 +    // recent state that may change.
   45.86 +    return pImpl ? (pImpl->Enumerated && pImpl->pLock->pManager) : false;
   45.87 +}
   45.88 +
   45.89 +bool DeviceHandle::IsCreated() const
   45.90 +{
   45.91 +    return pImpl ? (pImpl->pDevice != 0) : false;
   45.92 +}
   45.93 +
   45.94 +DeviceBase* DeviceHandle::CreateDevice()
   45.95 +{       
   45.96 +    if (!pImpl)
   45.97 +        return 0;
   45.98 +    
   45.99 +    DeviceBase*            device = 0;
  45.100 +    Ptr<DeviceManagerImpl> manager= 0;
  45.101 +
  45.102 +    // Since both manager and device pointers can only be destroyed during a lock,
  45.103 +    // hold it while checking for availability.
  45.104 +    // AddRef to manager so that it doesn't get released on us.
  45.105 +    {
  45.106 +        Lock::Locker deviceLockScope(pImpl->GetLock());
  45.107 +
  45.108 +        if (pImpl->pDevice)
  45.109 +        {
  45.110 +            pImpl->pDevice->AddRef();
  45.111 +            return pImpl->pDevice;
  45.112 +        }
  45.113 +        manager = pImpl->GetManagerImpl();
  45.114 +    }
  45.115 +
  45.116 +    if (manager)
  45.117 +    {
  45.118 +        if (manager->GetThreadId() != OVR::GetCurrentThreadId())
  45.119 +        {
  45.120 +            // Queue up a CreateDevice request. This fills in '&device' with AddRefed value,
  45.121 +            // or keep it at null.
  45.122 +            manager->GetThreadQueue()->PushCallAndWaitResult(
  45.123 +                manager.GetPtr(), &DeviceManagerImpl::CreateDevice_MgrThread,
  45.124 +                &device, pImpl, (DeviceBase*)0);
  45.125 +        }
  45.126 +        else
  45.127 +            device = manager->CreateDevice_MgrThread(pImpl, (DeviceBase*)0);
  45.128 +    }
  45.129 +    return device;
  45.130 +}
  45.131 +
  45.132 +void DeviceHandle::Clear()
  45.133 +{
  45.134 +    if (pImpl)
  45.135 +    {
  45.136 +        pImpl->Release();
  45.137 +        pImpl = 0;
  45.138 +    }
  45.139 +}
  45.140 +
  45.141 +bool DeviceHandle::enumerateNext(const DeviceEnumerationArgs& args)
  45.142 +{
  45.143 +    if (GetType() == Device_None)
  45.144 +        return false;
  45.145 +    
  45.146 +    Ptr<DeviceManagerImpl> managerKeepAlive;
  45.147 +    Lock::Locker           lockScope(pImpl->GetLock());
  45.148 +    
  45.149 +    DeviceCreateDesc* next = pImpl;
  45.150 +    // If manager was destroyed, we get removed from the list.
  45.151 +    if (!pImpl->pNext)
  45.152 +        return false;
  45.153 +
  45.154 +    managerKeepAlive = next->GetManagerImpl();
  45.155 +    OVR_ASSERT(managerKeepAlive);
  45.156 +    
  45.157 +    do {
  45.158 +        next = next->pNext;
  45.159 +
  45.160 +        if (managerKeepAlive->Devices.IsNull(next))
  45.161 +        {
  45.162 +            pImpl->Release();
  45.163 +            pImpl = 0;
  45.164 +            return false;
  45.165 +        }
  45.166 +
  45.167 +    } while(!args.MatchRule(next->Type, next->Enumerated));
  45.168 +
  45.169 +    next->AddRef();
  45.170 +    pImpl->Release();
  45.171 +    pImpl = next;
  45.172 +
  45.173 +    return true;
  45.174 +}
  45.175 +
  45.176 +} // namespace OVR
  45.177 +
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/libovr/Src/OVR_DeviceHandle.h	Sat Sep 14 16:14:59 2013 +0300
    46.3 @@ -0,0 +1,97 @@
    46.4 +/************************************************************************************
    46.5 +
    46.6 +PublicHeader:   OVR.h
    46.7 +Filename    :   OVR_DeviceHandle.h
    46.8 +Content     :   Handle to a device that was enumerated
    46.9 +Created     :   February 5, 2013
   46.10 +Authors     :   Lee Cooper
   46.11 +
   46.12 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   46.13 +
   46.14 +Use of this software is subject to the terms of the Oculus license
   46.15 +agreement provided at the time of installation or download, or which
   46.16 +otherwise accompanies this software in either electronic or hard copy form.
   46.17 +
   46.18 +*************************************************************************************/
   46.19 +
   46.20 +#ifndef OVR_DeviceHandle_h
   46.21 +#define OVR_DeviceHandle_h
   46.22 +
   46.23 +#include "OVR_DeviceConstants.h"
   46.24 +
   46.25 +namespace OVR {
   46.26 +
   46.27 +class DeviceBase;
   46.28 +class DeviceInfo;
   46.29 +
   46.30 +// Internal
   46.31 +class DeviceCreateDesc;
   46.32 +class DeviceEnumerationArgs;
   46.33 +
   46.34 +
   46.35 +//-------------------------------------------------------------------------------------
   46.36 +// ***** DeviceHandle
   46.37 +
   46.38 +// DeviceHandle references a specific device that was enumerated; it can be assigned
   46.39 +// directly from DeviceEnumerator.
   46.40 +//
   46.41 +// Devices represented by DeviceHandle are not necessarily created or available.
   46.42 +// A device may become unavailable if, for example, it its unplugged. If the device
   46.43 +// is available, it can be created by calling CreateDevice.
   46.44 +//
   46.45 +
   46.46 +class DeviceHandle
   46.47 +{    
   46.48 +	friend class DeviceManager;
   46.49 +	friend class DeviceManagerImpl;
   46.50 +    template<class B> friend class HIDDeviceImpl;
   46.51 +
   46.52 +public:
   46.53 +	DeviceHandle() : pImpl(0) { }    
   46.54 +	DeviceHandle(const DeviceHandle& src);
   46.55 +	~DeviceHandle();
   46.56 +
   46.57 +	void operator = (const DeviceHandle& src);
   46.58 +
   46.59 +	bool operator == (const DeviceHandle& other) const { return pImpl == other.pImpl; }
   46.60 +	bool operator != (const DeviceHandle& other) const { return pImpl != other.pImpl; }
   46.61 +
   46.62 +	// operator bool() returns true if Handle/Enumerator points to a valid device.
   46.63 +	operator bool () const   { return GetType() != Device_None; }
   46.64 +
   46.65 +    // Returns existing device, or NULL if !IsCreated. The returned ptr is 
   46.66 +    // addref-ed.
   46.67 +    DeviceBase* GetDevice_AddRef() const;
   46.68 +	DeviceType  GetType() const;
   46.69 +	bool        GetDeviceInfo(DeviceInfo* info) const;
   46.70 +	bool        IsAvailable() const;
   46.71 +	bool        IsCreated() const;
   46.72 +    // Returns true, if the handle contains the same device ptr
   46.73 +    // as specified in the parameter.
   46.74 +    bool        IsDevice(DeviceBase*) const;
   46.75 +
   46.76 +	// Creates a device, or returns AddRefed pointer if one is already created.
   46.77 +	// New devices start out with RefCount of 1.
   46.78 +	DeviceBase* CreateDevice();
   46.79 +
   46.80 +    // Creates a device, or returns AddRefed pointer if one is already created.
   46.81 +    // New devices start out with RefCount of 1. DeviceT is used to cast the
   46.82 +    // DeviceBase* to a concreete type.
   46.83 +    template <class DeviceT>
   46.84 +    DeviceT* CreateDeviceTyped() const
   46.85 +    {
   46.86 +        return static_cast<DeviceT*>(DeviceHandle(*this).CreateDevice());
   46.87 +    }
   46.88 +
   46.89 +	// Resets the device handle to uninitialized state.
   46.90 +	void        Clear();
   46.91 +
   46.92 +protected:
   46.93 +	explicit DeviceHandle(DeviceCreateDesc* impl);
   46.94 +	bool     enumerateNext(const DeviceEnumerationArgs& args);
   46.95 +	DeviceCreateDesc* pImpl;
   46.96 +};
   46.97 +
   46.98 +} // namespace OVR
   46.99 +
  46.100 +#endif
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/libovr/Src/OVR_DeviceImpl.cpp	Sat Sep 14 16:14:59 2013 +0300
    47.3 @@ -0,0 +1,790 @@
    47.4 +/************************************************************************************
    47.5 +
    47.6 +Filename    :   OVR_DeviceImpl.h
    47.7 +Content     :   Partial back-end independent implementation of Device interfaces
    47.8 +Created     :   October 10, 2012
    47.9 +Authors     :   Michael Antonov
   47.10 +
   47.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   47.12 +
   47.13 +Use of this software is subject to the terms of the Oculus license
   47.14 +agreement provided at the time of installation or download, or which
   47.15 +otherwise accompanies this software in either electronic or hard copy form.
   47.16 +
   47.17 +*************************************************************************************/
   47.18 +
   47.19 +#include "OVR_DeviceImpl.h"
   47.20 +#include "Kernel/OVR_Atomic.h"
   47.21 +#include "Kernel/OVR_Log.h"
   47.22 +#include "Kernel/OVR_System.h"
   47.23 +
   47.24 +#include "OVR_DeviceImpl.h"
   47.25 +#include "OVR_SensorImpl.h"
   47.26 +#include "OVR_Profile.h"
   47.27 +
   47.28 +namespace OVR {
   47.29 +
   47.30 +
   47.31 +//-------------------------------------------------------------------------------------
   47.32 +// ***** SharedLock
   47.33 +
   47.34 +// This is a general purpose globally shared Lock implementation that should probably be
   47.35 +// moved to Kernel.
   47.36 +// May in theory busy spin-wait if we hit contention on first lock creation,
   47.37 +// but this shouldn't matter in practice since Lock* should be cached.
   47.38 +
   47.39 +
   47.40 +enum { LockInitMarker = 0xFFFFFFFF };
   47.41 +
   47.42 +Lock* SharedLock::GetLockAddRef()
   47.43 +{
   47.44 +    int oldUseCount;
   47.45 +
   47.46 +    do {
   47.47 +        oldUseCount = UseCount;
   47.48 +        if (oldUseCount == LockInitMarker)
   47.49 +            continue;
   47.50 +
   47.51 +        if (oldUseCount == 0)
   47.52 +        {
   47.53 +            // Initialize marker
   47.54 +            if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 0, LockInitMarker))
   47.55 +            {
   47.56 +                Construct<Lock>(Buffer);
   47.57 +                do { }
   47.58 +                while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 1));
   47.59 +                return toLock();
   47.60 +            }
   47.61 +            continue;
   47.62 +        }
   47.63 +
   47.64 +    } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount + 1));
   47.65 +
   47.66 +    return toLock();
   47.67 +}
   47.68 +
   47.69 +void SharedLock::ReleaseLock(Lock* plock)
   47.70 +{
   47.71 +    OVR_UNUSED(plock);
   47.72 +    OVR_ASSERT(plock == toLock());
   47.73 +
   47.74 +    int oldUseCount;
   47.75 +
   47.76 +    do {
   47.77 +        oldUseCount = UseCount;
   47.78 +        OVR_ASSERT(oldUseCount != LockInitMarker);
   47.79 +
   47.80 +        if (oldUseCount == 1)
   47.81 +        {
   47.82 +            // Initialize marker
   47.83 +            if (AtomicOps<int>::CompareAndSet_Sync(&UseCount, 1, LockInitMarker))
   47.84 +            {
   47.85 +                Destruct<Lock>(toLock());
   47.86 +
   47.87 +                do { }
   47.88 +                while (!AtomicOps<int>::CompareAndSet_Sync(&UseCount, LockInitMarker, 0));
   47.89 +
   47.90 +                return;
   47.91 +            }
   47.92 +            continue;
   47.93 +        }
   47.94 +
   47.95 +    } while (!AtomicOps<int>::CompareAndSet_NoSync(&UseCount, oldUseCount, oldUseCount - 1));
   47.96 +}
   47.97 +
   47.98 +
   47.99 +
  47.100 +//-------------------------------------------------------------------------------------
  47.101 +// ***** MessageHandler
  47.102 +
  47.103 +// Threading notes:
  47.104 +// The OnMessage() handler and SetMessageHandler are currently synchronized
  47.105 +// through a separately stored shared Lock object to avoid calling the handler 
  47.106 +// from background thread while it's being removed.
  47.107 +
  47.108 +static SharedLock MessageHandlerSharedLock;
  47.109 +
  47.110 +
  47.111 +class MessageHandlerImpl
  47.112 +{
  47.113 +public:
  47.114 +    MessageHandlerImpl()
  47.115 +        : pLock(MessageHandlerSharedLock.GetLockAddRef())
  47.116 +    {
  47.117 +    }
  47.118 +    ~MessageHandlerImpl()
  47.119 +    {
  47.120 +        MessageHandlerSharedLock.ReleaseLock(pLock);
  47.121 +        pLock = 0;
  47.122 +    }
  47.123 +
  47.124 +    static MessageHandlerImpl* FromHandler(MessageHandler* handler)
  47.125 +    { return (MessageHandlerImpl*)&handler->Internal; }
  47.126 +    static const MessageHandlerImpl* FromHandler(const MessageHandler* handler)
  47.127 +    { return (const MessageHandlerImpl*)&handler->Internal; }
  47.128 +
  47.129 +    // This lock is held while calling a handler and when we are applied/
  47.130 +    // removed from a device.
  47.131 +    Lock*                     pLock;
  47.132 +    // List of device we are applied to.
  47.133 +    List<MessageHandlerRef>   UseList;
  47.134 +};
  47.135 +
  47.136 +
  47.137 +MessageHandlerRef::MessageHandlerRef(DeviceBase* device)
  47.138 +    : pLock(MessageHandlerSharedLock.GetLockAddRef()), pDevice(device), pHandler(0)
  47.139 +{
  47.140 +}
  47.141 +
  47.142 +MessageHandlerRef::~MessageHandlerRef()
  47.143 +{
  47.144 +    {
  47.145 +        Lock::Locker lockScope(pLock);
  47.146 +        if (pHandler)
  47.147 +        {
  47.148 +            pHandler = 0;
  47.149 +            RemoveNode();
  47.150 +        }
  47.151 +    }
  47.152 +    MessageHandlerSharedLock.ReleaseLock(pLock);
  47.153 +    pLock = 0;
  47.154 +}
  47.155 +
  47.156 +void MessageHandlerRef::SetHandler(MessageHandler* handler)
  47.157 +{    
  47.158 +    OVR_ASSERT(!handler ||
  47.159 +               MessageHandlerImpl::FromHandler(handler)->pLock == pLock);    
  47.160 +    Lock::Locker lockScope(pLock);
  47.161 +    SetHandler_NTS(handler);
  47.162 +}
  47.163 +
  47.164 +void MessageHandlerRef::SetHandler_NTS(MessageHandler* handler)
  47.165 +{   
  47.166 +    if (pHandler != handler)
  47.167 +    {
  47.168 +        if (pHandler)
  47.169 +            RemoveNode();
  47.170 +        pHandler = handler;
  47.171 +
  47.172 +        if (handler)
  47.173 +        {
  47.174 +            MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(handler);
  47.175 +            handlerImpl->UseList.PushBack(this);
  47.176 +        }
  47.177 +        // TBD: Call notifier on device?
  47.178 +    }
  47.179 +}
  47.180 +
  47.181 +
  47.182 +MessageHandler::MessageHandler()
  47.183 +{    
  47.184 +    OVR_COMPILER_ASSERT(sizeof(Internal) > sizeof(MessageHandlerImpl));
  47.185 +    Construct<MessageHandlerImpl>(Internal);
  47.186 +}
  47.187 +
  47.188 +MessageHandler::~MessageHandler()
  47.189 +{
  47.190 +    MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
  47.191 +    {
  47.192 +        Lock::Locker lockedScope(handlerImpl->pLock);
  47.193 +        OVR_ASSERT_LOG(handlerImpl->UseList.IsEmpty(),
  47.194 +            ("~MessageHandler %p - Handler still active; call RemoveHandlerFromDevices", this));
  47.195 +    }
  47.196 +
  47.197 +    Destruct<MessageHandlerImpl>(handlerImpl);    
  47.198 +}
  47.199 +
  47.200 +bool MessageHandler::IsHandlerInstalled() const
  47.201 +{
  47.202 +    const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);    
  47.203 +    Lock::Locker lockedScope(handlerImpl->pLock);
  47.204 +    return handlerImpl->UseList.IsEmpty() != true;
  47.205 +}
  47.206 +
  47.207 +
  47.208 +void MessageHandler::RemoveHandlerFromDevices()
  47.209 +{
  47.210 +    MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
  47.211 +    Lock::Locker lockedScope(handlerImpl->pLock);
  47.212 +
  47.213 +    while(!handlerImpl->UseList.IsEmpty())
  47.214 +    {
  47.215 +        MessageHandlerRef* use = handlerImpl->UseList.GetFirst();
  47.216 +        use->SetHandler_NTS(0);
  47.217 +    }
  47.218 +}
  47.219 +
  47.220 +Lock* MessageHandler::GetHandlerLock() const
  47.221 +{
  47.222 +    const MessageHandlerImpl* handlerImpl = MessageHandlerImpl::FromHandler(this);
  47.223 +    return handlerImpl->pLock;
  47.224 +}
  47.225 +
  47.226 +
  47.227 +//-------------------------------------------------------------------------------------
  47.228 +// ***** DeviceBase
  47.229 +   
  47.230 +
  47.231 +// Delegate relevant implementation to DeviceRectord to avoid re-implementation in
  47.232 +// every derived Device.
  47.233 +void DeviceBase::AddRef()
  47.234 +{
  47.235 +    getDeviceCommon()->DeviceAddRef();
  47.236 +}
  47.237 +void DeviceBase::Release()
  47.238 +{
  47.239 +    getDeviceCommon()->DeviceRelease();
  47.240 +}
  47.241 +DeviceBase* DeviceBase::GetParent() const
  47.242 +{
  47.243 +    return getDeviceCommon()->pParent.GetPtr();
  47.244 +}
  47.245 +DeviceManager* DeviceBase::GetManager() const
  47.246 +{
  47.247 +    return getDeviceCommon()->pCreateDesc->GetManagerImpl();
  47.248 +}
  47.249 +
  47.250 +void DeviceBase::SetMessageHandler(MessageHandler* handler)
  47.251 +{
  47.252 +    getDeviceCommon()->HandlerRef.SetHandler(handler);
  47.253 +}
  47.254 +MessageHandler* DeviceBase::GetMessageHandler() const
  47.255 +{
  47.256 +    return getDeviceCommon()->HandlerRef.GetHandler();
  47.257 +}
  47.258 +
  47.259 +DeviceType DeviceBase::GetType() const
  47.260 +{
  47.261 +    return getDeviceCommon()->pCreateDesc->Type;
  47.262 +}
  47.263 +
  47.264 +bool DeviceBase::GetDeviceInfo(DeviceInfo* info) const
  47.265 +{
  47.266 +    return getDeviceCommon()->pCreateDesc->GetDeviceInfo(info);
  47.267 +    //info->Name[0] = 0;
  47.268 +    //return false;
  47.269 +}
  47.270 +
  47.271 +// returns the MessageHandler's lock
  47.272 +Lock* DeviceBase::GetHandlerLock() const
  47.273 +{
  47.274 +    return getDeviceCommon()->HandlerRef.GetLock();
  47.275 +}
  47.276 +
  47.277 +// Derive DeviceManagerCreateDesc to provide abstract function implementation.
  47.278 +class DeviceManagerCreateDesc : public DeviceCreateDesc
  47.279 +{
  47.280 +public:
  47.281 +    DeviceManagerCreateDesc(DeviceFactory* factory)
  47.282 +        : DeviceCreateDesc(factory, Device_Manager) { }
  47.283 +
  47.284 +    // We don't need there on Manager since it isn't assigned to DeviceHandle.
  47.285 +    virtual DeviceCreateDesc* Clone() const                        { return 0; }
  47.286 +    virtual MatchResult MatchDevice(const DeviceCreateDesc&,
  47.287 +                                    DeviceCreateDesc**) const      { return Match_None; }
  47.288 +    virtual DeviceBase* NewDeviceInstance()                        { return 0; }
  47.289 +    virtual bool        GetDeviceInfo(DeviceInfo*) const           { return false; }
  47.290 +};
  47.291 +
  47.292 +//-------------------------------------------------------------------------------------
  47.293 +// ***** DeviceManagerImpl
  47.294 +
  47.295 +DeviceManagerImpl::DeviceManagerImpl()
  47.296 +    : DeviceImpl<OVR::DeviceManager>(CreateManagerDesc(), 0)
  47.297 +      //,DeviceCreateDescList(pCreateDesc ? pCreateDesc->pLock : 0)
  47.298 +{
  47.299 +    if (pCreateDesc)
  47.300 +    {
  47.301 +        pCreateDesc->pLock->pManager = this;
  47.302 +    }
  47.303 +}
  47.304 +
  47.305 +DeviceManagerImpl::~DeviceManagerImpl()
  47.306 +{
  47.307 +    // Shutdown must've been called.
  47.308 +    OVR_ASSERT(!pCreateDesc->pDevice);
  47.309 +
  47.310 +    // Remove all factories
  47.311 +    while(!Factories.IsEmpty())
  47.312 +    {
  47.313 +        DeviceFactory* factory = Factories.GetFirst();
  47.314 +        factory->RemovedFromManager();
  47.315 +        factory->RemoveNode();
  47.316 +    }
  47.317 +}
  47.318 +
  47.319 +DeviceCreateDesc* DeviceManagerImpl::CreateManagerDesc()
  47.320 +{
  47.321 +    DeviceCreateDesc* managerDesc = new DeviceManagerCreateDesc(0);
  47.322 +    if (managerDesc)
  47.323 +    {
  47.324 +        managerDesc->pLock = *new DeviceManagerLock;
  47.325 +    }
  47.326 +    return managerDesc;
  47.327 +}
  47.328 +
  47.329 +bool DeviceManagerImpl::Initialize(DeviceBase* parent)
  47.330 +{
  47.331 +    OVR_UNUSED(parent);
  47.332 +    if (!pCreateDesc || !pCreateDesc->pLock)
  47.333 +		return false;
  47.334 +
  47.335 +    pProfileManager = *ProfileManager::Create();
  47.336 +
  47.337 +    return true;
  47.338 +}
  47.339 +
  47.340 +void DeviceManagerImpl::Shutdown()
  47.341 +{
  47.342 +    // Remove all device descriptors from list while the lock is held.
  47.343 +    // Some descriptors may survive longer due to handles.    
  47.344 +    while(!Devices.IsEmpty())
  47.345 +    {     
  47.346 +        DeviceCreateDesc* devDesc = Devices.GetFirst();
  47.347 +        OVR_ASSERT(!devDesc->pDevice); // Manager shouldn't be dying while Device exists.
  47.348 +        devDesc->Enumerated = false;
  47.349 +        devDesc->RemoveNode();
  47.350 +        devDesc->pNext = devDesc->pPrev = 0;
  47.351 +
  47.352 +        if (devDesc->HandleCount == 0)
  47.353 +        {
  47.354 +            delete devDesc;
  47.355 +        }
  47.356 +    }
  47.357 +    Devices.Clear();
  47.358 +
  47.359 +    // These must've been cleared by caller.
  47.360 +    OVR_ASSERT(pCreateDesc->pDevice == 0);
  47.361 +    OVR_ASSERT(pCreateDesc->pLock->pManager == 0);
  47.362 +
  47.363 +    pProfileManager.Clear();
  47.364 +}
  47.365 +
  47.366 +
  47.367 +// Callbacks for DeviceCreation/Release    
  47.368 +DeviceBase* DeviceManagerImpl::CreateDevice_MgrThread(DeviceCreateDesc* createDesc, DeviceBase* parent)
  47.369 +{
  47.370 +    // Calls to DeviceManagerImpl::CreateDevice are enqueued with wait while holding pManager,
  47.371 +    // so 'this' must remain valid.
  47.372 +    OVR_ASSERT(createDesc->pLock->pManager);    
  47.373 +
  47.374 +    Lock::Locker devicesLock(GetLock());
  47.375 +
  47.376 +    // If device already exists, just AddRef to it.
  47.377 +    if (createDesc->pDevice)
  47.378 +    {
  47.379 +        createDesc->pDevice->AddRef();
  47.380 +        return createDesc->pDevice;
  47.381 +    }
  47.382 +
  47.383 +    if (!parent)
  47.384 +        parent = this;
  47.385 +
  47.386 +    DeviceBase* device = createDesc->NewDeviceInstance();
  47.387 +    
  47.388 +    if (device)
  47.389 +    {
  47.390 +        if (device->getDeviceCommon()->Initialize(parent))
  47.391 +        {
  47.392 +           createDesc->pDevice = device;
  47.393 +        }
  47.394 +        else
  47.395 +        {
  47.396 +            // Don't go through Release() to avoid PushCall behaviour,
  47.397 +            // as it is not needed here.
  47.398 +            delete device;
  47.399 +            device = 0;
  47.400 +        }
  47.401 +    }
  47.402 +     
  47.403 +    return device;
  47.404 +}
  47.405 +
  47.406 +Void DeviceManagerImpl::ReleaseDevice_MgrThread(DeviceBase* device)
  47.407 +{
  47.408 +    // descKeepAlive will keep ManagerLock object alive as well,
  47.409 +    // allowing us to exit gracefully.    
  47.410 +    Ptr<DeviceCreateDesc>  descKeepAlive;
  47.411 +    Lock::Locker           devicesLock(GetLock());
  47.412 +    DeviceCommon*          devCommon = device->getDeviceCommon();
  47.413 +
  47.414 +    while(1)
  47.415 +    {
  47.416 +        UInt32 refCount = devCommon->RefCount;
  47.417 +
  47.418 +        if (refCount > 1)
  47.419 +        {
  47.420 +            if (devCommon->RefCount.CompareAndSet_NoSync(refCount, refCount-1))
  47.421 +            {
  47.422 +                // We decreented from initial count higher then 1;
  47.423 +                // nothing else to do.
  47.424 +                return 0;
  47.425 +            }        
  47.426 +        }
  47.427 +        else if (devCommon->RefCount.CompareAndSet_NoSync(1, 0))
  47.428 +        {
  47.429 +            // { 1 -> 0 } decrement succeded. Destroy this device.
  47.430 +            break;
  47.431 +        }
  47.432 +    }
  47.433 +
  47.434 +    // At this point, may be releasing the device manager itself.
  47.435 +    // This does not matter, however, since shutdown logic is the same
  47.436 +    // in both cases. DeviceManager::Shutdown with begin shutdown process for
  47.437 +    // the internal manager thread, which will eventually destroy itself.
  47.438 +    // TBD: Clean thread shutdown.
  47.439 +    descKeepAlive = devCommon->pCreateDesc;
  47.440 +    descKeepAlive->pDevice = 0;
  47.441 +    devCommon->Shutdown();
  47.442 +    delete device;
  47.443 +    return 0;
  47.444 +}
  47.445 +
  47.446 +
  47.447 +
  47.448 +Void DeviceManagerImpl::EnumerateAllFactoryDevices()
  47.449 +{
  47.450 +    // 1. Mark matching devices as NOT enumerated.
  47.451 +    // 2. Call factory to enumerate all HW devices, adding any device that 
  47.452 +    //    was not matched.
  47.453 +    // 3. Remove non-matching devices.
  47.454 +
  47.455 +    Lock::Locker deviceLock(GetLock());
  47.456 +
  47.457 +    DeviceCreateDesc* devDesc, *nextdevDesc;
  47.458 +
  47.459 +    // 1.
  47.460 +    for(devDesc = Devices.GetFirst();
  47.461 +        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
  47.462 +    {
  47.463 +        //if (devDesc->pFactory == factory)
  47.464 +            devDesc->Enumerated = false;
  47.465 +    }
  47.466 +    
  47.467 +    // 2.
  47.468 +    DeviceFactory* factory = Factories.GetFirst();
  47.469 +    while(!Factories.IsNull(factory))
  47.470 +    {
  47.471 +        EnumerateFactoryDevices(factory);
  47.472 +        factory = factory->pNext;
  47.473 +    }
  47.474 +
  47.475 +    
  47.476 +    // 3.
  47.477 +    for(devDesc = Devices.GetFirst();
  47.478 +        !Devices.IsNull(devDesc);  devDesc = nextdevDesc)
  47.479 +    {
  47.480 +        // In case 'devDesc' gets removed.
  47.481 +        nextdevDesc = devDesc->pNext; 
  47.482 +
  47.483 +        // Note, device might be not enumerated since it is opened and
  47.484 +        // in use! Do NOT notify 'device removed' in this case (!AB)
  47.485 +        if (!devDesc->Enumerated)
  47.486 +        {
  47.487 +            // This deletes the devDesc for HandleCount == 0 due to Release in DeviceHandle.
  47.488 +            CallOnDeviceRemoved(devDesc);
  47.489 +
  47.490 +            /*
  47.491 +            if (devDesc->HandleCount == 0)
  47.492 +            {                
  47.493 +                // Device must be dead if it ever existed, since it AddRefs to us.
  47.494 +                // ~DeviceCreateDesc removes its node from list.
  47.495 +                OVR_ASSERT(!devDesc->pDevice);
  47.496 +                delete devDesc;
  47.497 +            }
  47.498 +            */
  47.499 +        }
  47.500 +    }
  47.501 +
  47.502 +    return 0;
  47.503 +}
  47.504 +
  47.505 +Ptr<DeviceCreateDesc> DeviceManagerImpl::AddDevice_NeedsLock(
  47.506 +    const DeviceCreateDesc& createDesc)
  47.507 +{
  47.508 +    // If found, mark as enumerated and we are done.
  47.509 +    DeviceCreateDesc* descCandidate = 0;
  47.510 +
  47.511 +    for(DeviceCreateDesc* devDesc = Devices.GetFirst();
  47.512 +        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
  47.513 +    {
  47.514 +        DeviceCreateDesc::MatchResult mr = devDesc->MatchDevice(createDesc, &descCandidate);
  47.515 +        if (mr == DeviceCreateDesc::Match_Found)
  47.516 +        {
  47.517 +            devDesc->Enumerated = true;
  47.518 +            if (!devDesc->pDevice)
  47.519 +                CallOnDeviceAdded(devDesc);
  47.520 +            return devDesc;
  47.521 +        }
  47.522 +    }
  47.523 +
  47.524 +    // Update candidate (this may involve writing fields to HMDDevice createDesc).
  47.525 +    if (descCandidate)
  47.526 +    {
  47.527 +        bool newDevice = false;
  47.528 +        if (descCandidate->UpdateMatchedCandidate(createDesc, &newDevice))
  47.529 +        {
  47.530 +            descCandidate->Enumerated = true;
  47.531 +            if (!descCandidate->pDevice || newDevice)
  47.532 +                CallOnDeviceAdded(descCandidate);
  47.533 +            return descCandidate;
  47.534 +        }
  47.535 +    }
  47.536 +
  47.537 +    // If not found, add new device.
  47.538 +    //  - This stores a new descriptor with
  47.539 +    //    {pDevice = 0, HandleCount = 1, Enumerated = true}
  47.540 +    DeviceCreateDesc* desc = createDesc.Clone();
  47.541 +    desc->pLock = pCreateDesc->pLock;
  47.542 +    Devices.PushBack(desc);
  47.543 +    desc->Enumerated = true;
  47.544 +
  47.545 +    CallOnDeviceAdded(desc);
  47.546 +
  47.547 +    return desc;
  47.548 +}
  47.549 +
  47.550 +Ptr<DeviceCreateDesc> DeviceManagerImpl::FindDevice(
  47.551 +    const String& path, 
  47.552 +    DeviceType deviceType)
  47.553 +{
  47.554 +    Lock::Locker deviceLock(GetLock());
  47.555 +    DeviceCreateDesc* devDesc;
  47.556 +
  47.557 +    for (devDesc = Devices.GetFirst();
  47.558 +        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
  47.559 +    {
  47.560 +        if ((deviceType == Device_None || deviceType == devDesc->Type) &&
  47.561 +            devDesc->MatchDevice(path))
  47.562 +            return devDesc;
  47.563 +    }
  47.564 +    return NULL;
  47.565 +}
  47.566 +
  47.567 +Ptr<DeviceCreateDesc> DeviceManagerImpl::FindHIDDevice(const HIDDeviceDesc& hidDevDesc)
  47.568 +{
  47.569 +    Lock::Locker deviceLock(GetLock());
  47.570 +    DeviceCreateDesc* devDesc;
  47.571 +    
  47.572 +    for (devDesc = Devices.GetFirst();
  47.573 +        !Devices.IsNull(devDesc);  devDesc = devDesc->pNext)
  47.574 +    {
  47.575 +        if (devDesc->MatchHIDDevice(hidDevDesc))
  47.576 +            return devDesc;
  47.577 +    }
  47.578 +    return NULL;
  47.579 +}
  47.580 +  
  47.581 +void DeviceManagerImpl::DetectHIDDevice(const HIDDeviceDesc& hidDevDesc)
  47.582 +{
  47.583 +    Lock::Locker deviceLock(GetLock());
  47.584 +    DeviceFactory* factory = Factories.GetFirst();
  47.585 +    while(!Factories.IsNull(factory))
  47.586 +    {
  47.587 +        if (factory->DetectHIDDevice(this, hidDevDesc))
  47.588 +            break;
  47.589 +        factory = factory->pNext;
  47.590 +    }
  47.591 +    
  47.592 +}
  47.593 +    
  47.594 +// Enumerates devices for a particular factory.
  47.595 +Void DeviceManagerImpl::EnumerateFactoryDevices(DeviceFactory* factory)
  47.596 +{
  47.597 +       
  47.598 +    class FactoryEnumerateVisitor : public DeviceFactory::EnumerateVisitor
  47.599 +    {        
  47.600 +        DeviceManagerImpl* pManager;
  47.601 +        DeviceFactory*     pFactory;
  47.602 +    public:
  47.603 +        FactoryEnumerateVisitor(DeviceManagerImpl* manager, DeviceFactory* factory)
  47.604 +            : pManager(manager), pFactory(factory) { }
  47.605 +
  47.606 +        virtual void Visit(const DeviceCreateDesc& createDesc)
  47.607 +        {
  47.608 +            pManager->AddDevice_NeedsLock(createDesc);
  47.609 +        }
  47.610 +    };
  47.611 +
  47.612 +    FactoryEnumerateVisitor newDeviceVisitor(this, factory);
  47.613 +    factory->EnumerateDevices(newDeviceVisitor);
  47.614 +
  47.615 +
  47.616 +    return 0;
  47.617 +}
  47.618 +
  47.619 +
  47.620 +DeviceEnumerator<> DeviceManagerImpl::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
  47.621 +{
  47.622 +    Lock::Locker deviceLock(GetLock());
  47.623 +    
  47.624 +    if (Devices.IsEmpty())
  47.625 +        return DeviceEnumerator<>();
  47.626 +
  47.627 +    DeviceCreateDesc*  firstDeviceDesc = Devices.GetFirst();
  47.628 +    DeviceEnumerator<> e = enumeratorFromHandle(DeviceHandle(firstDeviceDesc), args);
  47.629 +
  47.630 +    if (!args.MatchRule(firstDeviceDesc->Type, firstDeviceDesc->Enumerated))
  47.631 +    {
  47.632 +        e.Next();
  47.633 +    }
  47.634 +    
  47.635 +    return e;
  47.636 +}
  47.637 +
  47.638 +//-------------------------------------------------------------------------------------
  47.639 +// ***** DeviceCommon
  47.640 +
  47.641 +void DeviceCommon::DeviceAddRef()
  47.642 +{
  47.643 +    RefCount++;
  47.644 +}
  47.645 +
  47.646 +void DeviceCommon::DeviceRelease()
  47.647 +{
  47.648 +    while(1)
  47.649 +    {
  47.650 +        UInt32 refCount = RefCount;
  47.651 +        OVR_ASSERT(refCount > 0);
  47.652 +        
  47.653 +        if (refCount == 1)
  47.654 +        {
  47.655 +            DeviceManagerImpl*  manager = pCreateDesc->GetManagerImpl();
  47.656 +            ThreadCommandQueue* queue   = manager->GetThreadQueue();
  47.657 +
  47.658 +            // Enqueue ReleaseDevice for {1 -> 0} transition with no wait.
  47.659 +            // We pass our reference ownership into the queue to destroy.
  47.660 +            // It's in theory possible for another thread to re-steal our device reference,
  47.661 +            // but that is checked for atomically in DeviceManagerImpl::ReleaseDevice.
  47.662 +            if (!queue->PushCall(manager, &DeviceManagerImpl::ReleaseDevice_MgrThread,
  47.663 +                                          pCreateDesc->pDevice))
  47.664 +            {
  47.665 +                // PushCall shouldn't fail because background thread runs while manager is
  47.666 +                // alive and we are holding Manager alive through pParent chain.
  47.667 +                OVR_ASSERT(false);
  47.668 +            }
  47.669 +
  47.670 +            // Warning! At his point everything, including manager, may be dead.
  47.671 +            break;
  47.672 +        }
  47.673 +        else if (RefCount.CompareAndSet_NoSync(refCount, refCount-1))
  47.674 +        {
  47.675 +            break;
  47.676 +        }
  47.677 +    }
  47.678 +}
  47.679 +
  47.680 +
  47.681 +
  47.682 +//-------------------------------------------------------------------------------------
  47.683 +// ***** DeviceCreateDesc
  47.684 +
  47.685 +
  47.686 +void DeviceCreateDesc::AddRef()
  47.687 +{
  47.688 +    // Technically, HandleCount { 0 -> 1 } transition can only happen during Lock,
  47.689 +    // but we leave this to caller to worry about (happens during enumeration).
  47.690 +    HandleCount++;
  47.691 +}
  47.692 +
  47.693 +void DeviceCreateDesc::Release()
  47.694 +{
  47.695 +    while(1)
  47.696 +    {
  47.697 +        UInt32 handleCount = HandleCount;
  47.698 +        // HandleCount must obviously be >= 1, since we are releasing it.
  47.699 +        OVR_ASSERT(handleCount > 0);
  47.700 +
  47.701 +        // {1 -> 0} transition may cause us to be destroyed, so require a lock.
  47.702 +        if (handleCount == 1)
  47.703 +        {       
  47.704 +            Ptr<DeviceManagerLock>  lockKeepAlive;
  47.705 +            Lock::Locker            deviceLockScope(GetLock());
  47.706 +
  47.707 +            if (!HandleCount.CompareAndSet_NoSync(handleCount, 0))
  47.708 +                continue;
  47.709 +            
  47.710 +            OVR_ASSERT(pDevice == 0);
  47.711 +
  47.712 +            // Destroy *this if the manager was destroyed already, or Enumerated
  47.713 +            // is false (device no longer available).           
  47.714 +            if (!GetManagerImpl() || !Enumerated)
  47.715 +            {
  47.716 +                lockKeepAlive = pLock;
  47.717 +
  47.718 +                // Remove from manager list (only matters for !Enumerated).
  47.719 +                if (pNext)
  47.720 +                {
  47.721 +                    RemoveNode();
  47.722 +                    pNext = pPrev = 0;
  47.723 +                }
  47.724 +
  47.725 +                delete this;
  47.726 +            }
  47.727 +
  47.728 +            // Available DeviceCreateDesc may survive with { HandleCount == 0 },
  47.729 +            // in case it might be enumerated again later.
  47.730 +            break;
  47.731 +        }
  47.732 +        else if (HandleCount.CompareAndSet_NoSync(handleCount, handleCount-1))
  47.733 +        {
  47.734 +            break;
  47.735 +        }
  47.736 +    }
  47.737 +}
  47.738 +
  47.739 +HMDDevice* HMDDevice::Disconnect(SensorDevice* psensor)
  47.740 +{
  47.741 +    if (!psensor)
  47.742 +        return NULL;
  47.743 +
  47.744 +    OVR::DeviceManager* manager = GetManager();
  47.745 +    if (manager)
  47.746 +    {
  47.747 +        //DeviceManagerImpl* mgrImpl = static_cast<DeviceManagerImpl*>(manager);
  47.748 +        Ptr<DeviceCreateDesc> desc = getDeviceCommon()->pCreateDesc;
  47.749 +        if (desc)
  47.750 +        {
  47.751 +            class Visitor : public DeviceFactory::EnumerateVisitor
  47.752 +            {
  47.753 +                Ptr<DeviceCreateDesc> Desc;
  47.754 +            public:
  47.755 +                Visitor(DeviceCreateDesc* desc) : Desc(desc) {}
  47.756 +                virtual void Visit(const DeviceCreateDesc& createDesc) 
  47.757 +                {
  47.758 +                    Lock::Locker lock(Desc->GetLock());
  47.759 +                    Desc->UpdateMatchedCandidate(createDesc);
  47.760 +                }
  47.761 +            } visitor(desc);
  47.762 +            //SensorDeviceImpl* sImpl = static_cast<SensorDeviceImpl*>(psensor);
  47.763 +
  47.764 +            SensorDisplayInfoImpl displayInfo;
  47.765 +
  47.766 +            if (psensor->GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize))
  47.767 +            {
  47.768 +                displayInfo.Unpack();
  47.769 +
  47.770 +                // If we got display info, try to match / create HMDDevice as well
  47.771 +                // so that sensor settings give preference.
  47.772 +                if (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt)
  47.773 +                {
  47.774 +                    SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(displayInfo, visitor);
  47.775 +                }
  47.776 +            }
  47.777 +        }
  47.778 +    }
  47.779 +    return this;
  47.780 +}
  47.781 +
  47.782 +bool  HMDDevice::IsDisconnected() const
  47.783 +{
  47.784 +    OVR::HMDInfo info;
  47.785 +    GetDeviceInfo(&info);
  47.786 +    // if strlen(info.DisplayDeviceName) == 0 then
  47.787 +    // this HMD is 'fake' (created using sensor).
  47.788 +    return (strlen(info.DisplayDeviceName) == 0);
  47.789 +}
  47.790 +
  47.791 +
  47.792 +} // namespace OVR
  47.793 +
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/libovr/Src/OVR_DeviceImpl.h	Sat Sep 14 16:14:59 2013 +0300
    48.3 @@ -0,0 +1,432 @@
    48.4 +/************************************************************************************
    48.5 +
    48.6 +Filename    :   OVR_DeviceImpl.h
    48.7 +Content     :   Partial back-end independent implementation of Device interfaces
    48.8 +Created     :   October 10, 2012
    48.9 +Authors     :   Michael Antonov
   48.10 +
   48.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   48.12 +
   48.13 +Use of this software is subject to the terms of the Oculus license
   48.14 +agreement provided at the time of installation or download, or which
   48.15 +otherwise accompanies this software in either electronic or hard copy form.
   48.16 +
   48.17 +*************************************************************************************/
   48.18 +
   48.19 +#ifndef OVR_DeviceImpl_h
   48.20 +#define OVR_DeviceImpl_h
   48.21 +
   48.22 +#include "OVR_Device.h"
   48.23 +#include "Kernel/OVR_Atomic.h"
   48.24 +#include "Kernel/OVR_Log.h"
   48.25 +#include "Kernel/OVR_System.h"
   48.26 +
   48.27 +#include "Kernel/OVR_Threads.h"
   48.28 +#include "OVR_ThreadCommandQueue.h"
   48.29 +#include "OVR_HIDDevice.h"
   48.30 +
   48.31 +namespace OVR {
   48.32 +    
   48.33 +class DeviceManagerImpl;
   48.34 +class DeviceFactory;
   48.35 +
   48.36 +enum
   48.37 +{
   48.38 +    Oculus_VendorId = 0x2833
   48.39 +};
   48.40 +
   48.41 +//-------------------------------------------------------------------------------------
   48.42 +// Globally shared Lock implementation used for MessageHandlers.
   48.43 +
   48.44 +class SharedLock
   48.45 +{    
   48.46 +public:
   48.47 +    SharedLock() : UseCount(0) {}
   48.48 +
   48.49 +    Lock* GetLockAddRef();
   48.50 +    void  ReleaseLock(Lock* plock);
   48.51 +   
   48.52 +private:
   48.53 +    Lock* toLock() { return (Lock*)Buffer; }
   48.54 +
   48.55 +    // UseCount and max alignment.
   48.56 +    volatile int    UseCount;
   48.57 +    UInt64          Buffer[(sizeof(Lock)+sizeof(UInt64)-1)/sizeof(UInt64)];
   48.58 +};
   48.59 +
   48.60 +
   48.61 +// Wrapper for MessageHandler that includes synchronization logic.
   48.62 +// References to MessageHandlers are organized in a list to allow for them to
   48.63 +// easily removed with MessageHandler::RemoveAllHandlers.
   48.64 +class MessageHandlerRef : public ListNode<MessageHandlerRef>
   48.65 +{    
   48.66 +public:
   48.67 +    MessageHandlerRef(DeviceBase* device);
   48.68 +    ~MessageHandlerRef();
   48.69 +
   48.70 +    void SetHandler(MessageHandler* hander);
   48.71 +
   48.72 +    // Not-thread-safe version
   48.73 +    void SetHandler_NTS(MessageHandler* hander);
   48.74 +    
   48.75 +    void Call(const Message& msg)
   48.76 +    {
   48.77 +        Lock::Locker lockScope(pLock);
   48.78 +        if (pHandler)
   48.79 +            pHandler->OnMessage(msg);
   48.80 +    }
   48.81 +
   48.82 +    Lock*           GetLock() const { return pLock; }
   48.83 +
   48.84 +    // GetHandler() is not thread safe if used out of order across threads; nothing can be done
   48.85 +    // about that.
   48.86 +    MessageHandler* GetHandler() const { return pHandler; }
   48.87 +    DeviceBase*     GetDevice() const  { return pDevice; }
   48.88 +
   48.89 +private:
   48.90 +    Lock*           pLock;   // Cached global handler lock.
   48.91 +    DeviceBase*     pDevice;
   48.92 +    MessageHandler* pHandler;
   48.93 +};
   48.94 +
   48.95 +
   48.96 +
   48.97 +//-------------------------------------------------------------------------------------
   48.98 +
   48.99 +// DeviceManagerLock is a synchronization lock used by DeviceManager for Devices
  48.100 +// and is allocated separately for potentially longer lifetime.
  48.101 +// 
  48.102 +// DeviceManagerLock is used for all of the following:
  48.103 +//  - Adding/removing devices
  48.104 +//  - Reporting manager lifetime (pManager != 0) for DeviceHandles
  48.105 +//  - Protecting device creation/shutdown.
  48.106 +
  48.107 +class DeviceManagerLock : public RefCountBase<DeviceManagerLock>
  48.108 +{
  48.109 +public:
  48.110 +    Lock                CreateLock;
  48.111 +    DeviceManagerImpl*  pManager;
  48.112 +
  48.113 +    DeviceManagerLock() : pManager(0) { }
  48.114 +};
  48.115 +
  48.116 +
  48.117 +// DeviceCreateDesc provides all of the information needed to create any device, a derived
  48.118 +// instance of this class is created by DeviceFactory during enumeration.
  48.119 +//   - DeviceCreateDesc may or may not be a part of DeviceManager::Devices list (check pNext != 0).
  48.120 +//   - Referenced and kept alive by DeviceHandle.
  48.121 +
  48.122 +class DeviceCreateDesc : public ListNode<DeviceCreateDesc>, public NewOverrideBase
  48.123 +{    
  48.124 +    void operator = (const DeviceCreateDesc&) { } // Assign not supported; suppress MSVC warning.
  48.125 +public:
  48.126 +    DeviceCreateDesc(DeviceFactory* factory, DeviceType type)
  48.127 +        : pFactory(factory), Type(type), pLock(0), HandleCount(0), pDevice(0), Enumerated(true)
  48.128 +    {
  48.129 +        pNext = pPrev = 0;
  48.130 +    }
  48.131 +
  48.132 +    virtual ~DeviceCreateDesc()
  48.133 +    {
  48.134 +        OVR_ASSERT(!pDevice);
  48.135 +        if (pNext)        
  48.136 +            RemoveNode();
  48.137 +    }
  48.138 +
  48.139 +    DeviceManagerImpl* GetManagerImpl() const { return pLock->pManager; }
  48.140 +    Lock*              GetLock() const        { return &pLock->CreateLock; }
  48.141 +
  48.142 +    // DeviceCreateDesc reference counting is tied to Devices list management,
  48.143 +    // see comments for HandleCount.
  48.144 +    void AddRef();
  48.145 +    void Release();
  48.146 +
  48.147 +
  48.148 +    // *** Device creation/matching Interface
  48.149 +
  48.150 +
  48.151 +    // Cloning copies us to an allocated object when new device is enumerated.
  48.152 +    virtual DeviceCreateDesc* Clone() const = 0;
  48.153 +    // Creates a new device instance without Initializing it; the
  48.154 +    // later is done my Initialize()/Shutdown() methods of the device itself.
  48.155 +    virtual DeviceBase*       NewDeviceInstance() = 0;
  48.156 +    // Override to return device-specific info.
  48.157 +    virtual bool              GetDeviceInfo(DeviceInfo* info) const = 0;
  48.158 +
  48.159 +
  48.160 +    enum MatchResult
  48.161 +    {
  48.162 +        Match_None,
  48.163 +        Match_Found,
  48.164 +        Match_Candidate
  48.165 +    };
  48.166 +
  48.167 +    // Override to return Match_Found if descriptor matches our device.
  48.168 +    // Match_Candidate can be returned, with pcandicate update, if this may be a match
  48.169 +    // but more searching is necessary. If this is the case UpdateMatchedCandidate will be called.
  48.170 +    virtual MatchResult       MatchDevice(const DeviceCreateDesc& other,
  48.171 +                                          DeviceCreateDesc** pcandidate) const = 0;
  48.172 +    
  48.173 +    // Called for matched candidate after all potential matches are iterated.
  48.174 +    // Used to update HMDevice creation arguments from Sensor.
  48.175 +    // Optional return param 'newDeviceFlag' will be set to true if the 
  48.176 +    // 'desc' refers to a new device; false, otherwise.
  48.177 +    // Return 'false' to create new object, 'true' if done with this argument.
  48.178 +    virtual bool              UpdateMatchedCandidate(
  48.179 +        const DeviceCreateDesc& desc, bool* newDeviceFlag = NULL) 
  48.180 +    { OVR_UNUSED2(desc, newDeviceFlag); return false; }
  48.181 +
  48.182 +    // Matches HID device to the descriptor.
  48.183 +    virtual bool              MatchHIDDevice(const HIDDeviceDesc&) const { return false; }
  48.184 +
  48.185 +    // Matches device by path.
  48.186 +    virtual bool              MatchDevice(const String& /*path*/) { return false; }
  48.187 +//protected:
  48.188 +    DeviceFactory* const        pFactory;
  48.189 +    const DeviceType            Type;
  48.190 +
  48.191 +    // List in which this descriptor lives. pList->CreateLock required if added/removed.
  48.192 +    Ptr<DeviceManagerLock>      pLock;    
  48.193 +
  48.194 +    // Strong references to us: Incremented by Device, DeviceHandles & Enumerators.
  48.195 +    // May be 0 if device not created and there are no handles.
  48.196 +    // Following transitions require pList->CreateLock:
  48.197 +    //  {1 -> 0}: May delete & remove handle if no longer available.
  48.198 +    //  {0 -> 1}: Device creation is only possible if manager is still alive.
  48.199 +    AtomicInt<UInt32>           HandleCount;
  48.200 +    // If not null, points to our created device instance. Modified during lock only.
  48.201 +    DeviceBase*                 pDevice;
  48.202 +    // True if device is marked as available during enumeration.
  48.203 +    bool                        Enumerated;
  48.204 +};
  48.205 +
  48.206 +
  48.207 +
  48.208 +// Common data present in the implementation of every DeviceBase.
  48.209 +// Injected by DeviceImpl.
  48.210 +class DeviceCommon
  48.211 +{
  48.212 +public:
  48.213 +    AtomicInt<UInt32>      RefCount;
  48.214 +    Ptr<DeviceCreateDesc>  pCreateDesc;
  48.215 +    Ptr<DeviceBase>        pParent;
  48.216 +    MessageHandlerRef      HandlerRef;
  48.217 +
  48.218 +    DeviceCommon(DeviceCreateDesc* createDesc, DeviceBase* device, DeviceBase* parent)
  48.219 +        : RefCount(1), pCreateDesc(createDesc), pParent(parent), HandlerRef(device)
  48.220 +    {
  48.221 +    }
  48.222 +
  48.223 +    // Device reference counting delegates to Manager thread to actually kill devices.
  48.224 +    void DeviceAddRef();
  48.225 +    void DeviceRelease();
  48.226 +
  48.227 +    Lock* GetLock() const { return pCreateDesc->GetLock(); }
  48.228 +
  48.229 +    virtual bool Initialize(DeviceBase* parent) = 0;
  48.230 +    virtual void Shutdown() = 0;
  48.231 +};
  48.232 +
  48.233 +
  48.234 +//-------------------------------------------------------------------------------------
  48.235 +// DeviceImpl address DeviceRecord implementation to a device base class B.
  48.236 +// B must be derived form DeviceBase.
  48.237 +
  48.238 +template<class B>
  48.239 +class DeviceImpl : public B, public DeviceCommon
  48.240 +{
  48.241 +public:
  48.242 +    DeviceImpl(DeviceCreateDesc* createDesc, DeviceBase* parent)
  48.243 +        : DeviceCommon(createDesc, getThis(), parent)        
  48.244 +    {
  48.245 +    }
  48.246 +
  48.247 +	// Convenience method to avoid manager access typecasts.
  48.248 +    DeviceManagerImpl*  GetManagerImpl() const      { return pCreateDesc->pLock->pManager; }
  48.249 +
  48.250 +    // Inline to avoid warnings.
  48.251 +    DeviceImpl*         getThis()                   { return this; }
  48.252 +
  48.253 +    // Common implementation delegate to avoid virtual inheritance and dynamic casts.
  48.254 +    virtual DeviceCommon* getDeviceCommon() const   { return (DeviceCommon*)this; }
  48.255 +
  48.256 +    /*
  48.257 +    virtual void            AddRef()                                   { pCreateDesc->DeviceAddRef(); }
  48.258 +    virtual void            Release()                                  { pCreateDesc->DeviceRelease(); }
  48.259 +    virtual DeviceBase*     GetParent() const                          { return pParent.GetPtr(); } 
  48.260 +    virtual DeviceManager*  GetManager() const                         { return pCreateDesc->pLock->pManager;}
  48.261 +    virtual void            SetMessageHandler(MessageHandler* handler) { HanderRef.SetHandler(handler); }
  48.262 +    virtual MessageHandler* GetMessageHandler() const                  { return HanderRef.GetHandler(); }
  48.263 +    virtual DeviceType      GetType() const                            { return pCreateDesc->Type; }
  48.264 +    virtual DeviceType      GetType() const                            { return pCreateDesc->Type; }
  48.265 +    */
  48.266 +};
  48.267 +
  48.268 +
  48.269 +//-------------------------------------------------------------------------------------
  48.270 +// ***** DeviceFactory
  48.271 +
  48.272 +// DeviceFactory is maintained in DeviceManager for each separately-enumerable
  48.273 +// device type; factories allow separation of unrelated enumeration code.
  48.274 +
  48.275 +class DeviceFactory : public ListNode<DeviceFactory>, public NewOverrideBase
  48.276 +{    
  48.277 +public:
  48.278 +
  48.279 +    DeviceFactory() : pManager(0)
  48.280 +    {
  48.281 +        pNext = pPrev = 0;
  48.282 +    }
  48.283 +    virtual ~DeviceFactory() { }
  48.284 +
  48.285 +    DeviceManagerImpl* GetManagerImpl() { return pManager; }
  48.286 +
  48.287 +    // Notifiers called when we are added to/removed from a device.
  48.288 +    virtual bool AddedToManager(DeviceManagerImpl* manager)
  48.289 +    {
  48.290 +        OVR_ASSERT(pManager == 0);
  48.291 +        pManager = manager;
  48.292 +        return true;
  48.293 +    }
  48.294 +
  48.295 +    virtual void RemovedFromManager()
  48.296 +    {
  48.297 +        pManager = 0;
  48.298 +    }
  48.299 +
  48.300 +
  48.301 +    // *** Device Enumeration/Creation Support
  48.302 +    
  48.303 +    // Passed to EnumerateDevices to be informed of every device detected.
  48.304 +    class EnumerateVisitor
  48.305 +    {
  48.306 +    public:        
  48.307 +        virtual void Visit(const DeviceCreateDesc& createDesc) = 0;
  48.308 +    };
  48.309 +
  48.310 +    // Enumerates factory devices by notifying EnumerateVisitor about every
  48.311 +    // device that is present.
  48.312 +    virtual void EnumerateDevices(EnumerateVisitor& visitor) = 0;
  48.313 +
  48.314 +    // Matches vendorId/productId pair with the factory; returns 'true'
  48.315 +    // if the factory can handle the device.
  48.316 +    virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const
  48.317 +    {
  48.318 +        OVR_UNUSED2(vendorId, productId);
  48.319 +        return false;
  48.320 +    }
  48.321 +
  48.322 +    // Detects the HID device and adds the DeviceCreateDesc into Devices list, if
  48.323 +    // the device belongs to this factory. Returns 'false', if not.
  48.324 +    virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc)
  48.325 +    {
  48.326 +        OVR_UNUSED2(pdevMgr, desc);
  48.327 +        return false;
  48.328 +    }
  48.329 +    
  48.330 +protected:
  48.331 +    DeviceManagerImpl* pManager;
  48.332 +};
  48.333 +
  48.334 +
  48.335 +//-------------------------------------------------------------------------------------
  48.336 +// ***** DeviceManagerImpl
  48.337 +
  48.338 +// DeviceManagerImpl is a partial default DeviceManager implementation that
  48.339 +// maintains a list of devices and supports their enumeration.
  48.340 +
  48.341 +class DeviceManagerImpl : public DeviceImpl<OVR::DeviceManager>, public ThreadCommandQueue
  48.342 +{
  48.343 +public:
  48.344 +    DeviceManagerImpl();
  48.345 +    ~DeviceManagerImpl();
  48.346 +
  48.347 +    // Constructor helper function to create Descriptor and manager lock during initialization.
  48.348 +    static DeviceCreateDesc* CreateManagerDesc();
  48.349 +
  48.350 +    // DeviceManagerImpl provides partial implementation of Initialize/Shutdown that must
  48.351 +    // be called by the platform-specific derived class.
  48.352 +    virtual bool Initialize(DeviceBase* parent);
  48.353 +    virtual void Shutdown();
  48.354 +
  48.355 +
  48.356 +    // Every DeviceManager has an associated profile manager, which is used to store
  48.357 +    // user settings that may affect device behavior. 
  48.358 +    virtual ProfileManager* GetProfileManager() const { return pProfileManager.GetPtr(); }
  48.359 +
  48.360 +    // Override to return ThreadCommandQueue implementation used to post commands
  48.361 +    // to the background device manager thread (that must be created by Initialize).
  48.362 +    virtual ThreadCommandQueue* GetThreadQueue() = 0;
  48.363 +
  48.364 +    // Returns the thread id of the DeviceManager.
  48.365 +    virtual ThreadId GetThreadId() const = 0;
  48.366 +
  48.367 +    virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args);
  48.368 +
  48.369 +
  48.370 +    // 
  48.371 +    void AddFactory(DeviceFactory* factory)
  48.372 +    {
  48.373 +        // This lock is only needed if we call AddFactory after manager thread creation.
  48.374 +        Lock::Locker scopeLock(GetLock());
  48.375 +        Factories.PushBack(factory);
  48.376 +        factory->AddedToManager(this);        
  48.377 +    }
  48.378 +
  48.379 +    void CallOnDeviceAdded(DeviceCreateDesc* desc)
  48.380 +    {
  48.381 +        HandlerRef.Call(MessageDeviceStatus(Message_DeviceAdded, this, DeviceHandle(desc)));
  48.382 +    }
  48.383 +    void CallOnDeviceRemoved(DeviceCreateDesc* desc)
  48.384 +    {
  48.385 +        HandlerRef.Call(MessageDeviceStatus(Message_DeviceRemoved, this, DeviceHandle(desc)));
  48.386 +    }
  48.387 +
  48.388 +    // Helper to access Common data for a device.
  48.389 +    static DeviceCommon* GetDeviceCommon(DeviceBase* device)
  48.390 +    {
  48.391 +        return device->getDeviceCommon();
  48.392 +    }
  48.393 +
  48.394 +
  48.395 +    // Background-thread callbacks for DeviceCreation/Release. These
  48.396 +    DeviceBase* CreateDevice_MgrThread(DeviceCreateDesc* createDesc, DeviceBase* parent = 0);
  48.397 +    Void        ReleaseDevice_MgrThread(DeviceBase* device);
  48.398 +
  48.399 +   
  48.400 +    // Calls EnumerateDevices() on all factories
  48.401 +    virtual Void EnumerateAllFactoryDevices();
  48.402 +    // Enumerates devices for a particular factory.
  48.403 +    virtual Void EnumerateFactoryDevices(DeviceFactory* factory);
  48.404 +
  48.405 +    virtual HIDDeviceManager* GetHIDDeviceManager() const
  48.406 +    {
  48.407 +        return HidDeviceManager;
  48.408 +    }
  48.409 +
  48.410 +    // Adds device (DeviceCreateDesc*) into Devices. Returns NULL, 
  48.411 +    // if unsuccessful or device is already in the list.
  48.412 +    virtual Ptr<DeviceCreateDesc> AddDevice_NeedsLock(const DeviceCreateDesc& createDesc);
  48.413 +    
  48.414 +    // Finds a device descriptor by path and optional type.
  48.415 +    Ptr<DeviceCreateDesc> FindDevice(const String& path, DeviceType = Device_None);
  48.416 +
  48.417 +    // Finds HID device by HIDDeviceDesc.
  48.418 +    Ptr<DeviceCreateDesc> FindHIDDevice(const HIDDeviceDesc&);
  48.419 +    void DetectHIDDevice(const HIDDeviceDesc&);
  48.420 +
  48.421 +    // Manager Lock-protected list of devices.
  48.422 +    List<DeviceCreateDesc>  Devices;    
  48.423 +
  48.424 +    // Factories used to detect and manage devices.
  48.425 +    List<DeviceFactory>     Factories;
  48.426 +
  48.427 +protected:
  48.428 +    Ptr<HIDDeviceManager>   HidDeviceManager;
  48.429 +    Ptr<ProfileManager>     pProfileManager;
  48.430 +};
  48.431 +
  48.432 +
  48.433 +} // namespace OVR
  48.434 +
  48.435 +#endif
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/libovr/Src/OVR_DeviceMessages.h	Sat Sep 14 16:14:59 2013 +0300
    49.3 @@ -0,0 +1,162 @@
    49.4 +/************************************************************************************
    49.5 +
    49.6 +PublicHeader:   OVR.h
    49.7 +Filename    :   OVR_DeviceMessages.h
    49.8 +Content     :   Definition of messages generated by devices
    49.9 +Created     :   February 5, 2013
   49.10 +Authors     :   Lee Cooper
   49.11 +
   49.12 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   49.13 +
   49.14 +Use of this software is subject to the terms of the Oculus license
   49.15 +agreement provided at the time of installation or download, or which
   49.16 +otherwise accompanies this software in either electronic or hard copy form.
   49.17 +
   49.18 +*************************************************************************************/
   49.19 +
   49.20 +#ifndef OVR_DeviceMessages_h
   49.21 +#define OVR_DeviceMessages_h
   49.22 +
   49.23 +#include "OVR_DeviceConstants.h"
   49.24 +#include "OVR_DeviceHandle.h"
   49.25 +
   49.26 +#include "Kernel/OVR_Math.h"
   49.27 +#include "Kernel/OVR_Array.h"
   49.28 +#include "Kernel/OVR_Color.h"
   49.29 +
   49.30 +namespace OVR {
   49.31 +
   49.32 +class DeviceBase;
   49.33 +class DeviceHandle;
   49.34 +
   49.35 +
   49.36 +#define OVR_MESSAGETYPE(devName, msgIndex)   ((Device_##devName << 8) | msgIndex)
   49.37 +
   49.38 +// MessageType identifies the structure of the Message class; based on the message,
   49.39 +// casting can be used to obtain the exact value.
   49.40 +enum MessageType
   49.41 +{
   49.42 +    // Used for unassigned message types.
   49.43 +    Message_None            = 0,
   49.44 +
   49.45 +    // Device Manager Messages
   49.46 +    Message_DeviceAdded             = OVR_MESSAGETYPE(Manager, 0),  // A new device is detected by manager.
   49.47 +    Message_DeviceRemoved           = OVR_MESSAGETYPE(Manager, 1),  // Existing device has been plugged/unplugged.
   49.48 +    // Sensor Messages
   49.49 +    Message_BodyFrame               = OVR_MESSAGETYPE(Sensor, 0),   // Emitted by sensor at regular intervals.
   49.50 +    // Latency Tester Messages
   49.51 +    Message_LatencyTestSamples          = OVR_MESSAGETYPE(LatencyTester, 0),
   49.52 +    Message_LatencyTestColorDetected    = OVR_MESSAGETYPE(LatencyTester, 1),
   49.53 +    Message_LatencyTestStarted          = OVR_MESSAGETYPE(LatencyTester, 2),
   49.54 +    Message_LatencyTestButton           = OVR_MESSAGETYPE(LatencyTester, 3),
   49.55 +
   49.56 +};
   49.57 +
   49.58 +//-------------------------------------------------------------------------------------
   49.59 +// Base class for all messages.
   49.60 +class Message
   49.61 +{
   49.62 +public:
   49.63 +    Message(MessageType type = Message_None,
   49.64 +            DeviceBase* pdev = 0) : Type(type), pDevice(pdev)
   49.65 +    { }
   49.66 +
   49.67 +    MessageType Type;    // What kind of message this is.
   49.68 +    DeviceBase* pDevice; // Device that emitted the message.
   49.69 +};
   49.70 +
   49.71 +
   49.72 +// Sensor BodyFrame notification.
   49.73 +// Sensor uses Right-Handed coordinate system to return results, with the following
   49.74 +// axis definitions:
   49.75 +//  - Y Up positive
   49.76 +//  - X Right Positive
   49.77 +//  - Z Back Positive
   49.78 +// Rotations a counter-clockwise (CCW) while looking in the negative direction
   49.79 +// of the axis. This means they are interpreted as follows:
   49.80 +//  - Roll is rotation around Z, counter-clockwise (tilting left) in XY plane.
   49.81 +//  - Yaw is rotation around Y, positive for turning left.
   49.82 +//  - Pitch is rotation around X, positive for pitching up.
   49.83 +
   49.84 +class MessageBodyFrame : public Message
   49.85 +{
   49.86 +public:
   49.87 +    MessageBodyFrame(DeviceBase* dev)
   49.88 +        : Message(Message_BodyFrame, dev), Temperature(0.0f), TimeDelta(0.0f)
   49.89 +    {
   49.90 +    }
   49.91 +
   49.92 +    Vector3f Acceleration;   // Acceleration in m/s^2.
   49.93 +    Vector3f RotationRate;   // Angular velocity in rad/s^2.
   49.94 +    Vector3f MagneticField;  // Magnetic field strength in Gauss.
   49.95 +    float    Temperature;    // Temperature reading on sensor surface, in degrees Celsius.
   49.96 +    float    TimeDelta;      // Time passed since last Body Frame, in seconds.
   49.97 +};
   49.98 +
   49.99 +// Sent when we receive a device status changes (e.g.:
  49.100 +// Message_DeviceAdded, Message_DeviceRemoved).
  49.101 +class MessageDeviceStatus : public Message
  49.102 +{
  49.103 +public:
  49.104 +	MessageDeviceStatus(MessageType type, DeviceBase* dev, const DeviceHandle &hdev)
  49.105 +		: Message(type, dev), Handle(hdev) { }
  49.106 +
  49.107 +	DeviceHandle Handle;
  49.108 +};
  49.109 +
  49.110 +//-------------------------------------------------------------------------------------
  49.111 +// ***** Latency Tester
  49.112 +
  49.113 +// Sent when we receive Latency Tester samples.
  49.114 +class MessageLatencyTestSamples : public Message
  49.115 +{
  49.116 +public:
  49.117 +    MessageLatencyTestSamples(DeviceBase* dev)
  49.118 +        : Message(Message_LatencyTestSamples, dev)
  49.119 +    {
  49.120 +    }
  49.121 +
  49.122 +    Array<Color>     Samples;
  49.123 +};
  49.124 +
  49.125 +// Sent when a Latency Tester 'color detected' event occurs.
  49.126 +class MessageLatencyTestColorDetected : public Message
  49.127 +{
  49.128 +public:
  49.129 +    MessageLatencyTestColorDetected(DeviceBase* dev)
  49.130 +        : Message(Message_LatencyTestColorDetected, dev)
  49.131 +    {
  49.132 +    }
  49.133 +
  49.134 +    UInt16      Elapsed;
  49.135 +    Color       DetectedValue;
  49.136 +    Color       TargetValue;
  49.137 +};
  49.138 +
  49.139 +// Sent when a Latency Tester 'change color' event occurs.
  49.140 +class MessageLatencyTestStarted : public Message
  49.141 +{
  49.142 +public:
  49.143 +    MessageLatencyTestStarted(DeviceBase* dev)
  49.144 +        : Message(Message_LatencyTestStarted, dev)
  49.145 +    {
  49.146 +    }
  49.147 +
  49.148 +    Color    TargetValue;
  49.149 +};
  49.150 +
  49.151 +// Sent when a Latency Tester 'button' event occurs.
  49.152 +class MessageLatencyTestButton : public Message
  49.153 +{
  49.154 +public:
  49.155 +    MessageLatencyTestButton(DeviceBase* dev)
  49.156 +        : Message(Message_LatencyTestButton, dev)
  49.157 +    {
  49.158 +    }
  49.159 +
  49.160 +};
  49.161 +
  49.162 +
  49.163 +} // namespace OVR
  49.164 +
  49.165 +#endif
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/libovr/Src/OVR_HIDDevice.h	Sat Sep 14 16:14:59 2013 +0300
    50.3 @@ -0,0 +1,143 @@
    50.4 +/************************************************************************************
    50.5 +
    50.6 +Filename    :   OVR_HIDDevice.h
    50.7 +Content     :   Cross platform HID device interface.
    50.8 +Created     :   February 22, 2013
    50.9 +Authors     :   Lee Cooper
   50.10 +
   50.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   50.12 +
   50.13 +Use of this software is subject to the terms of the Oculus license
   50.14 +agreement provided at the time of installation or download, or which
   50.15 +otherwise accompanies this software in either electronic or hard copy form.
   50.16 +
   50.17 +*************************************************************************************/
   50.18 +
   50.19 +#ifndef OVR_HIDDevice_h
   50.20 +#define OVR_HIDDevice_h
   50.21 +
   50.22 +#include "OVR_HIDDeviceBase.h"
   50.23 +
   50.24 +#include "Kernel/OVR_RefCount.h"
   50.25 +#include "Kernel/OVR_String.h"
   50.26 +#include "Kernel/OVR_Timer.h"
   50.27 +
   50.28 +namespace OVR {
   50.29 +
   50.30 +class HIDDevice;
   50.31 +class DeviceManager;
   50.32 +
   50.33 +// HIDDeviceDesc contains interesting attributes of a HID device, including a Path
   50.34 +// that can be used to create it.
   50.35 +struct HIDDeviceDesc
   50.36 +{
   50.37 +    UInt16  VendorId;
   50.38 +    UInt16  ProductId;
   50.39 +    UInt16  VersionNumber;
   50.40 +    UInt16  Usage;
   50.41 +    UInt16  UsagePage;
   50.42 +    String  Path;           // Platform specific.
   50.43 +    String  Manufacturer;
   50.44 +    String  Product;
   50.45 +    String  SerialNumber;
   50.46 +};
   50.47 +
   50.48 +// HIDEnumerateVisitor exposes a Visit interface called for every detected device
   50.49 +// by HIDDeviceManager::Enumerate. 
   50.50 +class HIDEnumerateVisitor
   50.51 +{
   50.52 +public:
   50.53 +
   50.54 +    // Should return true if we are interested in supporting
   50.55 +    // this HID VendorId and ProductId pair.
   50.56 +    virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId)
   50.57 +    { OVR_UNUSED2(vendorId, productId); return true; }
   50.58 +
   50.59 +    // Override to get notified about available device. Will only be called for
   50.60 +    // devices that matched MatchVendorProduct.
   50.61 +    virtual void Visit(HIDDevice&, const HIDDeviceDesc&) { }
   50.62 +};
   50.63 +
   50.64 +
   50.65 +//-------------------------------------------------------------------------------------
   50.66 +// ***** HIDDeviceManager
   50.67 +
   50.68 +// Internal manager for enumerating and opening HID devices.
   50.69 +// If an OVR::DeviceManager is created then an OVR::HIDDeviceManager will automatically be created and can be accessed from the
   50.70 +// DeviceManager by calling 'GetHIDDeviceManager()'. When using HIDDeviceManager in standalone mode, the client must call
   50.71 +// 'Create' below.
   50.72 +class HIDDeviceManager : public RefCountBase<HIDDeviceManager>
   50.73 +{
   50.74 +public:
   50.75 +
   50.76 +    // Creates a new HIDDeviceManager. Only one instance of HIDDeviceManager should be created at a time.
   50.77 +    static HIDDeviceManager* Create();
   50.78 +
   50.79 +    // Enumerate HID devices using a HIDEnumerateVisitor derived visitor class.
   50.80 +    virtual bool Enumerate(HIDEnumerateVisitor* enumVisitor) = 0;
   50.81 +
   50.82 +    // Open a HID device with the specified path.
   50.83 +    virtual HIDDevice* Open(const String& path) = 0;
   50.84 +
   50.85 +protected:
   50.86 +    HIDDeviceManager()
   50.87 +    { }
   50.88 +};
   50.89 +
   50.90 +//-------------------------------------------------------------------------------------
   50.91 +// ***** HIDDevice
   50.92 +
   50.93 +// HID device object. This is designed to be operated in synchronous
   50.94 +// and asynchronous modes. With no handler set, input messages will be
   50.95 +// stored and can be retrieved by calling 'Read' or 'ReadBlocking'.
   50.96 +class HIDDevice : public RefCountBase<HIDDevice>, public HIDDeviceBase
   50.97 +{
   50.98 +public:
   50.99 +
  50.100 +    HIDDevice()
  50.101 +     :  Handler(NULL)
  50.102 +    {
  50.103 +    }
  50.104 +
  50.105 +    virtual ~HIDDevice() {}
  50.106 +
  50.107 +    virtual bool SetFeatureReport(UByte* data, UInt32 length) = 0;
  50.108 +    virtual bool GetFeatureReport(UByte* data, UInt32 length) = 0;
  50.109 +
  50.110 +// Not yet implemented.
  50.111 +/*
  50.112 +    virtual bool Write(UByte* data, UInt32 length) = 0;
  50.113 +
  50.114 +    virtual bool Read(UByte* pData, UInt32 length, UInt32 timeoutMilliS) = 0;
  50.115 +    virtual bool ReadBlocking(UByte* pData, UInt32 length) = 0;
  50.116 +*/
  50.117 +
  50.118 +    class HIDHandler
  50.119 +    {
  50.120 +    public:
  50.121 +        virtual void OnInputReport(UByte* pData, UInt32 length)
  50.122 +        { OVR_UNUSED2(pData, length); }
  50.123 +
  50.124 +        virtual UInt64 OnTicks(UInt64 ticksMks)
  50.125 +        { OVR_UNUSED1(ticksMks);  return Timer::MksPerSecond * 1000; ; }
  50.126 +
  50.127 +        enum HIDDeviceMessageType
  50.128 +        {
  50.129 +            HIDDeviceMessage_DeviceAdded    = 0,
  50.130 +            HIDDeviceMessage_DeviceRemoved  = 1
  50.131 +        };
  50.132 +
  50.133 +        virtual void OnDeviceMessage(HIDDeviceMessageType messageType) 
  50.134 +        { OVR_UNUSED1(messageType); }
  50.135 +    };
  50.136 +
  50.137 +    void SetHandler(HIDHandler* handler)
  50.138 +    { Handler = handler; }
  50.139 +
  50.140 +protected:
  50.141 +    HIDHandler* Handler;
  50.142 +};
  50.143 +
  50.144 +} // namespace OVR
  50.145 +
  50.146 +#endif
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/libovr/Src/OVR_HIDDeviceBase.h	Sat Sep 14 16:14:59 2013 +0300
    51.3 @@ -0,0 +1,40 @@
    51.4 +/************************************************************************************
    51.5 +
    51.6 +PublicHeader:   OVR.h
    51.7 +Filename    :   OVR_HIDDeviceBase.h
    51.8 +Content     :   Definition of HID device interface.
    51.9 +Created     :   March 11, 2013
   51.10 +Authors     :   Lee Cooper
   51.11 +
   51.12 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   51.13 +
   51.14 +Use of this software is subject to the terms of the Oculus license
   51.15 +agreement provided at the time of installation or download, or which
   51.16 +otherwise accompanies this software in either electronic or hard copy form.
   51.17 +
   51.18 +*************************************************************************************/
   51.19 +
   51.20 +#ifndef OVR_HIDDeviceBase_h
   51.21 +#define OVR_HIDDeviceBase_h
   51.22 +
   51.23 +#include "Kernel/OVR_Types.h"
   51.24 +
   51.25 +namespace OVR {
   51.26 +
   51.27 +//-------------------------------------------------------------------------------------
   51.28 +// ***** HIDDeviceBase
   51.29 +
   51.30 +// Base interface for HID devices.
   51.31 +class HIDDeviceBase
   51.32 +{
   51.33 +public:
   51.34 +
   51.35 +    virtual ~HIDDeviceBase() { }
   51.36 +
   51.37 +    virtual bool SetFeatureReport(UByte* data, UInt32 length) = 0;
   51.38 +    virtual bool GetFeatureReport(UByte* data, UInt32 length) = 0;
   51.39 +};
   51.40 +
   51.41 +} // namespace OVR
   51.42 +
   51.43 +#endif
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/libovr/Src/OVR_HIDDeviceImpl.h	Sat Sep 14 16:14:59 2013 +0300
    52.3 @@ -0,0 +1,203 @@
    52.4 +/************************************************************************************
    52.5 +
    52.6 +Filename    :   OVR_HIDDeviceImpl.h
    52.7 +Content     :   Implementation of HIDDevice.
    52.8 +Created     :   March 7, 2013
    52.9 +Authors     :   Lee Cooper
   52.10 +
   52.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   52.12 +
   52.13 +Use of this software is subject to the terms of the Oculus license
   52.14 +agreement provided at the time of installation or download, or which
   52.15 +otherwise accompanies this software in either electronic or hard copy form.
   52.16 +
   52.17 +*************************************************************************************/
   52.18 +
   52.19 +#ifndef OVR_HIDDeviceImpl_h
   52.20 +#define OVR_HIDDeviceImpl_h
   52.21 +
   52.22 +//#include "OVR_Device.h"
   52.23 +#include "OVR_DeviceImpl.h"
   52.24 +
   52.25 +namespace OVR {
   52.26 +
   52.27 +//-------------------------------------------------------------------------------------
   52.28 +class HIDDeviceCreateDesc : public DeviceCreateDesc
   52.29 +{
   52.30 +public:
   52.31 +    HIDDeviceCreateDesc(DeviceFactory* factory, DeviceType type, const HIDDeviceDesc& hidDesc)
   52.32 +        : DeviceCreateDesc(factory, type), HIDDesc(hidDesc) { }
   52.33 +    HIDDeviceCreateDesc(const HIDDeviceCreateDesc& other)
   52.34 +        : DeviceCreateDesc(other.pFactory, other.Type), HIDDesc(other.HIDDesc) { }
   52.35 +
   52.36 +    virtual bool MatchDevice(const String& path)
   52.37 +    {
   52.38 +        // should it be case insensitive?
   52.39 +        return HIDDesc.Path.CompareNoCase(path) == 0;
   52.40 +    }
   52.41 +
   52.42 +    HIDDeviceDesc HIDDesc;
   52.43 +};
   52.44 +
   52.45 +//-------------------------------------------------------------------------------------
   52.46 +template<class B>
   52.47 +class HIDDeviceImpl : public DeviceImpl<B>, public HIDDevice::HIDHandler
   52.48 +{
   52.49 +public:
   52.50 +    HIDDeviceImpl(HIDDeviceCreateDesc* createDesc, DeviceBase* parent)
   52.51 +     :  DeviceImpl<B>(createDesc, parent)        
   52.52 +    {
   52.53 +    }
   52.54 +
   52.55 +    // HIDDevice::Handler interface.
   52.56 +    virtual void OnDeviceMessage(HIDDeviceMessageType messageType)
   52.57 +    {
   52.58 +        MessageType handlerMessageType;
   52.59 +        switch (messageType) {
   52.60 +            case HIDDeviceMessage_DeviceAdded:
   52.61 +                handlerMessageType = Message_DeviceAdded;
   52.62 +                break;
   52.63 +
   52.64 +            case HIDDeviceMessage_DeviceRemoved:
   52.65 +                handlerMessageType = Message_DeviceRemoved;
   52.66 +                break;
   52.67 +
   52.68 +            default: OVR_ASSERT(0); return;
   52.69 +        }
   52.70 +
   52.71 +        // Do device notification.
   52.72 +        {
   52.73 +            Lock::Locker scopeLock(this->HandlerRef.GetLock());
   52.74 +
   52.75 +            if (this->HandlerRef.GetHandler())
   52.76 +            {
   52.77 +                MessageDeviceStatus status(handlerMessageType, this, OVR::DeviceHandle(this->pCreateDesc));
   52.78 +                this->HandlerRef.GetHandler()->OnMessage(status);
   52.79 +            }
   52.80 +        }
   52.81 +
   52.82 +        // Do device manager notification.
   52.83 +        DeviceManagerImpl*   manager = this->GetManagerImpl();
   52.84 +        switch (handlerMessageType) {
   52.85 +            case Message_DeviceAdded:
   52.86 +                manager->CallOnDeviceAdded(this->pCreateDesc);
   52.87 +                break;
   52.88 +                
   52.89 +            case Message_DeviceRemoved:
   52.90 +                manager->CallOnDeviceRemoved(this->pCreateDesc);
   52.91 +                break;
   52.92 +                
   52.93 +            default:;
   52.94 +        }
   52.95 +    }
   52.96 +
   52.97 +    virtual bool Initialize(DeviceBase* parent)
   52.98 +    {
   52.99 +        // Open HID device.
  52.100 +        HIDDeviceDesc&		hidDesc = *getHIDDesc();
  52.101 +        HIDDeviceManager*   pManager = GetHIDDeviceManager();
  52.102 +
  52.103 +
  52.104 +        HIDDevice* device = pManager->Open(hidDesc.Path);
  52.105 +        if (!device)
  52.106 +        {
  52.107 +            return false;
  52.108 +        }
  52.109 +
  52.110 +        InternalDevice = *device;
  52.111 +        InternalDevice->SetHandler(this);
  52.112 +
  52.113 +        // AddRef() to parent, forcing chain to stay alive.
  52.114 +        DeviceImpl<B>::pParent = parent;
  52.115 +
  52.116 +        return true;
  52.117 +    }
  52.118 +
  52.119 +    virtual void Shutdown()
  52.120 +    {   
  52.121 +        InternalDevice->SetHandler(NULL);
  52.122 +
  52.123 +        // Remove the handler, if any.
  52.124 +        this->HandlerRef.SetHandler(0);
  52.125 +
  52.126 +        DeviceImpl<B>::pParent.Clear();
  52.127 +    }
  52.128 +
  52.129 +    DeviceManager* GetDeviceManager()
  52.130 +    {
  52.131 +        return DeviceImpl<B>::pCreateDesc->GetManagerImpl();
  52.132 +    }
  52.133 +
  52.134 +    HIDDeviceManager* GetHIDDeviceManager()
  52.135 +    {
  52.136 +        return DeviceImpl<B>::pCreateDesc->GetManagerImpl()->GetHIDDeviceManager();
  52.137 +    }
  52.138 +
  52.139 +
  52.140 +    struct WriteData
  52.141 +    {
  52.142 +        enum { BufferSize = 64 };
  52.143 +        UByte Buffer[64];
  52.144 +        UPInt Size;
  52.145 +
  52.146 +        WriteData(UByte* data, UPInt size) : Size(size)
  52.147 +        {
  52.148 +            OVR_ASSERT(size <= BufferSize);
  52.149 +            memcpy(Buffer, data, size);
  52.150 +        }
  52.151 +    };
  52.152 +
  52.153 +    bool SetFeatureReport(UByte* data, UInt32 length)
  52.154 +    { 
  52.155 +        WriteData writeData(data, length);
  52.156 +
  52.157 +        // Push call with wait.
  52.158 +        bool result = false;
  52.159 +
  52.160 +		ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue();
  52.161 +        if (!pQueue->PushCallAndWaitResult(this, &HIDDeviceImpl::setFeatureReport, &result, writeData))
  52.162 +            return false;
  52.163 +
  52.164 +        return result;
  52.165 +    }
  52.166 +
  52.167 +    bool setFeatureReport(const WriteData& data)
  52.168 +    {
  52.169 +        return InternalDevice->SetFeatureReport((UByte*) data.Buffer, (UInt32) data.Size);
  52.170 +    }
  52.171 +
  52.172 +    bool GetFeatureReport(UByte* data, UInt32 length)
  52.173 +    { 
  52.174 +        bool result = false;
  52.175 +
  52.176 +		ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue();
  52.177 +        if (!pQueue->PushCallAndWaitResult(this, &HIDDeviceImpl::getFeatureReport, &result, data, length))
  52.178 +            return false;
  52.179 +
  52.180 +        return result;
  52.181 +    }
  52.182 +
  52.183 +    bool getFeatureReport(UByte* data, UInt32 length)
  52.184 +    {
  52.185 +        return InternalDevice->GetFeatureReport(data, length);
  52.186 +    }
  52.187 +
  52.188 +protected:
  52.189 +    HIDDevice* GetInternalDevice() const
  52.190 +    {
  52.191 +        return InternalDevice;
  52.192 +    }
  52.193 +
  52.194 +    HIDDeviceDesc* getHIDDesc() const
  52.195 +    { return &getCreateDesc()->HIDDesc; }
  52.196 +
  52.197 +    HIDDeviceCreateDesc* getCreateDesc() const
  52.198 +    { return (HIDDeviceCreateDesc*) &(*DeviceImpl<B>::pCreateDesc); }
  52.199 +
  52.200 +private:
  52.201 +    Ptr<HIDDevice> InternalDevice;
  52.202 +};
  52.203 +
  52.204 +} // namespace OVR
  52.205 +
  52.206 +#endif
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/libovr/Src/OVR_JSON.cpp	Sat Sep 14 16:14:59 2013 +0300
    53.3 @@ -0,0 +1,1056 @@
    53.4 +/************************************************************************************
    53.5 +
    53.6 +PublicHeader:   None
    53.7 +Filename    :   OVR_JSON.h
    53.8 +Content     :   JSON format reader and writer
    53.9 +Created     :   April 9, 2013
   53.10 +Author      :   Brant Lewis
   53.11 +Notes       :
   53.12 +  The code is a derivative of the cJSON library written by Dave Gamble and subject 
   53.13 +  to the following permissive copyright.
   53.14 +
   53.15 +  Copyright (c) 2009 Dave Gamble
   53.16 + 
   53.17 +  Permission is hereby granted, free of charge, to any person obtaining a copy
   53.18 +  of this software and associated documentation files (the "Software"), to deal
   53.19 +  in the Software without restriction, including without limitation the rights
   53.20 +  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   53.21 +  copies of the Software, and to permit persons to whom the Software is
   53.22 +  furnished to do so, subject to the following conditions:
   53.23 + 
   53.24 +  The above copyright notice and this permission notice shall be included in
   53.25 +  all copies or substantial portions of the Software.
   53.26 + 
   53.27 +  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   53.28 +  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   53.29 +  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   53.30 +  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   53.31 +  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   53.32 +  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   53.33 +  THE SOFTWARE.
   53.34 +
   53.35 +
   53.36 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   53.37 +
   53.38 +Use of this software is subject to the terms of the Oculus license
   53.39 +agreement provided at the time of installation or download, or which
   53.40 +otherwise accompanies this software in either electronic or hard copy form.
   53.41 +
   53.42 +************************************************************************************/
   53.43 +
   53.44 +#include <string.h>
   53.45 +#include <stdio.h>
   53.46 +#include <math.h>
   53.47 +#include <stdlib.h>
   53.48 +#include <float.h>
   53.49 +#include <limits.h>
   53.50 +#include <ctype.h>
   53.51 +#include "OVR_JSON.h"
   53.52 +#include "Kernel/OVR_SysFile.h"
   53.53 +#include "Kernel/OVR_Log.h"
   53.54 +
   53.55 +namespace OVR {
   53.56 +
   53.57 +
   53.58 +//-----------------------------------------------------------------------------
   53.59 +// Create a new copy of a string
   53.60 +static char* JSON_strdup(const char* str)
   53.61 +{
   53.62 +    UPInt len  = OVR_strlen(str) + 1;
   53.63 +    char* copy = (char*)OVR_ALLOC(len);
   53.64 +    if (!copy)
   53.65 +        return 0;
   53.66 +    memcpy(copy, str, len);
   53.67 +    return copy;
   53.68 +}
   53.69 +
   53.70 +
   53.71 +//-----------------------------------------------------------------------------
   53.72 +// Render the number from the given item into a string.
   53.73 +static char* PrintNumber(double d)
   53.74 +{
   53.75 +	char *str;
   53.76 +	//double d=item->valuedouble;
   53.77 +    int valueint = (int)d;
   53.78 +	if (fabs(((double)valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
   53.79 +	{
   53.80 +		str=(char*)OVR_ALLOC(21);	// 2^64+1 can be represented in 21 chars.
   53.81 +		if (str)
   53.82 +            OVR_sprintf(str, 21, "%d", valueint);
   53.83 +	}
   53.84 +	else
   53.85 +	{
   53.86 +		str=(char*)OVR_ALLOC(64);	// This is a nice tradeoff.
   53.87 +		if (str)
   53.88 +		{
   53.89 +			if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)
   53.90 +                OVR_sprintf(str, 64, "%.0f", d);
   53.91 +			else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9)
   53.92 +                OVR_sprintf(str, 64, "%e", d);
   53.93 +			else
   53.94 +                OVR_sprintf(str, 64, "%f", d);
   53.95 +		}
   53.96 +	}
   53.97 +	return str;
   53.98 +}
   53.99 +
  53.100 +// Parse the input text into an un-escaped cstring, and populate item.
  53.101 +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
  53.102 +
  53.103 +// Helper to assign error sting and return 0.
  53.104 +const char* AssignError(const char** perror, const char *errorMessage)
  53.105 +{
  53.106 +    if (perror)
  53.107 +        *perror = errorMessage;
  53.108 +    return 0;
  53.109 +}
  53.110 +
  53.111 +//-----------------------------------------------------------------------------
  53.112 +// ***** JSON Node class
  53.113 +
  53.114 +JSON::JSON(JSONItemType itemType)
  53.115 +    : Type(itemType), dValue(0.0)
  53.116 +{
  53.117 +}
  53.118 +
  53.119 +JSON::~JSON()
  53.120 +{
  53.121 +    JSON* child = Children.GetFirst();
  53.122 +    while (!Children.IsNull(child))
  53.123 +    {
  53.124 +        child->RemoveNode();
  53.125 +        child->Release();
  53.126 +        child = Children.GetFirst();
  53.127 +    }
  53.128 +}
  53.129 +
  53.130 +//-----------------------------------------------------------------------------
  53.131 +// Parse the input text to generate a number, and populate the result into item
  53.132 +// Returns the text position after the parsed number
  53.133 +const char* JSON::parseNumber(const char *num)
  53.134 +{
  53.135 +    const char* num_start = num;
  53.136 +    double      n=0, sign=1, scale=0;
  53.137 +    int         subscale     = 0,
  53.138 +                signsubscale = 1;
  53.139 +
  53.140 +	// Could use sscanf for this?
  53.141 +	if (*num=='-') 
  53.142 +        sign=-1,num++;	// Has sign?
  53.143 +	if (*num=='0')
  53.144 +        num++;			// is zero
  53.145 +	
  53.146 +    if (*num>='1' && *num<='9')	
  53.147 +    {
  53.148 +        do
  53.149 +        {   
  53.150 +            n=(n*10.0)+(*num++ -'0');
  53.151 +        }
  53.152 +        while (*num>='0' && *num<='9');	// Number?
  53.153 +    }
  53.154 +
  53.155 +	if (*num=='.' && num[1]>='0' && num[1]<='9')
  53.156 +    {
  53.157 +        num++;
  53.158 +        do
  53.159 +        {
  53.160 +            n=(n*10.0)+(*num++ -'0');
  53.161 +            scale--;
  53.162 +        }
  53.163 +        while (*num>='0' && *num<='9');  // Fractional part?
  53.164 +    }
  53.165 +
  53.166 +	if (*num=='e' || *num=='E')		// Exponent?
  53.167 +	{
  53.168 +        num++;
  53.169 +        if (*num=='+')
  53.170 +            num++;
  53.171 +        else if (*num=='-')
  53.172 +        {
  53.173 +            signsubscale=-1;
  53.174 +            num++;		// With sign?
  53.175 +        }
  53.176 +
  53.177 +		while (*num>='0' && *num<='9')
  53.178 +            subscale=(subscale*10)+(*num++ - '0');	// Number?
  53.179 +	}
  53.180 +
  53.181 +    // Number = +/- number.fraction * 10^+/- exponent
  53.182 +	n = sign*n*pow(10.0,(scale+subscale*signsubscale));
  53.183 +
  53.184 +    // Assign parsed value.
  53.185 +	Type   = JSON_Number;
  53.186 +    dValue = n;
  53.187 +    Value.AssignString(num_start, num - num_start);
  53.188 +    
  53.189 +	return num;
  53.190 +}
  53.191 +
  53.192 +// Parses a hex string up to the specified number of digits.
  53.193 +// Returns the first character after the string.
  53.194 +const char* ParseHex(unsigned* val, unsigned digits, const char* str)
  53.195 +{
  53.196 +    *val = 0;
  53.197 +
  53.198 +    for(unsigned digitCount = 0; digitCount < digits; digitCount++, str++)
  53.199 +    {
  53.200 +        unsigned v = *str;
  53.201 +
  53.202 +        if ((v >= '0') && (v <= '9'))
  53.203 +            v -= '0';
  53.204 +        else if ((v >= 'a') && (v <= 'f'))
  53.205 +            v = 10 + v - 'a';
  53.206 +        else if ((v >= 'A') && (v <= 'F'))
  53.207 +            v = 10 + v - 'A';
  53.208 +        else
  53.209 +            break;
  53.210 +
  53.211 +        *val = *val * 16 + v;
  53.212 +    }
  53.213 +
  53.214 +    return str;
  53.215 +}
  53.216 +
  53.217 +//-----------------------------------------------------------------------------
  53.218 +// Parses the input text into a string item and returns the text position after
  53.219 +// the parsed string
  53.220 +const char* JSON::parseString(const char* str, const char** perror)
  53.221 +{
  53.222 +	const char* ptr = str+1;
  53.223 +    const char* p;
  53.224 +    char*       ptr2;
  53.225 +    char*       out;
  53.226 +    int         len=0;
  53.227 +    unsigned    uc, uc2;
  53.228 +	
  53.229 +    if (*str!='\"')
  53.230 +    {
  53.231 +        return AssignError(perror, "Syntax Error: Missing quote");
  53.232 +    }
  53.233 +	
  53.234 +	while (*ptr!='\"' && *ptr && ++len)
  53.235 +    {   
  53.236 +        if (*ptr++ == '\\') ptr++;	// Skip escaped quotes.
  53.237 +    }
  53.238 +	
  53.239 +    // This is how long we need for the string, roughly.
  53.240 +	out=(char*)OVR_ALLOC(len+1);
  53.241 +	if (!out)
  53.242 +        return 0;
  53.243 +	
  53.244 +	ptr = str+1;
  53.245 +    ptr2= out;
  53.246 +
  53.247 +	while (*ptr!='\"' && *ptr)
  53.248 +	{
  53.249 +		if (*ptr!='\\')
  53.250 +        {
  53.251 +            *ptr2++ = *ptr++;
  53.252 +        }
  53.253 +		else
  53.254 +		{
  53.255 +			ptr++;
  53.256 +			switch (*ptr)
  53.257 +			{
  53.258 +				case 'b': *ptr2++ = '\b';	break;
  53.259 +				case 'f': *ptr2++ = '\f';	break;
  53.260 +				case 'n': *ptr2++ = '\n';	break;
  53.261 +				case 'r': *ptr2++ = '\r';	break;
  53.262 +				case 't': *ptr2++ = '\t';	break;
  53.263 +
  53.264 +                // Transcode utf16 to utf8.
  53.265 +                case 'u':
  53.266 +
  53.267 +                    // Get the unicode char.
  53.268 +                    p = ParseHex(&uc, 4, ptr + 1);
  53.269 +                    if (ptr != p)
  53.270 +                        ptr = p - 1;
  53.271 +
  53.272 +					if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0)
  53.273 +                        break;	// Check for invalid.
  53.274 +
  53.275 +                    // UTF16 surrogate pairs.
  53.276 +					if (uc>=0xD800 && uc<=0xDBFF)
  53.277 +					{
  53.278 +						if (ptr[1]!='\\' || ptr[2]!='u')
  53.279 +                            break;	// Missing second-half of surrogate.
  53.280 +
  53.281 +                        p= ParseHex(&uc2, 4, ptr + 3);
  53.282 +                        if (ptr != p)
  53.283 +                            ptr = p - 1;
  53.284 +                        
  53.285 +						if (uc2<0xDC00 || uc2>0xDFFF)
  53.286 +                            break;	// Invalid second-half of surrogate.
  53.287 +
  53.288 +						uc = 0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
  53.289 +					}
  53.290 +
  53.291 +					len=4;
  53.292 +                    
  53.293 +                    if (uc<0x80)
  53.294 +                        len=1;
  53.295 +                    else if (uc<0x800)
  53.296 +                        len=2;
  53.297 +                    else if (uc<0x10000)
  53.298 +                        len=3;
  53.299 +                    
  53.300 +                    ptr2+=len;
  53.301 +					
  53.302 +					switch (len)
  53.303 +                    {
  53.304 +						case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
  53.305 +						case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
  53.306 +						case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
  53.307 +						case 1: *--ptr2 = (char)(uc | firstByteMark[len]);
  53.308 +					}
  53.309 +					ptr2+=len;
  53.310 +					break;
  53.311 +
  53.312 +                default:
  53.313 +                    *ptr2++ = *ptr;
  53.314 +                    break;
  53.315 +			}
  53.316 +			ptr++;
  53.317 +		}
  53.318 +	}
  53.319 +
  53.320 +	*ptr2 = 0;
  53.321 +	if (*ptr=='\"')
  53.322 +        ptr++;
  53.323 +	
  53.324 +    // Make a copy of the string 
  53.325 +    Value=out;
  53.326 +    OVR_FREE(out);
  53.327 +	Type=JSON_String;
  53.328 +
  53.329 +	return ptr;
  53.330 +}
  53.331 +
  53.332 +//-----------------------------------------------------------------------------
  53.333 +// Render the string provided to an escaped version that can be printed.
  53.334 +char* PrintString(const char* str)
  53.335 +{
  53.336 +	const char *ptr;
  53.337 +    char *ptr2,*out;
  53.338 +    int len=0;
  53.339 +    unsigned char token;
  53.340 +	
  53.341 +	if (!str)
  53.342 +        return JSON_strdup("");
  53.343 +	ptr=str;
  53.344 +    
  53.345 +    token=*ptr;
  53.346 +    while (token && ++len)\
  53.347 +    {
  53.348 +        if (strchr("\"\\\b\f\n\r\t",token))
  53.349 +            len++;
  53.350 +        else if (token<32) 
  53.351 +            len+=5;
  53.352 +        ptr++;
  53.353 +        token=*ptr;
  53.354 +    }
  53.355 +	
  53.356 +	int buff_size = len+3;
  53.357 +    out=(char*)OVR_ALLOC(buff_size);
  53.358 +	if (!out)
  53.359 +        return 0;
  53.360 +
  53.361 +	ptr2 = out;
  53.362 +    ptr  = str;
  53.363 +	*ptr2++ = '\"';
  53.364 +
  53.365 +	while (*ptr)
  53.366 +	{
  53.367 +		if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') 
  53.368 +            *ptr2++=*ptr++;
  53.369 +		else
  53.370 +		{
  53.371 +			*ptr2++='\\';
  53.372 +			switch (token=*ptr++)
  53.373 +			{
  53.374 +				case '\\':	*ptr2++='\\';	break;
  53.375 +				case '\"':	*ptr2++='\"';	break;
  53.376 +				case '\b':	*ptr2++='b';	break;
  53.377 +				case '\f':	*ptr2++='f';	break;
  53.378 +				case '\n':	*ptr2++='n';	break;
  53.379 +				case '\r':	*ptr2++='r';	break;
  53.380 +				case '\t':	*ptr2++='t';	break;
  53.381 +				default: 
  53.382 +                    OVR_sprintf(ptr2, buff_size - (ptr2-out), "u%04x",token);
  53.383 +                    ptr2+=5;
  53.384 +                    break;	// Escape and print.
  53.385 +			}
  53.386 +		}
  53.387 +	}
  53.388 +	*ptr2++='\"';
  53.389 +    *ptr2++=0;
  53.390 +	return out;
  53.391 +}
  53.392 +
  53.393 +//-----------------------------------------------------------------------------
  53.394 +// Utility to jump whitespace and cr/lf
  53.395 +static const char* skip(const char* in)
  53.396 +{
  53.397 +    while (in && *in && (unsigned char)*in<=' ') 
  53.398 +        in++; 
  53.399 +    return in;
  53.400 +}
  53.401 +
  53.402 +//-----------------------------------------------------------------------------
  53.403 +// Parses the supplied buffer of JSON text and returns a JSON object tree
  53.404 +// The returned object must be Released after use
  53.405 +JSON* JSON::Parse(const char* buff, const char** perror)
  53.406 +{
  53.407 +    const char* end = 0;
  53.408 +	JSON*       json = new JSON();
  53.409 +	
  53.410 +	if (!json)
  53.411 +    {
  53.412 +        AssignError(perror, "Error: Failed to allocate memory");
  53.413 +        return 0;
  53.414 +    }
  53.415 + 
  53.416 +	end = json->parseValue(skip(buff), perror);
  53.417 +	if (!end)
  53.418 +    {
  53.419 +        json->Release();
  53.420 +        return NULL;
  53.421 +    }	// parse failure. ep is set.
  53.422 +
  53.423 +    return json;
  53.424 +}
  53.425 +
  53.426 +//-----------------------------------------------------------------------------
  53.427 +// Parser core - when encountering text, process appropriately.
  53.428 +const char* JSON::parseValue(const char* buff, const char** perror)
  53.429 +{
  53.430 +    if (perror)
  53.431 +        *perror = 0;
  53.432 +
  53.433 +	if (!buff)
  53.434 +        return NULL;	// Fail on null.
  53.435 +
  53.436 +	if (!strncmp(buff,"null",4))
  53.437 +    {
  53.438 +        Type = JSON_Null;
  53.439 +        return buff+4;
  53.440 +    }
  53.441 +	if (!strncmp(buff,"false",5))
  53.442 +    { 
  53.443 +        Type   = JSON_Bool;
  53.444 +        Value  = "false";
  53.445 +        dValue = 0;
  53.446 +        return buff+5;
  53.447 +    }
  53.448 +	if (!strncmp(buff,"true",4))
  53.449 +    {
  53.450 +        Type   = JSON_Bool;
  53.451 +        Value  = "true";
  53.452 +        dValue = 1;
  53.453 +        return buff+4;
  53.454 +    }
  53.455 +	if (*buff=='\"')
  53.456 +    {
  53.457 +        return parseString(buff, perror);
  53.458 +    }
  53.459 +	if (*buff=='-' || (*buff>='0' && *buff<='9'))
  53.460 +    { 
  53.461 +        return parseNumber(buff);
  53.462 +    }
  53.463 +	if (*buff=='[')
  53.464 +    { 
  53.465 +        return parseArray(buff, perror);
  53.466 +    }
  53.467 +	if (*buff=='{')
  53.468 +    {
  53.469 +        return parseObject(buff, perror);
  53.470 +    }
  53.471 +
  53.472 +    return AssignError(perror, "Syntax Error: Invalid syntax");
  53.473 +}
  53.474 +
  53.475 +
  53.476 +//-----------------------------------------------------------------------------
  53.477 +// Render a value to text. 
  53.478 +char* JSON::PrintValue(int depth, bool fmt)
  53.479 +{
  53.480 +	char *out=0;
  53.481 +
  53.482 +    switch (Type)
  53.483 +	{
  53.484 +        case JSON_Null:	    out = JSON_strdup("null");	break;
  53.485 +        case JSON_Bool:
  53.486 +            if (dValue == 0)
  53.487 +                out = JSON_strdup("false");
  53.488 +            else
  53.489 +                out = JSON_strdup("true");
  53.490 +            break;
  53.491 +        case JSON_Number:	out = PrintNumber(dValue); break;
  53.492 +        case JSON_String:	out = PrintString(Value); break;
  53.493 +        case JSON_Array:	out = PrintArray(depth, fmt); break;
  53.494 +        case JSON_Object:	out = PrintObject(depth, fmt); break;
  53.495 +        case JSON_None: OVR_ASSERT_LOG(false, ("Bad JSON type.")); break;
  53.496 +	}
  53.497 +	return out;
  53.498 +}
  53.499 +
  53.500 +//-----------------------------------------------------------------------------
  53.501 +// Build an array object from input text and returns the text position after
  53.502 +// the parsed array
  53.503 +const char* JSON::parseArray(const char* buff, const char** perror)
  53.504 +{
  53.505 +	JSON *child;
  53.506 +	if (*buff!='[')
  53.507 +    {
  53.508 +        return AssignError(perror, "Syntax Error: Missing opening bracket");
  53.509 +    }
  53.510 +
  53.511 +	Type=JSON_Array;
  53.512 +	buff=skip(buff+1);
  53.513 +	
  53.514 +    if (*buff==']')
  53.515 +        return buff+1;	// empty array.
  53.516 +
  53.517 +    child = new JSON();
  53.518 +	if (!child)
  53.519 +        return 0;		 // memory fail
  53.520 +    Children.PushBack(child);
  53.521 +	
  53.522 +    buff=skip(child->parseValue(skip(buff), perror));	// skip any spacing, get the buff. 
  53.523 +	if (!buff)
  53.524 +        return 0;
  53.525 +
  53.526 +	while (*buff==',')
  53.527 +	{
  53.528 +		JSON *new_item = new JSON();
  53.529 +		if (!new_item)
  53.530 +            return AssignError(perror, "Error: Failed to allocate memory");
  53.531 +		
  53.532 +        Children.PushBack(new_item);
  53.533 +
  53.534 +		buff=skip(new_item->parseValue(skip(buff+1), perror));
  53.535 +		if (!buff)
  53.536 +            return AssignError(perror, "Error: Failed to allocate memory");
  53.537 +	}
  53.538 +
  53.539 +	if (*buff==']')
  53.540 +        return buff+1;	// end of array
  53.541 +
  53.542 +    return AssignError(perror, "Syntax Error: Missing ending bracket");
  53.543 +}
  53.544 +
  53.545 +//-----------------------------------------------------------------------------
  53.546 +// Render an array to text.  The returned text must be freed
  53.547 +char* JSON::PrintArray(int depth, bool fmt)
  53.548 +{
  53.549 +	char **entries;
  53.550 +	char * out = 0,*ptr,*ret;
  53.551 +    SPInt  len = 5;
  53.552 +	
  53.553 +    bool fail = false;
  53.554 +	
  53.555 +	// How many entries in the array? 
  53.556 +    int numentries = GetItemCount();
  53.557 +	if (!numentries)
  53.558 +	{
  53.559 +		out=(char*)OVR_ALLOC(3);
  53.560 +		if (out)
  53.561 +            OVR_strcpy(out, 3, "[]");
  53.562 +		return out;
  53.563 +	}
  53.564 +	// Allocate an array to hold the values for each
  53.565 +	entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
  53.566 +	if (!entries)
  53.567 +        return 0;
  53.568 +	memset(entries,0,numentries*sizeof(char*));
  53.569 +
  53.570 +	//// Retrieve all the results:
  53.571 +    JSON* child = Children.GetFirst();
  53.572 +    for (int i=0; i<numentries; i++)
  53.573 +	{
  53.574 +		//JSON* child = Children[i];
  53.575 +        ret=child->PrintValue(depth+1, fmt);
  53.576 +		entries[i]=ret;
  53.577 +		if (ret)
  53.578 +            len+=OVR_strlen(ret)+2+(fmt?1:0);
  53.579 +        else
  53.580 +        {
  53.581 +            fail = true;
  53.582 +            break;
  53.583 +        }
  53.584 +        child = Children.GetNext(child);
  53.585 +	}
  53.586 +	
  53.587 +	// If we didn't fail, try to malloc the output string 
  53.588 +	if (!fail)
  53.589 +        out=(char*)OVR_ALLOC(len);
  53.590 +	// If that fails, we fail. 
  53.591 +	if (!out)
  53.592 +        fail = true;
  53.593 +
  53.594 +	// Handle failure.
  53.595 +	if (fail)
  53.596 +	{
  53.597 +		for (int i=0; i<numentries; i++) 
  53.598 +        {
  53.599 +            if (entries[i])
  53.600 +                OVR_FREE(entries[i]);
  53.601 +        }
  53.602 +		OVR_FREE(entries);
  53.603 +		return 0;
  53.604 +	}
  53.605 +	
  53.606 +	// Compose the output array.
  53.607 +	*out='[';
  53.608 +	ptr=out+1;
  53.609 +    *ptr=0;
  53.610 +	for (int i=0; i<numentries; i++)
  53.611 +	{
  53.612 +		OVR_strcpy(ptr, len - (ptr-out), entries[i]);
  53.613 +        ptr+=OVR_strlen(entries[i]);
  53.614 +		if (i!=numentries-1)
  53.615 +        {
  53.616 +            *ptr++=',';
  53.617 +            if (fmt)
  53.618 +                *ptr++=' ';
  53.619 +            *ptr=0;
  53.620 +        }
  53.621 +		OVR_FREE(entries[i]);
  53.622 +	}
  53.623 +	OVR_FREE(entries);
  53.624 +	*ptr++=']';
  53.625 +    *ptr++=0;
  53.626 +	return out;	
  53.627 +}
  53.628 +
  53.629 +//-----------------------------------------------------------------------------
  53.630 +// Build an object from the supplied text and returns the text position after
  53.631 +// the parsed object
  53.632 +const char* JSON::parseObject(const char* buff, const char** perror)
  53.633 +{
  53.634 +	if (*buff!='{')
  53.635 +    {
  53.636 +        return AssignError(perror, "Syntax Error: Missing opening brace");
  53.637 +    }
  53.638 +	
  53.639 +	Type=JSON_Object;
  53.640 +	buff=skip(buff+1);
  53.641 +	if (*buff=='}')
  53.642 +        return buff+1;	// empty array.
  53.643 +	
  53.644 +    JSON* child = new JSON();
  53.645 +    Children.PushBack(child);
  53.646 +
  53.647 +	buff=skip(child->parseString(skip(buff), perror));
  53.648 +	if (!buff) 
  53.649 +        return 0;
  53.650 +	child->Name = child->Value;
  53.651 +    child->Value.Clear();
  53.652 +	
  53.653 +    if (*buff!=':')
  53.654 +    {
  53.655 +        return AssignError(perror, "Syntax Error: Missing colon");
  53.656 +    }
  53.657 +
  53.658 +	buff=skip(child->parseValue(skip(buff+1), perror));	// skip any spacing, get the value.
  53.659 +	if (!buff)
  53.660 +        return 0;
  53.661 +	
  53.662 +	while (*buff==',')
  53.663 +	{
  53.664 +        child = new JSON();
  53.665 +		if (!child)
  53.666 +            return 0; // memory fail
  53.667 +		
  53.668 +        Children.PushBack(child);
  53.669 +
  53.670 +		buff=skip(child->parseString(skip(buff+1), perror));
  53.671 +		if (!buff)
  53.672 +            return 0;
  53.673 +		
  53.674 +        child->Name=child->Value;
  53.675 +        child->Value.Clear();
  53.676 +		
  53.677 +        if (*buff!=':')
  53.678 +        {
  53.679 +            return AssignError(perror, "Syntax Error: Missing colon");
  53.680 +        }	// fail!
  53.681 +		
  53.682 +        // Skip any spacing, get the value.
  53.683 +        buff=skip(child->parseValue(skip(buff+1), perror));
  53.684 +		if (!buff)
  53.685 +            return 0;
  53.686 +	}
  53.687 +	
  53.688 +	if (*buff=='}')
  53.689 +        return buff+1;	// end of array 
  53.690 +	
  53.691 +    return AssignError(perror, "Syntax Error: Missing closing brace");
  53.692 +}
  53.693 +
  53.694 +//-----------------------------------------------------------------------------
  53.695 +// Render an object to text.  The returned string must be freed
  53.696 +char* JSON::PrintObject(int depth, bool fmt)
  53.697 +{
  53.698 +	char** entries = 0, **names = 0;
  53.699 +	char*  out = 0;
  53.700 +    char*  ptr, *ret, *str;
  53.701 +    SPInt  len = 7, i = 0, j;
  53.702 +    bool   fail = false;
  53.703 +	
  53.704 +    // Count the number of entries.
  53.705 +    int numentries = GetItemCount();
  53.706 +    
  53.707 +	// Explicitly handle empty object case
  53.708 +	if (numentries == 0)
  53.709 +	{
  53.710 +		out=(char*)OVR_ALLOC(fmt?depth+3:3);
  53.711 +		if (!out)
  53.712 +            return 0;
  53.713 +		ptr=out;
  53.714 +        *ptr++='{';
  53.715 +		
  53.716 +        if (fmt)
  53.717 +        {
  53.718 +            *ptr++='\n';
  53.719 +            for (i=0;i<depth-1;i++)
  53.720 +                *ptr++='\t';
  53.721 +        }
  53.722 +		*ptr++='}';
  53.723 +        *ptr++=0;
  53.724 +		return out;
  53.725 +	}
  53.726 +	// Allocate space for the names and the objects
  53.727 +	entries=(char**)OVR_ALLOC(numentries*sizeof(char*));
  53.728 +	if (!entries)
  53.729 +        return 0;
  53.730 +	names=(char**)OVR_ALLOC(numentries*sizeof(char*));
  53.731 +	
  53.732 +    if (!names)
  53.733 +    {
  53.734 +        OVR_FREE(entries);
  53.735 +        return 0;
  53.736 +    }
  53.737 +	memset(entries,0,sizeof(char*)*numentries);
  53.738 +	memset(names,0,sizeof(char*)*numentries);
  53.739 +
  53.740 +	// Collect all the results into our arrays:
  53.741 +    depth++;
  53.742 +    if (fmt)
  53.743 +        len+=depth;
  53.744 +
  53.745 +    JSON* child = Children.GetFirst();
  53.746 +    while (!Children.IsNull(child))
  53.747 +	{
  53.748 +		names[i]     = str = PrintString(child->Name);
  53.749 +		entries[i++] = ret = child->PrintValue(depth, fmt);
  53.750 +
  53.751 +		if (str && ret)
  53.752 +        {
  53.753 +            len += OVR_strlen(ret)+OVR_strlen(str)+2+(fmt?2+depth:0);
  53.754 +        }
  53.755 +        else
  53.756 +        {
  53.757 +            fail = true;
  53.758 +            break;
  53.759 +        }
  53.760 +		
  53.761 +        child = Children.GetNext(child);
  53.762 +	}
  53.763 +	
  53.764 +	// Try to allocate the output string
  53.765 +	if (!fail)
  53.766 +        out=(char*)OVR_ALLOC(len);
  53.767 +	if (!out)
  53.768 +        fail=true;
  53.769 +
  53.770 +	// Handle failure
  53.771 +	if (fail)
  53.772 +	{
  53.773 +		for (i=0;i<numentries;i++)
  53.774 +        {
  53.775 +            if (names[i])
  53.776 +                OVR_FREE(names[i]);
  53.777 +            
  53.778 +            if (entries[i])
  53.779 +                OVR_FREE(entries[i]);}
  53.780 +		
  53.781 +        OVR_FREE(names);
  53.782 +        OVR_FREE(entries);
  53.783 +		return 0;
  53.784 +	}
  53.785 +	
  53.786 +	// Compose the output:
  53.787 +	*out = '{';
  53.788 +    ptr  = out+1;
  53.789 +    if (fmt)
  53.790 +        *ptr++='\n';
  53.791 +    *ptr = 0;
  53.792 +	
  53.793 +    for (i=0; i<numentries; i++)
  53.794 +	{
  53.795 +		if (fmt)
  53.796 +        {
  53.797 +            for (j=0; j<depth; j++)
  53.798 +                *ptr++ = '\t';
  53.799 +        }
  53.800 +		OVR_strcpy(ptr, len - (ptr-out), names[i]);
  53.801 +        ptr   += OVR_strlen(names[i]);
  53.802 +		*ptr++ =':';
  53.803 +        
  53.804 +        if (fmt)
  53.805 +            *ptr++='\t';
  53.806 +		
  53.807 +        OVR_strcpy(ptr, len - (ptr-out), entries[i]);
  53.808 +        ptr+=OVR_strlen(entries[i]);
  53.809 +		
  53.810 +        if (i!=numentries-1)
  53.811 +            *ptr++ = ',';
  53.812 +		
  53.813 +        if (fmt)
  53.814 +            *ptr++ = '\n';
  53.815 +        *ptr = 0;
  53.816 +		
  53.817 +        OVR_FREE(names[i]);
  53.818 +        OVR_FREE(entries[i]);
  53.819 +	}
  53.820 +	
  53.821 +	OVR_FREE(names);
  53.822 +    OVR_FREE(entries);
  53.823 +	
  53.824 +    if (fmt)
  53.825 +    {
  53.826 +        for (i=0;i<depth-1;i++)
  53.827 +            *ptr++='\t';
  53.828 +    }
  53.829 +	*ptr++='}';
  53.830 +    *ptr++=0;
  53.831 +	
  53.832 +    return out;	
  53.833 +}
  53.834 +
  53.835 +
  53.836 +
  53.837 +// Returns the number of child items in the object
  53.838 +// Counts the number of items in the object.
  53.839 +unsigned JSON::GetItemCount() const
  53.840 +{
  53.841 +    unsigned count = 0;
  53.842 +    for(const JSON* p = Children.GetFirst(); !Children.IsNull(p); p = p->pNext)
  53.843 +        count++;
  53.844 +    return count;
  53.845 +}
  53.846 +
  53.847 +JSON* JSON::GetItemByIndex(unsigned index)
  53.848 +{
  53.849 +    unsigned i     = 0;
  53.850 +    JSON*    child = 0;
  53.851 +
  53.852 +    if (!Children.IsEmpty())
  53.853 +    {
  53.854 +        child = Children.GetFirst();
  53.855 +
  53.856 +        while (i < index)
  53.857 +        {   
  53.858 +            if (Children.IsNull(child->pNext))
  53.859 +            {
  53.860 +                child = 0;
  53.861 +                break;
  53.862 +            }
  53.863 +            child = child->pNext;
  53.864 +            i++;
  53.865 +        }
  53.866 +    }
  53.867 +  
  53.868 +    return child;
  53.869 +}
  53.870 +
  53.871 +// Returns the child item with the given name or NULL if not found
  53.872 +JSON* JSON::GetItemByName(const char* name)
  53.873 +{
  53.874 +    JSON* child = 0;
  53.875 +
  53.876 +    if (!Children.IsEmpty())
  53.877 +    {
  53.878 +        child = Children.GetFirst();
  53.879 +
  53.880 +        while (OVR_strcmp(child->Name, name) != 0)
  53.881 +        {   
  53.882 +            if (Children.IsNull(child->pNext))
  53.883 +            {
  53.884 +                child = 0;
  53.885 +                break;
  53.886 +            }
  53.887 +            child = child->pNext;
  53.888 +        }
  53.889 +    }
  53.890 +
  53.891 +    return child;
  53.892 +}
  53.893 +
  53.894 +//-----------------------------------------------------------------------------
  53.895 +// Adds a new item to the end of the child list
  53.896 +void JSON::AddItem(const char *string, JSON *item)
  53.897 +{
  53.898 +    if (!item)
  53.899 +        return;
  53.900 + 
  53.901 +    item->Name = string;
  53.902 +    Children.PushBack(item);
  53.903 +}
  53.904 +
  53.905 +/*
  53.906 +
  53.907 +// Removes and frees the items at the given index
  53.908 +void JSON::DeleteItem(unsigned int index)
  53.909 +{
  53.910 +    unsigned int num_items = 0;
  53.911 +    JSON* child = Children.GetFirst();
  53.912 +    while (!Children.IsNull(child) && num_items < index)
  53.913 +    {   
  53.914 +        num_items++;
  53.915 +        child = Children.GetNext(child);
  53.916 +    }
  53.917 +
  53.918 +    if (!Children.IsNull(child))
  53.919 +    
  53.920 +        child->RemoveNode();
  53.921 +        child->Release();
  53.922 +    }
  53.923 +}
  53.924 +
  53.925 +// Replaces and frees the item at the give index with the new item
  53.926 +void JSON::ReplaceItem(unsigned int index, JSON* new_item)
  53.927 +{
  53.928 +    unsigned int num_items = 0;
  53.929 +    JSON* child = Children.GetFirst();
  53.930 +    while (!Children.IsNull(child) && num_items < index)
  53.931 +    {   
  53.932 +        num_items++;
  53.933 +        child = Children.GetNext(child);
  53.934 +    }
  53.935 +
  53.936 +    if (!Children.IsNull(child))
  53.937 +    {
  53.938 +        child->ReplaceNodeWith(new_item);
  53.939 +        child->Release();        
  53.940 +    }
  53.941 +}
  53.942 +*/
  53.943 +
  53.944 +// Helper function to simplify creation of a typed object
  53.945 +JSON* JSON::createHelper(JSONItemType itemType, double dval, const char* strVal)
  53.946 +{
  53.947 +    JSON *item = new JSON(itemType);
  53.948 +    if (item)
  53.949 +    {
  53.950 +        item->dValue = dval;
  53.951 +        if (strVal)
  53.952 +            item->Value = strVal;
  53.953 +    }
  53.954 +    return item;
  53.955 +}
  53.956 +
  53.957 +
  53.958 +//-----------------------------------------------------------------------------
  53.959 +// Adds an element to an array object type
  53.960 +void JSON::AddArrayElement(JSON *item)
  53.961 +{
  53.962 +    if (!item)
  53.963 +        return;
  53.964 +
  53.965 +    Children.PushBack(item);
  53.966 +}
  53.967 +
  53.968 +
  53.969 +// Returns the size of an array
  53.970 +int JSON::GetArraySize()
  53.971 +{
  53.972 +    if (Type == JSON_Array)
  53.973 +        return GetItemCount();
  53.974 +    else
  53.975 +        return 0;
  53.976 +}
  53.977 +
  53.978 +// Returns the number value an the give array index
  53.979 +double JSON::GetArrayNumber(int index)
  53.980 +{
  53.981 +    if (Type == JSON_Array)
  53.982 +    {
  53.983 +        JSON* number = GetItemByIndex(index);
  53.984 +        return number ? number->dValue : 0.0;
  53.985 +    }
  53.986 +    else
  53.987 +    {
  53.988 +        return 0;
  53.989 +    }
  53.990 +}
  53.991 +
  53.992 +// Returns the string value at the given array index
  53.993 +const char* JSON::GetArrayString(int index)
  53.994 +{
  53.995 +    if (Type == JSON_Array)
  53.996 +    {
  53.997 +        JSON* number = GetItemByIndex(index);
  53.998 +        return number ? number->Value : 0;
  53.999 +    }
 53.1000 +    else
 53.1001 +    {
 53.1002 +        return 0;
 53.1003 +    }
 53.1004 +}
 53.1005 +
 53.1006 +//-----------------------------------------------------------------------------
 53.1007 +// Loads and parses the given JSON file pathname and returns a JSON object tree.
 53.1008 +// The returned object must be Released after use.
 53.1009 +JSON* JSON::Load(const char* path, const char** perror)
 53.1010 +{
 53.1011 +    SysFile f;
 53.1012 +    if (!f.Open(path, File::Open_Read, File::Mode_Read))
 53.1013 +    {
 53.1014 +        AssignError(perror, "Failed to open file");
 53.1015 +        return NULL;
 53.1016 +    }
 53.1017 +
 53.1018 +    int    len   = f.GetLength();
 53.1019 +    UByte* buff  = (UByte*)OVR_ALLOC(len);
 53.1020 +    int    bytes = f.Read(buff, len);
 53.1021 +    f.Close();
 53.1022 +
 53.1023 +    if (bytes == 0 || bytes != len)
 53.1024 +    {
 53.1025 +        OVR_FREE(buff);
 53.1026 +        return NULL;
 53.1027 +    }
 53.1028 +
 53.1029 +    JSON* json = JSON::Parse((char*)buff, perror);
 53.1030 +    OVR_FREE(buff);
 53.1031 +    return json;
 53.1032 +}
 53.1033 +
 53.1034 +//-----------------------------------------------------------------------------
 53.1035 +// Serializes the JSON object and writes to the give file path
 53.1036 +bool JSON::Save(const char* path)
 53.1037 +{
 53.1038 +    SysFile f;
 53.1039 +    if (!f.Open(path, File::Open_Write | File::Open_Create | File::Open_Truncate, File::Mode_Write))
 53.1040 +        return false;
 53.1041 +
 53.1042 +    char* text = PrintValue(0, true);
 53.1043 +    if (text)
 53.1044 +    {
 53.1045 +        SPInt len   = OVR_strlen(text);
 53.1046 +        OVR_ASSERT(len < (SPInt)(int)len);
 53.1047 +
 53.1048 +        int   bytes = f.Write((UByte*)text, (int)len);
 53.1049 +        f.Close();
 53.1050 +        OVR_FREE(text);
 53.1051 +        return (bytes == len);
 53.1052 +    }
 53.1053 +    else
 53.1054 +    {
 53.1055 +        return false;
 53.1056 +    }
 53.1057 +}
 53.1058 +
 53.1059 +}
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/libovr/Src/OVR_JSON.h	Sat Sep 14 16:14:59 2013 +0300
    54.3 @@ -0,0 +1,143 @@
    54.4 +/************************************************************************************
    54.5 +
    54.6 +PublicHeader:   None
    54.7 +Filename    :   OVR_JSON.h
    54.8 +Content     :   JSON format reader and writer
    54.9 +Created     :   April 9, 2013
   54.10 +Author      :   Brant Lewis
   54.11 +Notes       :
   54.12 +
   54.13 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   54.14 +
   54.15 +Use of this software is subject to the terms of the Oculus license
   54.16 +agreement provided at the time of installation or download, or which
   54.17 +otherwise accompanies this software in either electronic or hard copy form.
   54.18 +
   54.19 +************************************************************************************/
   54.20 +
   54.21 +#ifndef OVR_JSON_H
   54.22 +#define OVR_JSON_H
   54.23 +
   54.24 +#include "Kernel/OVR_RefCount.h"
   54.25 +#include "Kernel/OVR_String.h"
   54.26 +#include "Kernel/OVR_List.h"
   54.27 +
   54.28 +namespace OVR {  
   54.29 +
   54.30 +// JSONItemType describes the type of JSON item, specifying the type of
   54.31 +// data that can be obtained from it.
   54.32 +enum JSONItemType
   54.33 +{
   54.34 +    JSON_None      = 0,
   54.35 +    JSON_Null      = 1,
   54.36 +    JSON_Bool      = 2,
   54.37 +    JSON_Number    = 3,
   54.38 +    JSON_String    = 4,
   54.39 +    JSON_Array     = 5,
   54.40 +    JSON_Object    = 6
   54.41 +};
   54.42 +
   54.43 +
   54.44 +//-----------------------------------------------------------------------------
   54.45 +// ***** JSON
   54.46 +
   54.47 +// JSON object represents a JSON node that can be either a root of the JSON tree
   54.48 +// or a child item. Every node has a type that describes what is is.
   54.49 +// New JSON trees are typically loaded JSON::Load or created with JSON::Parse.
   54.50 +
   54.51 +class JSON : public RefCountBase<JSON>, public ListNode<JSON>
   54.52 +{
   54.53 +protected:
   54.54 +    List<JSON>      Children;
   54.55 +
   54.56 +public:
   54.57 +    JSONItemType    Type;       // Type of this JSON node.
   54.58 +    String          Name;       // Name part of the {Name, Value} pair in a parent object.
   54.59 +    String          Value;
   54.60 +    double          dValue;
   54.61 +
   54.62 +public:
   54.63 +    ~JSON();
   54.64 +
   54.65 +    // *** Creation of NEW JSON objects
   54.66 +
   54.67 +    static JSON*    CreateObject()               { return new JSON(JSON_Object);}
   54.68 +    static JSON*    CreateNull()                 { return new JSON(JSON_Null); }
   54.69 +    static JSON*    CreateArray()                { return new JSON(JSON_Array); }
   54.70 +    static JSON*    CreateBool(bool b)           { return createHelper(JSON_Bool, b ? 1.0 : 0.0); }
   54.71 +    static JSON*    CreateNumber(double num)     { return createHelper(JSON_Number, num); }
   54.72 +    static JSON*    CreateString(const char *s)  { return createHelper(JSON_String, 0.0, s); }
   54.73 +
   54.74 +    // Creates a new JSON object from parsing string.
   54.75 +    // Returns null pointer and fills in *perror in case of parse error.
   54.76 +    static JSON*    Parse(const char* buff, const char** perror = 0);
   54.77 +
   54.78 +    // Loads and parses a JSON object from a file.
   54.79 +    // Returns 0 and assigns perror with error message on fail.
   54.80 +    static JSON*    Load(const char* path, const char** perror = 0);
   54.81 +
   54.82 +    // Saves a JSON object to a file.
   54.83 +    bool            Save(const char* path);
   54.84 +
   54.85 +
   54.86 +    // *** Object Member Access
   54.87 +
   54.88 +    // These provide access to child items of the list.
   54.89 +    bool            HasItems() const         { return Children.IsEmpty(); }
   54.90 +    // Returns first/last child item, or null if child list is empty
   54.91 +    JSON*           GetFirstItem()           { return (!Children.IsEmpty()) ? Children.GetFirst() : 0; }
   54.92 +    JSON*           GetLastItem()            { return (!Children.IsEmpty()) ? Children.GetLast() : 0; }
   54.93 +
   54.94 +    // Counts the number of items in the object; these methods are inefficient.
   54.95 +    unsigned        GetItemCount() const;
   54.96 +    JSON*           GetItemByIndex(unsigned i);
   54.97 +    JSON*           GetItemByName(const char* name);
   54.98 +
   54.99 +    // Returns next item in a list of children; 0 if no more items exist.
  54.100 +    JSON*           GetNextItem(JSON* item)  { return Children.IsNull(item->pNext) ? 0 : item->pNext; }
  54.101 +    JSON*           GetPrevItem(JSON* item)  { return Children.IsNull(item->pPrev) ? 0 : item->pPrev; }
  54.102 +
  54.103 +
  54.104 +    // Child item access functions
  54.105 +    void            AddItem(const char *string, JSON* item);
  54.106 +    void            AddNullItem(const char* name)                    { AddItem(name, CreateNull()); }
  54.107 +    void            AddBoolItem(const char* name, bool b)            { AddItem(name, CreateBool(b)); }
  54.108 +    void            AddNumberItem(const char* name, double n)        { AddItem(name, CreateNumber(n)); }
  54.109 +    void            AddStringItem(const char* name, const char* s)   { AddItem(name, CreateString(s)); }
  54.110 +//    void            ReplaceItem(unsigned index, JSON* new_item);
  54.111 +//    void            DeleteItem(unsigned index);
  54.112 +
  54.113 +    // *** Array Element Access
  54.114 +
  54.115 +    // Add new elements to the end of array.
  54.116 +    void            AddArrayElement(JSON *item);
  54.117 +    void            AddArrayNumber(double n)        { AddArrayElement(CreateNumber(n)); }
  54.118 +    void            AddArrayString(const char* s)   { AddArrayElement(CreateString(s)); }
  54.119 +
  54.120 +    // Accessed array elements; currently inefficient.
  54.121 +    int             GetArraySize();
  54.122 +    double          GetArrayNumber(int index);
  54.123 +    const char*     GetArrayString(int index);
  54.124 +
  54.125 +
  54.126 +protected:
  54.127 +    JSON(JSONItemType itemType = JSON_Object);
  54.128 +
  54.129 +    static JSON*    createHelper(JSONItemType itemType, double dval, const char* strVal = 0);
  54.130 +
  54.131 +    // JSON Parsing helper functions.
  54.132 +    const char*     parseValue(const char *buff, const char** perror);
  54.133 +    const char*     parseNumber(const char *num);
  54.134 +    const char*     parseArray(const char* value, const char** perror);
  54.135 +    const char*     parseObject(const char* value, const char** perror);
  54.136 +    const char*     parseString(const char* str, const char** perror);
  54.137 +
  54.138 +    char*           PrintValue(int depth, bool fmt);
  54.139 +    char*           PrintObject(int depth, bool fmt);
  54.140 +    char*           PrintArray(int depth, bool fmt);
  54.141 +};
  54.142 +
  54.143 +
  54.144 +}
  54.145 +
  54.146 +#endif
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/libovr/Src/OVR_LatencyTestImpl.cpp	Sat Sep 14 16:14:59 2013 +0300
    55.3 @@ -0,0 +1,774 @@
    55.4 +/************************************************************************************
    55.5 +
    55.6 +Filename    :   OVR_LatencyTestImpl.cpp
    55.7 +Content     :   Oculus Latency Tester device implementation.
    55.8 +Created     :   March 7, 2013
    55.9 +Authors     :   Lee Cooper
   55.10 +
   55.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   55.12 +
   55.13 +Use of this software is subject to the terms of the Oculus license
   55.14 +agreement provided at the time of installation or download, or which
   55.15 +otherwise accompanies this software in either electronic or hard copy form.
   55.16 +
   55.17 +*************************************************************************************/
   55.18 +
   55.19 +#include "OVR_LatencyTestImpl.h"
   55.20 +
   55.21 +namespace OVR {
   55.22 +
   55.23 +//-------------------------------------------------------------------------------------
   55.24 +// ***** Oculus Latency Tester specific packet data structures
   55.25 +
   55.26 +enum {    
   55.27 +    LatencyTester_VendorId  = Oculus_VendorId,
   55.28 +    LatencyTester_ProductId = 0x0101,
   55.29 +};
   55.30 +
   55.31 +// Reported data is little-endian now
   55.32 +static UInt16 DecodeUInt16(const UByte* buffer)
   55.33 +{
   55.34 +    return (UInt16(buffer[1]) << 8) | UInt16(buffer[0]);
   55.35 +}
   55.36 +
   55.37 +/* Unreferenced
   55.38 +static SInt16 DecodeSInt16(const UByte* buffer)
   55.39 +{
   55.40 +    return (SInt16(buffer[1]) << 8) | SInt16(buffer[0]);
   55.41 +}*/
   55.42 +
   55.43 +static void UnpackSamples(const UByte* buffer, UByte* r, UByte* g, UByte* b)
   55.44 +{
   55.45 +    *r = buffer[0];
   55.46 +    *g = buffer[1];
   55.47 +    *b = buffer[2];
   55.48 +}
   55.49 +
   55.50 +// Messages we handle.
   55.51 +enum LatencyTestMessageType
   55.52 +{
   55.53 +    LatencyTestMessage_None                 = 0,
   55.54 +    LatencyTestMessage_Samples              = 1,
   55.55 +    LatencyTestMessage_ColorDetected        = 2,
   55.56 +    LatencyTestMessage_TestStarted          = 3,
   55.57 +    LatencyTestMessage_Button               = 4,
   55.58 +    LatencyTestMessage_Unknown              = 0x100,
   55.59 +    LatencyTestMessage_SizeError            = 0x101,
   55.60 +};
   55.61 +
   55.62 +struct LatencyTestSample
   55.63 +{
   55.64 +    UByte Value[3];
   55.65 +};
   55.66 +
   55.67 +struct LatencyTestSamples
   55.68 +{
   55.69 +    UByte	SampleCount;
   55.70 +    UInt16	Timestamp;
   55.71 +
   55.72 +    LatencyTestSample Samples[20];
   55.73 +
   55.74 +    LatencyTestMessageType Decode(const UByte* buffer, int size)
   55.75 +    {
   55.76 +        if (size < 64)
   55.77 +        {
   55.78 +            return LatencyTestMessage_SizeError;
   55.79 +        }
   55.80 +
   55.81 +        SampleCount		= buffer[1];
   55.82 +        Timestamp		= DecodeUInt16(buffer + 2);
   55.83 +        
   55.84 +        for (UByte i = 0; i < SampleCount; i++)
   55.85 +        {
   55.86 +            UnpackSamples(buffer + 4 + (3 * i),  &Samples[i].Value[0], &Samples[i].Value[1], &Samples[i].Value[2]);
   55.87 +        }
   55.88 +
   55.89 +        return LatencyTestMessage_Samples;
   55.90 +    }
   55.91 +};
   55.92 +
   55.93 +struct LatencyTestSamplesMessage
   55.94 +{
   55.95 +    LatencyTestMessageType      Type;
   55.96 +    LatencyTestSamples        Samples;
   55.97 +};
   55.98 +
   55.99 +bool DecodeLatencyTestSamplesMessage(LatencyTestSamplesMessage* message, UByte* buffer, int size)
  55.100 +{
  55.101 +    memset(message, 0, sizeof(LatencyTestSamplesMessage));
  55.102 +
  55.103 +    if (size < 64)
  55.104 +    {
  55.105 +        message->Type = LatencyTestMessage_SizeError;
  55.106 +        return false;
  55.107 +    }
  55.108 +
  55.109 +    switch (buffer[0])
  55.110 +    {
  55.111 +    case LatencyTestMessage_Samples:
  55.112 +        message->Type = message->Samples.Decode(buffer, size);
  55.113 +        break;
  55.114 +
  55.115 +    default:
  55.116 +        message->Type = LatencyTestMessage_Unknown;
  55.117 +        break;
  55.118 +    }
  55.119 +
  55.120 +    return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
  55.121 +}
  55.122 +
  55.123 +struct LatencyTestColorDetected
  55.124 +{
  55.125 +    UInt16	CommandID;
  55.126 +    UInt16	Timestamp;
  55.127 +    UInt16  Elapsed;
  55.128 +    UByte   TriggerValue[3];
  55.129 +    UByte   TargetValue[3];
  55.130 +
  55.131 +    LatencyTestMessageType Decode(const UByte* buffer, int size)
  55.132 +    {
  55.133 +        if (size < 13)
  55.134 +            return LatencyTestMessage_SizeError;
  55.135 +
  55.136 +        CommandID = DecodeUInt16(buffer + 1);
  55.137 +        Timestamp = DecodeUInt16(buffer + 3);
  55.138 +        Elapsed = DecodeUInt16(buffer + 5);
  55.139 +        memcpy(TriggerValue, buffer + 7, 3);
  55.140 +        memcpy(TargetValue, buffer + 10, 3);
  55.141 +
  55.142 +        return LatencyTestMessage_ColorDetected;
  55.143 +    }
  55.144 +};
  55.145 +
  55.146 +struct LatencyTestColorDetectedMessage
  55.147 +{
  55.148 +    LatencyTestMessageType    Type;
  55.149 +    LatencyTestColorDetected  ColorDetected;
  55.150 +};
  55.151 +
  55.152 +bool DecodeLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message, UByte* buffer, int size)
  55.153 +{
  55.154 +    memset(message, 0, sizeof(LatencyTestColorDetectedMessage));
  55.155 +
  55.156 +    if (size < 13)
  55.157 +    {
  55.158 +        message->Type = LatencyTestMessage_SizeError;
  55.159 +        return false;
  55.160 +    }
  55.161 +
  55.162 +    switch (buffer[0])
  55.163 +    {
  55.164 +    case LatencyTestMessage_ColorDetected:
  55.165 +        message->Type = message->ColorDetected.Decode(buffer, size);
  55.166 +        break;
  55.167 +
  55.168 +    default:
  55.169 +        message->Type = LatencyTestMessage_Unknown;
  55.170 +        break;
  55.171 +    }
  55.172 +
  55.173 +    return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
  55.174 +}
  55.175 +
  55.176 +struct LatencyTestStarted
  55.177 +{
  55.178 +    UInt16	CommandID;
  55.179 +    UInt16	Timestamp;
  55.180 +    UByte   TargetValue[3];
  55.181 +
  55.182 +    LatencyTestMessageType Decode(const UByte* buffer, int size)
  55.183 +    {
  55.184 +        if (size < 8)
  55.185 +            return LatencyTestMessage_SizeError;
  55.186 +
  55.187 +        CommandID = DecodeUInt16(buffer + 1);
  55.188 +        Timestamp = DecodeUInt16(buffer + 3);
  55.189 +        memcpy(TargetValue, buffer + 5, 3);
  55.190 +
  55.191 +        return LatencyTestMessage_TestStarted;
  55.192 +    }
  55.193 +};
  55.194 +
  55.195 +struct LatencyTestStartedMessage
  55.196 +{
  55.197 +    LatencyTestMessageType  Type;
  55.198 +    LatencyTestStarted  TestStarted;
  55.199 +};
  55.200 +
  55.201 +bool DecodeLatencyTestStartedMessage(LatencyTestStartedMessage* message, UByte* buffer, int size)
  55.202 +{
  55.203 +    memset(message, 0, sizeof(LatencyTestStartedMessage));
  55.204 +
  55.205 +    if (size < 8)
  55.206 +    {
  55.207 +        message->Type = LatencyTestMessage_SizeError;
  55.208 +        return false;
  55.209 +    }
  55.210 +
  55.211 +    switch (buffer[0])
  55.212 +    {
  55.213 +    case LatencyTestMessage_TestStarted:
  55.214 +        message->Type = message->TestStarted.Decode(buffer, size);
  55.215 +        break;
  55.216 +
  55.217 +    default:
  55.218 +        message->Type = LatencyTestMessage_Unknown;
  55.219 +        break;
  55.220 +    }
  55.221 +
  55.222 +    return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
  55.223 +}
  55.224 +
  55.225 +struct LatencyTestButton
  55.226 +{
  55.227 +    UInt16	CommandID;
  55.228 +    UInt16	Timestamp;
  55.229 +
  55.230 +    LatencyTestMessageType Decode(const UByte* buffer, int size)
  55.231 +    {
  55.232 +        if (size < 5)
  55.233 +            return LatencyTestMessage_SizeError;
  55.234 +
  55.235 +        CommandID = DecodeUInt16(buffer + 1);
  55.236 +        Timestamp = DecodeUInt16(buffer + 3);
  55.237 +
  55.238 +        return LatencyTestMessage_Button;
  55.239 +    }
  55.240 +};
  55.241 +
  55.242 +struct LatencyTestButtonMessage
  55.243 +{
  55.244 +    LatencyTestMessageType    Type;
  55.245 +    LatencyTestButton         Button;
  55.246 +};
  55.247 +
  55.248 +bool DecodeLatencyTestButtonMessage(LatencyTestButtonMessage* message, UByte* buffer, int size)
  55.249 +{
  55.250 +    memset(message, 0, sizeof(LatencyTestButtonMessage));
  55.251 +
  55.252 +    if (size < 5)
  55.253 +    {
  55.254 +        message->Type = LatencyTestMessage_SizeError;
  55.255 +        return false;
  55.256 +    }
  55.257 +
  55.258 +    switch (buffer[0])
  55.259 +    {
  55.260 +    case LatencyTestMessage_Button:
  55.261 +        message->Type = message->Button.Decode(buffer, size);
  55.262 +        break;
  55.263 +
  55.264 +    default:
  55.265 +        message->Type = LatencyTestMessage_Unknown;
  55.266 +        break;
  55.267 +    }
  55.268 +
  55.269 +    return (message->Type < LatencyTestMessage_Unknown) && (message->Type != LatencyTestMessage_None);
  55.270 +}
  55.271 +
  55.272 +struct LatencyTestConfigurationImpl
  55.273 +{
  55.274 +    enum  { PacketSize = 5 };
  55.275 +    UByte   Buffer[PacketSize];
  55.276 +
  55.277 +    OVR::LatencyTestConfiguration  Configuration;
  55.278 +
  55.279 +    LatencyTestConfigurationImpl(const OVR::LatencyTestConfiguration& configuration)
  55.280 +        : Configuration(configuration)
  55.281 +    {
  55.282 +        Pack();
  55.283 +    }
  55.284 +
  55.285 +    void Pack()
  55.286 +    {
  55.287 +        Buffer[0] = 5;
  55.288 +		Buffer[1] = UByte(Configuration.SendSamples);
  55.289 +		Buffer[2] = Configuration.Threshold.R;
  55.290 +        Buffer[3] = Configuration.Threshold.G;
  55.291 +        Buffer[4] = Configuration.Threshold.B;
  55.292 +    }
  55.293 +
  55.294 +    void Unpack()
  55.295 +    {
  55.296 +		Configuration.SendSamples = Buffer[1] != 0 ? true : false;
  55.297 +        Configuration.Threshold.R = Buffer[2];
  55.298 +        Configuration.Threshold.G = Buffer[3];
  55.299 +        Configuration.Threshold.B = Buffer[4];
  55.300 +    }
  55.301 +};
  55.302 +
  55.303 +struct LatencyTestCalibrateImpl
  55.304 +{
  55.305 +    enum  { PacketSize = 4 };
  55.306 +    UByte   Buffer[PacketSize];
  55.307 +
  55.308 +    Color CalibrationColor;
  55.309 +    
  55.310 +    LatencyTestCalibrateImpl(const Color& calibrationColor)
  55.311 +        : CalibrationColor(calibrationColor)
  55.312 +    {
  55.313 +        Pack();
  55.314 +    }
  55.315 +
  55.316 +    void Pack()
  55.317 +    {
  55.318 +        Buffer[0] = 7;
  55.319 +		Buffer[1] = CalibrationColor.R;
  55.320 +		Buffer[2] = CalibrationColor.G;
  55.321 +		Buffer[3] = CalibrationColor.B;
  55.322 +    }
  55.323 +
  55.324 +    void Unpack()
  55.325 +    {
  55.326 +        CalibrationColor.R = Buffer[1];
  55.327 +        CalibrationColor.G = Buffer[2];
  55.328 +        CalibrationColor.B = Buffer[3];
  55.329 +    }
  55.330 +};
  55.331 +
  55.332 +struct LatencyTestStartTestImpl
  55.333 +{
  55.334 +    enum  { PacketSize = 6 };
  55.335 +    UByte   Buffer[PacketSize];
  55.336 +
  55.337 +    Color TargetColor;
  55.338 +
  55.339 +    LatencyTestStartTestImpl(const Color& targetColor)
  55.340 +        : TargetColor(targetColor)
  55.341 +    {
  55.342 +        Pack();
  55.343 +    }
  55.344 +
  55.345 +    void Pack()
  55.346 +    {
  55.347 +        UInt16 commandID = 1;
  55.348 +
  55.349 +        Buffer[0] = 8;
  55.350 +		Buffer[1] = UByte(commandID  & 0xFF);
  55.351 +		Buffer[2] = UByte(commandID >> 8);
  55.352 +		Buffer[3] = TargetColor.R;
  55.353 +		Buffer[4] = TargetColor.G;
  55.354 +		Buffer[5] = TargetColor.B;
  55.355 +    }
  55.356 +
  55.357 +    void Unpack()
  55.358 +    {
  55.359 +//      UInt16 commandID = Buffer[1] | (UInt16(Buffer[2]) << 8);
  55.360 +        TargetColor.R = Buffer[3];
  55.361 +        TargetColor.G = Buffer[4];
  55.362 +        TargetColor.B = Buffer[5];
  55.363 +    }
  55.364 +};
  55.365 +
  55.366 +struct LatencyTestDisplayImpl
  55.367 +{
  55.368 +    enum  { PacketSize = 6 };
  55.369 +    UByte   Buffer[PacketSize];
  55.370 +
  55.371 +    OVR::LatencyTestDisplay  Display;
  55.372 +
  55.373 +    LatencyTestDisplayImpl(const OVR::LatencyTestDisplay& display)
  55.374 +        : Display(display)
  55.375 +    {
  55.376 +        Pack();
  55.377 +    }
  55.378 +
  55.379 +    void Pack()
  55.380 +    {
  55.381 +        Buffer[0] = 9;
  55.382 +        Buffer[1] = Display.Mode;
  55.383 +        Buffer[2] = UByte(Display.Value & 0xFF);
  55.384 +        Buffer[3] = UByte((Display.Value >> 8) & 0xFF);
  55.385 +        Buffer[4] = UByte((Display.Value >> 16) & 0xFF);
  55.386 +        Buffer[5] = UByte((Display.Value >> 24) & 0xFF);
  55.387 +    }
  55.388 +
  55.389 +    void Unpack()
  55.390 +    {
  55.391 +        Display.Mode = Buffer[1];
  55.392 +        Display.Value = UInt32(Buffer[2]) |
  55.393 +            (UInt32(Buffer[3]) << 8) |
  55.394 +            (UInt32(Buffer[4]) << 16) |
  55.395 +            (UInt32(Buffer[5]) << 24);
  55.396 +    }
  55.397 +};
  55.398 +
  55.399 +//-------------------------------------------------------------------------------------
  55.400 +// ***** LatencyTestDeviceFactory
  55.401 +
  55.402 +LatencyTestDeviceFactory LatencyTestDeviceFactory::Instance;
  55.403 +
  55.404 +void LatencyTestDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
  55.405 +{
  55.406 +
  55.407 +    class LatencyTestEnumerator : public HIDEnumerateVisitor
  55.408 +    {
  55.409 +        // Assign not supported; suppress MSVC warning.
  55.410 +        void operator = (const LatencyTestEnumerator&) { }
  55.411 +
  55.412 +        DeviceFactory*     pFactory;
  55.413 +        EnumerateVisitor&  ExternalVisitor;   
  55.414 +    public:
  55.415 +        LatencyTestEnumerator(DeviceFactory* factory, EnumerateVisitor& externalVisitor)
  55.416 +            : pFactory(factory), ExternalVisitor(externalVisitor) { }
  55.417 +
  55.418 +        virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId)
  55.419 +        {
  55.420 +            return pFactory->MatchVendorProduct(vendorId, productId);
  55.421 +        }
  55.422 +
  55.423 +        virtual void Visit(HIDDevice& device, const HIDDeviceDesc& desc)
  55.424 +        {
  55.425 +            OVR_UNUSED(device);
  55.426 +
  55.427 +            LatencyTestDeviceCreateDesc createDesc(pFactory, desc);
  55.428 +            ExternalVisitor.Visit(createDesc);
  55.429 +        }
  55.430 +    };
  55.431 +
  55.432 +    LatencyTestEnumerator latencyTestEnumerator(this, visitor);
  55.433 +    GetManagerImpl()->GetHIDDeviceManager()->Enumerate(&latencyTestEnumerator);
  55.434 +}
  55.435 +
  55.436 +bool LatencyTestDeviceFactory::MatchVendorProduct(UInt16 vendorId, UInt16 productId) const
  55.437 +{
  55.438 +    return ((vendorId == LatencyTester_VendorId) && (productId == LatencyTester_ProductId));                
  55.439 +}
  55.440 +
  55.441 +bool LatencyTestDeviceFactory::DetectHIDDevice(DeviceManager* pdevMgr, 
  55.442 +                                               const HIDDeviceDesc& desc)
  55.443 +{
  55.444 +    if (MatchVendorProduct(desc.VendorId, desc.ProductId))
  55.445 +    {
  55.446 +        LatencyTestDeviceCreateDesc createDesc(this, desc);
  55.447 +        return pdevMgr->AddDevice_NeedsLock(createDesc).GetPtr() != NULL;
  55.448 +    }
  55.449 +    return false;
  55.450 +}
  55.451 +
  55.452 +//-------------------------------------------------------------------------------------
  55.453 +// ***** LatencyTestDeviceCreateDesc
  55.454 +
  55.455 +DeviceBase* LatencyTestDeviceCreateDesc::NewDeviceInstance()
  55.456 +{
  55.457 +    return new LatencyTestDeviceImpl(this);
  55.458 +}
  55.459 +
  55.460 +bool LatencyTestDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
  55.461 +{
  55.462 +    if ((info->InfoClassType != Device_LatencyTester) &&
  55.463 +        (info->InfoClassType != Device_None))
  55.464 +        return false;
  55.465 +
  55.466 +    OVR_strcpy(info->ProductName,  DeviceInfo::MaxNameLength, HIDDesc.Product.ToCStr());
  55.467 +    OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, HIDDesc.Manufacturer.ToCStr());
  55.468 +    info->Type    = Device_LatencyTester;
  55.469 +    info->Version = 0;
  55.470 +
  55.471 +    if (info->InfoClassType == Device_LatencyTester)
  55.472 +    {
  55.473 +        SensorInfo* sinfo = (SensorInfo*)info;
  55.474 +        sinfo->VendorId  = HIDDesc.VendorId;
  55.475 +        sinfo->ProductId = HIDDesc.ProductId;
  55.476 +        OVR_strcpy(sinfo->SerialNumber, sizeof(sinfo->SerialNumber),HIDDesc.SerialNumber.ToCStr());
  55.477 +    }
  55.478 +    return true;
  55.479 +}
  55.480 +
  55.481 +//-------------------------------------------------------------------------------------
  55.482 +// ***** LatencyTestDevice
  55.483 +
  55.484 +LatencyTestDeviceImpl::LatencyTestDeviceImpl(LatencyTestDeviceCreateDesc* createDesc)
  55.485 +    : OVR::HIDDeviceImpl<OVR::LatencyTestDevice>(createDesc, 0)
  55.486 +{
  55.487 +}
  55.488 +
  55.489 +LatencyTestDeviceImpl::~LatencyTestDeviceImpl()
  55.490 +{
  55.491 +    // Check that Shutdown() was called.
  55.492 +    OVR_ASSERT(!pCreateDesc->pDevice);    
  55.493 +}
  55.494 +
  55.495 +// Internal creation APIs.
  55.496 +bool LatencyTestDeviceImpl::Initialize(DeviceBase* parent)
  55.497 +{
  55.498 +    if (HIDDeviceImpl<OVR::LatencyTestDevice>::Initialize(parent))
  55.499 +    {
  55.500 +        LogText("OVR::LatencyTestDevice initialized.\n");
  55.501 +        return true;
  55.502 +    }
  55.503 +
  55.504 +    return false;
  55.505 +}
  55.506 +
  55.507 +void LatencyTestDeviceImpl::Shutdown()
  55.508 +{   
  55.509 +    HIDDeviceImpl<OVR::LatencyTestDevice>::Shutdown();
  55.510 +
  55.511 +    LogText("OVR::LatencyTestDevice - Closed '%s'\n", getHIDDesc()->Path.ToCStr());
  55.512 +}
  55.513 +
  55.514 +void LatencyTestDeviceImpl::OnInputReport(UByte* pData, UInt32 length)
  55.515 +{
  55.516 +    
  55.517 +    bool processed = false;
  55.518 +    if (!processed)
  55.519 +    {
  55.520 +        LatencyTestSamplesMessage message; 
  55.521 +        if (DecodeLatencyTestSamplesMessage(&message, pData, length))     
  55.522 +        {
  55.523 +            processed = true;
  55.524 +            onLatencyTestSamplesMessage(&message);
  55.525 +        }
  55.526 +    }
  55.527 +
  55.528 +    if (!processed)
  55.529 +    {
  55.530 +        LatencyTestColorDetectedMessage message; 
  55.531 +        if (DecodeLatencyTestColorDetectedMessage(&message, pData, length))     
  55.532 +        {
  55.533 +            processed = true;
  55.534 +            onLatencyTestColorDetectedMessage(&message);
  55.535 +        }
  55.536 +    }
  55.537 +
  55.538 +    if (!processed)
  55.539 +    {
  55.540 +        LatencyTestStartedMessage message; 
  55.541 +        if (DecodeLatencyTestStartedMessage(&message, pData, length))     
  55.542 +        {
  55.543 +            processed = true;
  55.544 +            onLatencyTestStartedMessage(&message);
  55.545 +        }
  55.546 +    }
  55.547 +
  55.548 +    if (!processed)
  55.549 +    {
  55.550 +        LatencyTestButtonMessage message; 
  55.551 +        if (DecodeLatencyTestButtonMessage(&message, pData, length))     
  55.552 +        {
  55.553 +            processed = true;
  55.554 +            onLatencyTestButtonMessage(&message);
  55.555 +        }
  55.556 +    }
  55.557 +}
  55.558 +
  55.559 +bool LatencyTestDeviceImpl::SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag)
  55.560 +{  
  55.561 +    bool                result = false;
  55.562 +    ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue();
  55.563 +
  55.564 +    if (GetManagerImpl()->GetThreadId() != OVR::GetCurrentThreadId())
  55.565 +    {
  55.566 +        if (!waitFlag)
  55.567 +        {
  55.568 +            return queue->PushCall(this, &LatencyTestDeviceImpl::setConfiguration, configuration);
  55.569 +        }
  55.570 +
  55.571 +        if (!queue->PushCallAndWaitResult(  this, 
  55.572 +            &LatencyTestDeviceImpl::setConfiguration,
  55.573 +            &result, 
  55.574 +            configuration))
  55.575 +        {
  55.576 +            return false;
  55.577 +        }
  55.578 +    }
  55.579 +    else
  55.580 +        return setConfiguration(configuration);
  55.581 +
  55.582 +    return result;
  55.583 +}
  55.584 +
  55.585 +bool LatencyTestDeviceImpl::setConfiguration(const OVR::LatencyTestConfiguration& configuration)
  55.586 +{
  55.587 +    LatencyTestConfigurationImpl ltc(configuration);
  55.588 +    return GetInternalDevice()->SetFeatureReport(ltc.Buffer, LatencyTestConfigurationImpl::PacketSize);
  55.589 +}
  55.590 +
  55.591 +bool LatencyTestDeviceImpl::GetConfiguration(OVR::LatencyTestConfiguration* configuration)
  55.592 +{  
  55.593 +    bool result = false;
  55.594 +
  55.595 +	ThreadCommandQueue* pQueue = this->GetManagerImpl()->GetThreadQueue();
  55.596 +    if (!pQueue->PushCallAndWaitResult(this, &LatencyTestDeviceImpl::getConfiguration, &result, configuration))
  55.597 +        return false;
  55.598 +
  55.599 +    return result;
  55.600 +}
  55.601 +
  55.602 +bool LatencyTestDeviceImpl::getConfiguration(OVR::LatencyTestConfiguration* configuration)
  55.603 +{
  55.604 +    LatencyTestConfigurationImpl ltc(*configuration);
  55.605 +    if (GetInternalDevice()->GetFeatureReport(ltc.Buffer, LatencyTestConfigurationImpl::PacketSize))
  55.606 +    {
  55.607 +        ltc.Unpack();
  55.608 +        *configuration = ltc.Configuration;
  55.609 +        return true;
  55.610 +    }
  55.611 +
  55.612 +    return false;
  55.613 +}
  55.614 +
  55.615 +bool LatencyTestDeviceImpl::SetCalibrate(const Color& calibrationColor, bool waitFlag)
  55.616 +{
  55.617 +    bool                result = false;
  55.618 +    ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue();
  55.619 +
  55.620 +    if (!waitFlag)
  55.621 +    {
  55.622 +        return queue->PushCall(this, &LatencyTestDeviceImpl::setCalibrate, calibrationColor);
  55.623 +    }
  55.624 +
  55.625 +    if (!queue->PushCallAndWaitResult(  this, 
  55.626 +                                        &LatencyTestDeviceImpl::setCalibrate,
  55.627 +                                        &result, 
  55.628 +                                        calibrationColor))
  55.629 +    {
  55.630 +        return false;
  55.631 +    }
  55.632 +
  55.633 +    return result;
  55.634 +}
  55.635 +
  55.636 +bool LatencyTestDeviceImpl::setCalibrate(const Color& calibrationColor)
  55.637 +{
  55.638 +    LatencyTestCalibrateImpl ltc(calibrationColor);
  55.639 +    return GetInternalDevice()->SetFeatureReport(ltc.Buffer, LatencyTestCalibrateImpl::PacketSize);
  55.640 +}
  55.641 +
  55.642 +bool LatencyTestDeviceImpl::SetStartTest(const Color& targetColor, bool waitFlag)
  55.643 +{
  55.644 +    bool                result = false;
  55.645 +    ThreadCommandQueue* queue = GetManagerImpl()->GetThreadQueue();
  55.646 +
  55.647 +    if (!waitFlag)
  55.648 +    {
  55.649 +        return queue->PushCall(this, &LatencyTestDeviceImpl::setStartTest, targetColor);
  55.650 +    }
  55.651 +
  55.652 +    if (!queue->PushCallAndWaitResult(  this, 
  55.653 +                                        &LatencyTestDeviceImpl::setStartTest,
  55.654 +                                        &result, 
  55.655 +                                        targetColor))
  55.656 +    {
  55.657 +        return false;
  55.658 +    }
  55.659 +
  55.660 +    return result;
  55.661 +}
  55.662 +
  55.663 +bool LatencyTestDeviceImpl::setStartTest(const Color& targetColor)
  55.664 +{
  55.665 +    LatencyTestStartTestImpl ltst(targetColor);
  55.666 +    return GetInternalDevice()->SetFeatureReport(ltst.Buffer, LatencyTestStartTestImpl::PacketSize);
  55.667 +}
  55.668 +
  55.669 +bool LatencyTestDeviceImpl::SetDisplay(const OVR::LatencyTestDisplay& display, bool waitFlag)
  55.670 +{
  55.671 +    bool                 result = false;
  55.672 +    ThreadCommandQueue * queue = GetManagerImpl()->GetThreadQueue();
  55.673 +
  55.674 +    if (!waitFlag)
  55.675 +    {
  55.676 +        return queue->PushCall(this, &LatencyTestDeviceImpl::setDisplay, display);
  55.677 +    }
  55.678 +
  55.679 +    if (!queue->PushCallAndWaitResult(  this, 
  55.680 +                                        &LatencyTestDeviceImpl::setDisplay,
  55.681 +                                        &result, 
  55.682 +                                        display))
  55.683 +    {
  55.684 +        return false;
  55.685 +    }
  55.686 +
  55.687 +    return result;
  55.688 +}
  55.689 +
  55.690 +bool LatencyTestDeviceImpl::setDisplay(const OVR::LatencyTestDisplay& display)
  55.691 +{
  55.692 +    LatencyTestDisplayImpl ltd(display);
  55.693 +    return GetInternalDevice()->SetFeatureReport(ltd.Buffer, LatencyTestDisplayImpl::PacketSize);
  55.694 +}
  55.695 +
  55.696 +void LatencyTestDeviceImpl::onLatencyTestSamplesMessage(LatencyTestSamplesMessage* message)
  55.697 +{
  55.698 +
  55.699 +    if (message->Type != LatencyTestMessage_Samples)
  55.700 +        return;
  55.701 +
  55.702 +    LatencyTestSamples& s = message->Samples;
  55.703 +
  55.704 +    // Call OnMessage() within a lock to avoid conflicts with handlers.
  55.705 +    Lock::Locker scopeLock(HandlerRef.GetLock());
  55.706 +  
  55.707 +    if (HandlerRef.GetHandler())
  55.708 +    {
  55.709 +        MessageLatencyTestSamples samples(this);
  55.710 +        for (UByte i = 0; i < s.SampleCount; i++)
  55.711 +        {            
  55.712 +            samples.Samples.PushBack(Color(s.Samples[i].Value[0], s.Samples[i].Value[1], s.Samples[i].Value[2]));
  55.713 +        }
  55.714 +
  55.715 +        HandlerRef.GetHandler()->OnMessage(samples);
  55.716 +    }
  55.717 +}
  55.718 +
  55.719 +void LatencyTestDeviceImpl::onLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message)
  55.720 +{
  55.721 +    if (message->Type != LatencyTestMessage_ColorDetected)
  55.722 +        return;
  55.723 +
  55.724 +    LatencyTestColorDetected& s = message->ColorDetected;
  55.725 +
  55.726 +    // Call OnMessage() within a lock to avoid conflicts with handlers.
  55.727 +    Lock::Locker scopeLock(HandlerRef.GetLock());
  55.728 +
  55.729 +    if (HandlerRef.GetHandler())
  55.730 +    {
  55.731 +        MessageLatencyTestColorDetected detected(this);
  55.732 +        detected.Elapsed = s.Elapsed;
  55.733 +        detected.DetectedValue = Color(s.TriggerValue[0], s.TriggerValue[1], s.TriggerValue[2]);
  55.734 +        detected.TargetValue = Color(s.TargetValue[0], s.TargetValue[1], s.TargetValue[2]);
  55.735 +
  55.736 +        HandlerRef.GetHandler()->OnMessage(detected);
  55.737 +    }
  55.738 +}
  55.739 +
  55.740 +void LatencyTestDeviceImpl::onLatencyTestStartedMessage(LatencyTestStartedMessage* message)
  55.741 +{
  55.742 +    if (message->Type != LatencyTestMessage_TestStarted)
  55.743 +        return;
  55.744 +
  55.745 +    LatencyTestStarted& ts = message->TestStarted;
  55.746 +
  55.747 +    // Call OnMessage() within a lock to avoid conflicts with handlers.
  55.748 +    Lock::Locker scopeLock(HandlerRef.GetLock());
  55.749 +
  55.750 +    if (HandlerRef.GetHandler())
  55.751 +    {
  55.752 +        MessageLatencyTestStarted started(this);
  55.753 +        started.TargetValue = Color(ts.TargetValue[0], ts.TargetValue[1], ts.TargetValue[2]);
  55.754 +
  55.755 +        HandlerRef.GetHandler()->OnMessage(started);
  55.756 +    }
  55.757 +}
  55.758 +
  55.759 +void LatencyTestDeviceImpl::onLatencyTestButtonMessage(LatencyTestButtonMessage* message)
  55.760 +{
  55.761 +    if (message->Type != LatencyTestMessage_Button)
  55.762 +        return;
  55.763 +
  55.764 +//  LatencyTestButton& s = message->Button;
  55.765 +
  55.766 +    // Call OnMessage() within a lock to avoid conflicts with handlers.
  55.767 +    Lock::Locker scopeLock(HandlerRef.GetLock());
  55.768 +
  55.769 +    if (HandlerRef.GetHandler())
  55.770 +    {
  55.771 +        MessageLatencyTestButton button(this);
  55.772 +
  55.773 +        HandlerRef.GetHandler()->OnMessage(button);
  55.774 +    }
  55.775 +}
  55.776 +
  55.777 +} // namespace OVR
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/libovr/Src/OVR_LatencyTestImpl.h	Sat Sep 14 16:14:59 2013 +0300
    56.3 @@ -0,0 +1,133 @@
    56.4 +/************************************************************************************
    56.5 +
    56.6 +Filename    :   OVR_LatencyTestImpl.h
    56.7 +Content     :   Latency Tester specific implementation.
    56.8 +Created     :   March 7, 2013
    56.9 +Authors     :   Lee Cooper
   56.10 +
   56.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   56.12 +
   56.13 +Use of this software is subject to the terms of the Oculus license
   56.14 +agreement provided at the time of installation or download, or which
   56.15 +otherwise accompanies this software in either electronic or hard copy form.
   56.16 +
   56.17 +*************************************************************************************/
   56.18 +
   56.19 +#ifndef OVR_LatencyTestImpl_h
   56.20 +#define OVR_LatencyTestImpl_h
   56.21 +
   56.22 +#include "OVR_HIDDeviceImpl.h"
   56.23 +
   56.24 +namespace OVR {
   56.25 +
   56.26 +struct LatencyTestSamplesMessage;
   56.27 +struct LatencyTestButtonMessage;
   56.28 +struct LatencyTestStartedMessage;
   56.29 +struct LatencyTestColorDetectedMessage;
   56.30 +
   56.31 +//-------------------------------------------------------------------------------------
   56.32 +// LatencyTestDeviceFactory enumerates Oculus Latency Tester devices.
   56.33 +class LatencyTestDeviceFactory : public DeviceFactory
   56.34 +{
   56.35 +public:
   56.36 +    static LatencyTestDeviceFactory Instance;
   56.37 +
   56.38 +    // Enumerates devices, creating and destroying relevant objects in manager.
   56.39 +    virtual void EnumerateDevices(EnumerateVisitor& visitor);
   56.40 +
   56.41 +    virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const;
   56.42 +    virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc);
   56.43 +
   56.44 +protected:
   56.45 +    DeviceManager* getManager() const { return (DeviceManager*) pManager; }   
   56.46 +};
   56.47 +
   56.48 +
   56.49 +// Describes a single a Oculus Latency Tester device and supports creating its instance.
   56.50 +class LatencyTestDeviceCreateDesc : public HIDDeviceCreateDesc
   56.51 +{
   56.52 +public:
   56.53 +    LatencyTestDeviceCreateDesc(DeviceFactory* factory, const HIDDeviceDesc& hidDesc)
   56.54 +        : HIDDeviceCreateDesc(factory, Device_LatencyTester, hidDesc) { }
   56.55 +    
   56.56 +    virtual DeviceCreateDesc* Clone() const
   56.57 +    {
   56.58 +        return new LatencyTestDeviceCreateDesc(*this);
   56.59 +    }
   56.60 +
   56.61 +    virtual DeviceBase* NewDeviceInstance();
   56.62 +
   56.63 +    virtual MatchResult MatchDevice(const DeviceCreateDesc& other,
   56.64 +                                    DeviceCreateDesc**) const
   56.65 +    {
   56.66 +        if ((other.Type == Device_LatencyTester) && (pFactory == other.pFactory))
   56.67 +        {            
   56.68 +            const LatencyTestDeviceCreateDesc& s2 = (const LatencyTestDeviceCreateDesc&) other;
   56.69 +            if (MatchHIDDevice(s2.HIDDesc))
   56.70 +                return Match_Found;
   56.71 +        }
   56.72 +        return Match_None;
   56.73 +    }
   56.74 +
   56.75 +    virtual bool MatchHIDDevice(const HIDDeviceDesc& hidDesc) const
   56.76 +    {
   56.77 +        // should paths comparison be case insensitive?
   56.78 +        return ((HIDDesc.Path.CompareNoCase(hidDesc.Path) == 0) &&
   56.79 +                (HIDDesc.SerialNumber == hidDesc.SerialNumber));
   56.80 +    }
   56.81 +    virtual bool        GetDeviceInfo(DeviceInfo* info) const;
   56.82 +};
   56.83 +
   56.84 +
   56.85 +//-------------------------------------------------------------------------------------
   56.86 +// ***** OVR::LatencyTestDeviceImpl
   56.87 +
   56.88 +// Oculus Latency Tester interface.
   56.89 +
   56.90 +class LatencyTestDeviceImpl : public HIDDeviceImpl<OVR::LatencyTestDevice>
   56.91 +{
   56.92 +public:
   56.93 +     LatencyTestDeviceImpl(LatencyTestDeviceCreateDesc* createDesc);
   56.94 +    ~LatencyTestDeviceImpl();
   56.95 +
   56.96 +    // DeviceCommon interface.
   56.97 +    virtual bool Initialize(DeviceBase* parent);
   56.98 +    virtual void Shutdown();
   56.99 +
  56.100 +    // DeviceManagerThread::Notifier interface.
  56.101 +    virtual void OnInputReport(UByte* pData, UInt32 length);
  56.102 +
  56.103 +    // LatencyTesterDevice interface
  56.104 +    virtual bool SetConfiguration(const OVR::LatencyTestConfiguration& configuration, bool waitFlag = false);
  56.105 +    virtual bool GetConfiguration(OVR::LatencyTestConfiguration* configuration);
  56.106 +
  56.107 +    virtual bool SetCalibrate(const Color& calibrationColor, bool waitFlag = false);
  56.108 +
  56.109 +    virtual bool SetStartTest(const Color& targetColor, bool waitFlag = false);
  56.110 +    virtual bool SetDisplay(const LatencyTestDisplay& display, bool waitFlag = false);
  56.111 +
  56.112 +protected:
  56.113 +    bool    openDevice(const char** errorFormatString);
  56.114 +    void    closeDevice();
  56.115 +    void    closeDeviceOnIOError();
  56.116 +
  56.117 +    bool    initializeRead();
  56.118 +    bool    processReadResult();
  56.119 +
  56.120 +    bool    setConfiguration(const OVR::LatencyTestConfiguration& configuration);
  56.121 +    bool    getConfiguration(OVR::LatencyTestConfiguration* configuration);
  56.122 +    bool    setCalibrate(const Color& calibrationColor);
  56.123 +    bool    setStartTest(const Color& targetColor);
  56.124 +    bool    setDisplay(const OVR::LatencyTestDisplay& display);
  56.125 +
  56.126 +    // Called for decoded messages
  56.127 +    void onLatencyTestSamplesMessage(LatencyTestSamplesMessage* message);
  56.128 +    void onLatencyTestButtonMessage(LatencyTestButtonMessage* message);
  56.129 +    void onLatencyTestStartedMessage(LatencyTestStartedMessage* message);
  56.130 +    void onLatencyTestColorDetectedMessage(LatencyTestColorDetectedMessage* message);
  56.131 +
  56.132 +};
  56.133 +
  56.134 +} // namespace OVR
  56.135 +
  56.136 +#endif // OVR_LatencyTestImpl_h
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/libovr/Src/OVR_Profile.cpp	Sat Sep 14 16:14:59 2013 +0300
    57.3 @@ -0,0 +1,671 @@
    57.4 +/************************************************************************************
    57.5 +
    57.6 +PublicHeader:   None
    57.7 +Filename    :   OVR_Profile.cpp
    57.8 +Content     :   Structs and functions for loading and storing device profile settings
    57.9 +Created     :   February 14, 2013
   57.10 +Notes       :
   57.11 +   
   57.12 +   Profiles are used to store per-user settings that can be transferred and used
   57.13 +   across multiple applications.  For example, player IPD can be configured once 
   57.14 +   and reused for a unified experience across games.  Configuration and saving of profiles
   57.15 +   can be accomplished in game via the Profile API or by the official Oculus Configuration
   57.16 +   Utility.
   57.17 +
   57.18 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   57.19 +
   57.20 +Use of this software is subject to the terms of the Oculus license
   57.21 +agreement provided at the time of installation or download, or which
   57.22 +otherwise accompanies this software in either electronic or hard copy form.
   57.23 +
   57.24 +************************************************************************************/
   57.25 +
   57.26 +#include "OVR_Profile.h"
   57.27 +#include "OVR_JSON.h"
   57.28 +#include "Kernel/OVR_Types.h"
   57.29 +#include "Kernel/OVR_SysFile.h"
   57.30 +#include "Kernel/OVR_Allocator.h"
   57.31 +#include "Kernel/OVR_Array.h"
   57.32 +
   57.33 +#ifdef OVR_OS_WIN32
   57.34 +#include <Shlobj.h>
   57.35 +#else
   57.36 +#include <dirent.h>
   57.37 +#include <sys/stat.h>
   57.38 +
   57.39 +#ifdef OVR_OS_LINUX
   57.40 +#include <unistd.h>
   57.41 +#include <pwd.h>
   57.42 +#endif
   57.43 +
   57.44 +#endif
   57.45 +
   57.46 +#define PROFILE_VERSION 1.0
   57.47 +
   57.48 +namespace OVR {
   57.49 +
   57.50 +//-----------------------------------------------------------------------------
   57.51 +// Returns the pathname of the JSON file containing the stored profiles
   57.52 +String GetBaseOVRPath(bool create_dir)
   57.53 +{
   57.54 +    String path;
   57.55 +
   57.56 +#if defined(OVR_OS_WIN32)
   57.57 +
   57.58 +    TCHAR data_path[MAX_PATH];
   57.59 +    SHGetFolderPath(0, CSIDL_LOCAL_APPDATA, NULL, 0, data_path);
   57.60 +    path = String(data_path);
   57.61 +    
   57.62 +    path += "/Oculus";
   57.63 +
   57.64 +    if (create_dir)
   57.65 +    {   // Create the Oculus directory if it doesn't exist
   57.66 +        WCHAR wpath[128];
   57.67 +        OVR::UTF8Util::DecodeString(wpath, path.ToCStr());
   57.68 +
   57.69 +        DWORD attrib = GetFileAttributes(wpath);
   57.70 +        bool exists = attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY);
   57.71 +        if (!exists)
   57.72 +        {   
   57.73 +            CreateDirectory(wpath, NULL);
   57.74 +        }
   57.75 +    }
   57.76 +        
   57.77 +#elif defined(OVR_OS_MAC)
   57.78 +
   57.79 +    const char* home = getenv("HOME");
   57.80 +    path = home;
   57.81 +    path += "/Library/Preferences/Oculus";
   57.82 +
   57.83 +    if (create_dir)
   57.84 +    {   // Create the Oculus directory if it doesn't exist
   57.85 +        DIR* dir = opendir(path);
   57.86 +        if (dir == NULL)
   57.87 +        {
   57.88 +            mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
   57.89 +        }
   57.90 +        else
   57.91 +        {
   57.92 +            closedir(dir);
   57.93 +        }
   57.94 +    }
   57.95 +
   57.96 +#else
   57.97 +
   57.98 +    passwd* pwd = getpwuid(getuid());
   57.99 +    const char* home = pwd->pw_dir;
  57.100 +    path = home;
  57.101 +    path += "/.config/Oculus";
  57.102 +
  57.103 +    if (create_dir)
  57.104 +    {   // Create the Oculus directory if it doesn't exist
  57.105 +        DIR* dir = opendir(path);
  57.106 +        if (dir == NULL)
  57.107 +        {
  57.108 +            mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO);
  57.109 +        }
  57.110 +        else
  57.111 +        {
  57.112 +            closedir(dir);
  57.113 +        }
  57.114 +    }
  57.115 +
  57.116 +#endif
  57.117 +
  57.118 +    return path;
  57.119 +}
  57.120 +
  57.121 +String GetProfilePath(bool create_dir)
  57.122 +{
  57.123 +    String path = GetBaseOVRPath(create_dir);
  57.124 +    path += "/Profiles.json";
  57.125 +    return path;
  57.126 +}
  57.127 +
  57.128 +//-----------------------------------------------------------------------------
  57.129 +// ***** ProfileManager
  57.130 +
  57.131 +ProfileManager::ProfileManager()
  57.132 +{
  57.133 +    Changed = false;
  57.134 +    CacheDevice = Profile_Unknown;
  57.135 +}
  57.136 +
  57.137 +ProfileManager::~ProfileManager()
  57.138 +{
  57.139 +    // If the profiles have been altered then write out the profile file
  57.140 +    if (Changed)
  57.141 +        SaveCache();
  57.142 +
  57.143 +    ClearCache();
  57.144 +}
  57.145 +
  57.146 +ProfileManager* ProfileManager::Create()
  57.147 +{
  57.148 +    return new ProfileManager();
  57.149 +}
  57.150 +
  57.151 +Profile* ProfileManager::CreateProfileObject(const char* user,
  57.152 +                                             ProfileType device,
  57.153 +                                             const char** device_name)
  57.154 +{
  57.155 +    Lock::Locker lockScope(&ProfileLock);
  57.156 +
  57.157 +    Profile* profile = NULL;
  57.158 +    switch (device)
  57.159 +    {
  57.160 +        case Profile_RiftDK1:
  57.161 +            *device_name = "RiftDK1";
  57.162 +            profile = new RiftDK1Profile(user);
  57.163 +            break;
  57.164 +        case Profile_RiftDKHD:
  57.165 +        case Profile_Unknown:
  57.166 +            break;
  57.167 +    }
  57.168 +
  57.169 +    return profile;
  57.170 +}
  57.171 +
  57.172 +
  57.173 +// Clear the local profile cache
  57.174 +void ProfileManager::ClearCache()
  57.175 +{
  57.176 +    Lock::Locker lockScope(&ProfileLock);
  57.177 +
  57.178 +    ProfileCache.Clear();
  57.179 +    CacheDevice = Profile_Unknown;
  57.180 +}
  57.181 +
  57.182 +
  57.183 +// Poplulates the local profile cache.  This occurs on the first access of the profile
  57.184 +// data.  All profile operations are performed against the local cache until the
  57.185 +// ProfileManager is released or goes out of scope at which time the cache is serialized
  57.186 +// to disk.
  57.187 +void ProfileManager::LoadCache(ProfileType device)
  57.188 +{
  57.189 +    Lock::Locker lockScope(&ProfileLock);
  57.190 +
  57.191 +    ClearCache();
  57.192 +
  57.193 +    String path = GetProfilePath(false);
  57.194 +
  57.195 +    Ptr<JSON> root = *JSON::Load(path);
  57.196 +    if (!root || root->GetItemCount() < 3)
  57.197 +        return;
  57.198 +
  57.199 +    // First read the file type and version to make sure this is a valid file
  57.200 +    JSON* item0 = root->GetFirstItem();
  57.201 +    JSON* item1 = root->GetNextItem(item0);
  57.202 +    JSON* item2 = root->GetNextItem(item1);
  57.203 +
  57.204 +    if (OVR_strcmp(item0->Name, "Oculus Profile Version") == 0)
  57.205 +    {   // In the future I may need to check versioning to determine parse method
  57.206 +    }
  57.207 +    else
  57.208 +    {
  57.209 +        return;
  57.210 +    }
  57.211 +
  57.212 +    DefaultProfile = item1->Value;
  57.213 +
  57.214 +    // Read the number of profiles
  57.215 +    int   profileCount = (int)item2->dValue;
  57.216 +    JSON* profileItem  = item2;
  57.217 +
  57.218 +    for (int p=0; p<profileCount; p++)
  57.219 +    {
  57.220 +        profileItem = profileItem->GetNextItem(profileItem);
  57.221 +        if (!profileItem)
  57.222 +            break;
  57.223 +        
  57.224 +        // Read the required Name field
  57.225 +        const char* profileName;
  57.226 +        JSON* item = profileItem->GetFirstItem();
  57.227 +        
  57.228 +        if (item && (OVR_strcmp(item->Name, "Name") == 0))
  57.229 +        {   
  57.230 +            profileName = item->Value;
  57.231 +        }
  57.232 +        else
  57.233 +        {
  57.234 +            return;   // invalid field
  57.235 +        }
  57.236 +
  57.237 +        const char*   deviceName  = 0;
  57.238 +        bool          deviceFound = false;
  57.239 +        Ptr<Profile>  profile     = *CreateProfileObject(profileName, device, &deviceName);
  57.240 +
  57.241 +        // Read the base profile fields.
  57.242 +        if (profile)
  57.243 +        {
  57.244 +            while (item = profileItem->GetNextItem(item), item)
  57.245 +            {
  57.246 +                if (item->Type != JSON_Object)
  57.247 +                {
  57.248 +                    profile->ParseProperty(item->Name, item->Value);
  57.249 +                }
  57.250 +                else
  57.251 +                {   // Search for the matching device to get device specific fields
  57.252 +                    if (!deviceFound && OVR_strcmp(item->Name, deviceName) == 0)
  57.253 +                    {
  57.254 +                        deviceFound = true;
  57.255 +
  57.256 +                        for (JSON* deviceItem = item->GetFirstItem(); deviceItem;
  57.257 +                             deviceItem = item->GetNextItem(deviceItem))
  57.258 +                        {
  57.259 +                            profile->ParseProperty(deviceItem->Name, deviceItem->Value);
  57.260 +                        }
  57.261 +                    }
  57.262 +                }
  57.263 +            }
  57.264 +        }
  57.265 +
  57.266 +        // Add the new profile
  57.267 +        if (deviceFound)
  57.268 +            ProfileCache.PushBack(profile);
  57.269 +    }
  57.270 +
  57.271 +    CacheDevice = device;
  57.272 +}
  57.273 +
  57.274 +
  57.275 +// Serializes the profiles to disk.
  57.276 +void ProfileManager::SaveCache()
  57.277 +{
  57.278 +    String path = GetProfilePath(true);
  57.279 + 
  57.280 +    Lock::Locker lockScope(&ProfileLock);
  57.281 +
  57.282 +    // TODO: Since there is only a single device type now, a full tree overwrite
  57.283 +    // is sufficient but in the future a selective device branch replacement will
  57.284 +    // be necessary
  57.285 +
  57.286 +    Ptr<JSON> root = *JSON::CreateObject();
  57.287 +    root->AddNumberItem("Oculus Profile Version", PROFILE_VERSION);
  57.288 +    root->AddStringItem("CurrentProfile", DefaultProfile);
  57.289 +    root->AddNumberItem("ProfileCount", (double) ProfileCache.GetSize());
  57.290 +
  57.291 +    // Generate a JSON subtree for each profile
  57.292 +    for (unsigned int i=0; i<ProfileCache.GetSize(); i++)
  57.293 +    {
  57.294 +        Profile* profile = ProfileCache[i];
  57.295 +
  57.296 +        JSON* json_profile = JSON::CreateObject();
  57.297 +        json_profile->Name = "Profile";
  57.298 +        json_profile->AddStringItem("Name", profile->Name);
  57.299 +        const char* gender;
  57.300 +        switch (profile->GetGender())
  57.301 +        {
  57.302 +            case Profile::Gender_Male:   gender = "Male"; break;
  57.303 +            case Profile::Gender_Female: gender = "Female"; break;
  57.304 +            default: gender = "Unspecified";
  57.305 +        }
  57.306 +        json_profile->AddStringItem("Gender", gender);
  57.307 +        json_profile->AddNumberItem("PlayerHeight", profile->PlayerHeight);
  57.308 +        json_profile->AddNumberItem("IPD", profile->IPD);
  57.309 +
  57.310 +        if (profile->Type == Profile_RiftDK1)
  57.311 +        {
  57.312 +            RiftDK1Profile* riftdk1 = (RiftDK1Profile*)profile;
  57.313 +            JSON* json_riftdk1 = JSON::CreateObject();
  57.314 +            json_profile->AddItem("RiftDK1", json_riftdk1);
  57.315 +
  57.316 +            const char* eyecup = "A";
  57.317 +            switch (riftdk1->EyeCups)
  57.318 +            {
  57.319 +                case RiftDK1Profile::EyeCup_A: eyecup = "A"; break;
  57.320 +                case RiftDK1Profile::EyeCup_B: eyecup = "B"; break;
  57.321 +                case RiftDK1Profile::EyeCup_C: eyecup = "C"; break;
  57.322 +            }
  57.323 +            json_riftdk1->AddStringItem("EyeCup", eyecup);
  57.324 +            json_riftdk1->AddNumberItem("LL", riftdk1->LL);
  57.325 +            json_riftdk1->AddNumberItem("LR", riftdk1->LR);
  57.326 +            json_riftdk1->AddNumberItem("RL", riftdk1->RL);
  57.327 +            json_riftdk1->AddNumberItem("RR", riftdk1->RR);
  57.328 +        }
  57.329 +
  57.330 +        root->AddItem("Profile", json_profile);
  57.331 +    }
  57.332 +
  57.333 +    root->Save(path);
  57.334 +}
  57.335 +
  57.336 +// Returns the number of stored profiles for this device type
  57.337 +int ProfileManager::GetProfileCount(ProfileType device)
  57.338 +{
  57.339 +    Lock::Locker lockScope(&ProfileLock);
  57.340 +
  57.341 +    if (CacheDevice == Profile_Unknown)
  57.342 +        LoadCache(device);
  57.343 +
  57.344 +    return (int)ProfileCache.GetSize();
  57.345 +}
  57.346 +
  57.347 +// Returns the profile name of a specific profile in the list.  The returned 
  57.348 +// memory is locally allocated and should not be stored or deleted.  Returns NULL
  57.349 +// if the index is invalid
  57.350 +const char* ProfileManager::GetProfileName(ProfileType device, unsigned int index)
  57.351 +{
  57.352 +    Lock::Locker lockScope(&ProfileLock);
  57.353 +
  57.354 +    if (CacheDevice == Profile_Unknown)
  57.355 +        LoadCache(device);
  57.356 +
  57.357 +    if (index < ProfileCache.GetSize())
  57.358 +    {
  57.359 +        Profile* profile = ProfileCache[index];
  57.360 +        OVR_strcpy(NameBuff, Profile::MaxNameLen, profile->Name);
  57.361 +        return NameBuff;
  57.362 +    }
  57.363 +    else
  57.364 +    {
  57.365 +        return NULL;
  57.366 +    }
  57.367 +}
  57.368 +
  57.369 +bool ProfileManager::HasProfile(ProfileType device, const char* name)
  57.370 +{
  57.371 +    Lock::Locker lockScope(&ProfileLock);
  57.372 +
  57.373 +    if (CacheDevice == Profile_Unknown)
  57.374 +        LoadCache(device);
  57.375 +
  57.376 +    for (unsigned i = 0; i< ProfileCache.GetSize(); i++)
  57.377 +    {
  57.378 +        if (ProfileCache[i] && OVR_strcmp(ProfileCache[i]->Name, name) == 0)
  57.379 +            return true;
  57.380 +    }
  57.381 +    return false;
  57.382 +}
  57.383 +
  57.384 +
  57.385 +// Returns a specific profile object in the list.  The returned memory should be
  57.386 +// encapsulated in a Ptr<> object or released after use.  Returns NULL if the index
  57.387 +// is invalid
  57.388 +Profile* ProfileManager::LoadProfile(ProfileType device, unsigned int index)
  57.389 +{
  57.390 +    Lock::Locker lockScope(&ProfileLock);
  57.391 +
  57.392 +    if (CacheDevice == Profile_Unknown)
  57.393 +        LoadCache(device);
  57.394 +
  57.395 +    if (index < ProfileCache.GetSize())
  57.396 +    {
  57.397 +        Profile* profile = ProfileCache[index];
  57.398 +        return profile->Clone();
  57.399 +    }
  57.400 +    else
  57.401 +    {
  57.402 +        return NULL;
  57.403 +    }
  57.404 +}
  57.405 +
  57.406 +// Returns a profile object for a particular device and user name.  The returned 
  57.407 +// memory should be encapsulated in a Ptr<> object or released after use.  Returns 
  57.408 +// NULL if the profile is not found
  57.409 +Profile* ProfileManager::LoadProfile(ProfileType device, const char* user)
  57.410 +{
  57.411 +    if (user == NULL)
  57.412 +        return NULL;
  57.413 +
  57.414 +    Lock::Locker lockScope(&ProfileLock);
  57.415 +    
  57.416 +    if (CacheDevice == Profile_Unknown)
  57.417 +        LoadCache(device);
  57.418 +
  57.419 +    for (unsigned int i=0; i<ProfileCache.GetSize(); i++)
  57.420 +    {
  57.421 +        if (OVR_strcmp(user, ProfileCache[i]->Name) == 0)
  57.422 +        {   // Found the requested user profile
  57.423 +            Profile* profile = ProfileCache[i];
  57.424 +            return profile->Clone();
  57.425 +        }
  57.426 +    }
  57.427 +
  57.428 +    return NULL;
  57.429 +}
  57.430 +
  57.431 +// Returns a profile with all system default values
  57.432 +Profile* ProfileManager::GetDeviceDefaultProfile(ProfileType device)
  57.433 +{
  57.434 +    const char* device_name = NULL;
  57.435 +    return CreateProfileObject("default", device, &device_name);
  57.436 +}
  57.437 +
  57.438 +// Returns the name of the profile that is marked as the current default user.
  57.439 +const char* ProfileManager::GetDefaultProfileName(ProfileType device)
  57.440 +{
  57.441 +    Lock::Locker lockScope(&ProfileLock);
  57.442 +
  57.443 +    if (CacheDevice == Profile_Unknown)
  57.444 +        LoadCache(device);
  57.445 +
  57.446 +    if (ProfileCache.GetSize() > 0)
  57.447 +    {
  57.448 +        OVR_strcpy(NameBuff, Profile::MaxNameLen, DefaultProfile);
  57.449 +        return NameBuff;
  57.450 +    }
  57.451 +    else
  57.452 +    {
  57.453 +        return NULL;
  57.454 +    }
  57.455 +}
  57.456 +
  57.457 +// Marks a particular user as the current default user.
  57.458 +bool ProfileManager::SetDefaultProfileName(ProfileType device, const char* name)
  57.459 +{
  57.460 +    Lock::Locker lockScope(&ProfileLock);
  57.461 +
  57.462 +    if (CacheDevice == Profile_Unknown)
  57.463 +        LoadCache(device);
  57.464 +// TODO: I should verify that the user is valid
  57.465 +    if (ProfileCache.GetSize() > 0)
  57.466 +    {
  57.467 +        DefaultProfile = name;
  57.468 +        Changed = true;
  57.469 +        return true;
  57.470 +    }
  57.471 +    else
  57.472 +    {
  57.473 +        return false;
  57.474 +    }
  57.475 +}
  57.476 +
  57.477 +
  57.478 +// Saves a new or existing profile.  Returns true on success or false on an
  57.479 +// invalid or failed save.
  57.480 +bool ProfileManager::Save(const Profile* profile)
  57.481 +{
  57.482 +    Lock::Locker lockScope(&ProfileLock);
  57.483 +
  57.484 +    if (OVR_strcmp(profile->Name, "default") == 0)
  57.485 +        return false;  // don't save a default profile
  57.486 +
  57.487 +    // TODO: I should also verify that this profile type matches the current cache
  57.488 +    if (CacheDevice == Profile_Unknown)
  57.489 +        LoadCache(profile->Type);
  57.490 +
  57.491 +    // Look for the pre-existence of this profile
  57.492 +    bool added = false;
  57.493 +    for (unsigned int i=0; i<ProfileCache.GetSize(); i++)
  57.494 +    {
  57.495 +        int compare = OVR_strcmp(profile->Name, ProfileCache[i]->Name);
  57.496 +              
  57.497 +        if (compare == 0)
  57.498 +        {   
  57.499 +            // TODO: I should do a proper field comparison to avoid unnecessary
  57.500 +            // overwrites and file saves
  57.501 +
  57.502 +            // Replace the previous instance with the new profile
  57.503 +            ProfileCache[i] = *profile->Clone();
  57.504 +            added   = true;
  57.505 +            Changed = true;
  57.506 +            break;
  57.507 +        }
  57.508 +    }
  57.509 +
  57.510 +    if (!added)
  57.511 +    {
  57.512 +        ProfileCache.PushBack(*profile->Clone());
  57.513 +        if (ProfileCache.GetSize() == 1)
  57.514 +            CacheDevice = profile->Type;
  57.515 +
  57.516 +        Changed = true;
  57.517 +    }
  57.518 +
  57.519 +    return true;
  57.520 +}
  57.521 +
  57.522 +// Removes an existing profile.  Returns true if the profile was found and deleted
  57.523 +// and returns false otherwise.
  57.524 +bool ProfileManager::Delete(const Profile* profile)
  57.525 +{
  57.526 +    Lock::Locker lockScope(&ProfileLock);
  57.527 +
  57.528 +    if (OVR_strcmp(profile->Name, "default") == 0)
  57.529 +        return false;  // don't delete a default profile
  57.530 +
  57.531 +    if (CacheDevice == Profile_Unknown)
  57.532 +        LoadCache(profile->Type);
  57.533 +
  57.534 +    // Look for the existence of this profile
  57.535 +    for (unsigned int i=0; i<ProfileCache.GetSize(); i++)
  57.536 +    {
  57.537 +        if (OVR_strcmp(profile->Name, ProfileCache[i]->Name) == 0)
  57.538 +        {  
  57.539 +            if (OVR_strcmp(profile->Name, DefaultProfile) == 0)
  57.540 +                DefaultProfile.Clear();
  57.541 +            
  57.542 +            ProfileCache.RemoveAt(i);
  57.543 +            Changed = true;
  57.544 +            return true;
  57.545 +        }
  57.546 +    }
  57.547 +
  57.548 +    return false;
  57.549 +}
  57.550 +
  57.551 +
  57.552 +
  57.553 +//-----------------------------------------------------------------------------
  57.554 +// ***** Profile
  57.555 +
  57.556 +Profile::Profile(ProfileType device, const char* name)
  57.557 +{
  57.558 +    Type         = device;
  57.559 +    Gender       = Gender_Unspecified;
  57.560 +    PlayerHeight = 1.778f;    // 5'10" inch man
  57.561 +    IPD          = 0.064f;
  57.562 +    OVR_strcpy(Name, MaxNameLen, name);
  57.563 +}
  57.564 +
  57.565 +
  57.566 +bool Profile::ParseProperty(const char* prop, const char* sval)
  57.567 +{
  57.568 +    if (OVR_strcmp(prop, "Name") == 0)
  57.569 +    {
  57.570 +        OVR_strcpy(Name, MaxNameLen, sval);
  57.571 +        return true;
  57.572 +    }
  57.573 +    else if (OVR_strcmp(prop, "Gender") == 0)
  57.574 +    {
  57.575 +        if (OVR_strcmp(sval, "Male") == 0)
  57.576 +            Gender = Gender_Male;
  57.577 +        else if (OVR_strcmp(sval, "Female") == 0)
  57.578 +            Gender = Gender_Female;
  57.579 +        else
  57.580 +            Gender = Gender_Unspecified;
  57.581 +
  57.582 +        return true;
  57.583 +    }
  57.584 +    else if (OVR_strcmp(prop, "PlayerHeight") == 0)
  57.585 +    {
  57.586 +        PlayerHeight = (float)atof(sval);
  57.587 +        return true;
  57.588 +    }
  57.589 +    else if (OVR_strcmp(prop, "IPD") == 0)
  57.590 +    {
  57.591 +        IPD = (float)atof(sval);
  57.592 +        return true;
  57.593 +    }
  57.594 +
  57.595 +    return false;
  57.596 +}
  57.597 +
  57.598 +
  57.599 +// Computes the eye height from the metric head height
  57.600 +float Profile::GetEyeHeight()
  57.601 +{
  57.602 +    const float EYE_TO_HEADTOP_RATIO =   0.44538f;
  57.603 +    const float MALE_AVG_HEAD_HEIGHT =   0.232f;
  57.604 +    const float FEMALE_AVG_HEAD_HEIGHT = 0.218f;
  57.605 +     
  57.606 +    // compute distance from top of skull to the eye
  57.607 +    float head_height;
  57.608 +    if (Gender == Gender_Female)
  57.609 +        head_height = FEMALE_AVG_HEAD_HEIGHT;
  57.610 +    else
  57.611 +        head_height = MALE_AVG_HEAD_HEIGHT;
  57.612 +
  57.613 +    float skull = EYE_TO_HEADTOP_RATIO * head_height;
  57.614 +
  57.615 +    float eye_height  = PlayerHeight - skull;
  57.616 +    return eye_height;
  57.617 +}
  57.618 +
  57.619 +
  57.620 +//-----------------------------------------------------------------------------
  57.621 +// ***** RiftDK1Profile
  57.622 +
  57.623 +RiftDK1Profile::RiftDK1Profile(const char* name) : Profile(Profile_RiftDK1, name)
  57.624 +{
  57.625 +    EyeCups = EyeCup_A;
  57.626 +    LL = 0;
  57.627 +    LR = 0;
  57.628 +    RL = 0;
  57.629 +    RR = 0;
  57.630 +}
  57.631 +
  57.632 +bool RiftDK1Profile::ParseProperty(const char* prop, const char* sval)
  57.633 +{
  57.634 +    if (OVR_strcmp(prop, "EyeCup") == 0)
  57.635 +    {
  57.636 +        switch (sval[0])
  57.637 +        {
  57.638 +            case 'C': EyeCups = EyeCup_C; break;
  57.639 +            case 'B': EyeCups = EyeCup_B; break;
  57.640 +            default:  EyeCups = EyeCup_A; break;
  57.641 +        }
  57.642 +        return true;
  57.643 +    }
  57.644 +    else if (OVR_strcmp(prop, "LL") == 0)
  57.645 +    {
  57.646 +        LL = atoi(sval);
  57.647 +        return true;
  57.648 +    }
  57.649 +    else if (OVR_strcmp(prop, "LR") == 0)
  57.650 +    {
  57.651 +        LR = atoi(sval);
  57.652 +        return true;
  57.653 +    }
  57.654 +    else if (OVR_strcmp(prop, "RL") == 0)
  57.655 +    {
  57.656 +        RL = atoi(sval);
  57.657 +        return true;
  57.658 +    }
  57.659 +    else if (OVR_strcmp(prop, "RR") == 0)
  57.660 +    {
  57.661 +        RR = atoi(sval);
  57.662 +        return true;
  57.663 +    }
  57.664 +    
  57.665 +    return Profile::ParseProperty(prop, sval);
  57.666 +}
  57.667 +
  57.668 +Profile* RiftDK1Profile::Clone() const
  57.669 +{
  57.670 +    RiftDK1Profile* profile = new RiftDK1Profile(*this);
  57.671 +    return profile;
  57.672 +}
  57.673 +
  57.674 +}  // OVR
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/libovr/Src/OVR_Profile.h	Sat Sep 14 16:14:59 2013 +0300
    58.3 @@ -0,0 +1,189 @@
    58.4 +/************************************************************************************
    58.5 +
    58.6 +PublicHeader:   OVR.h
    58.7 +Filename    :   OVR_Profile.h
    58.8 +Content     :   Structs and functions for loading and storing device profile settings
    58.9 +Created     :   February 14, 2013
   58.10 +Notes       :
   58.11 +   Profiles are used to store per-user settings that can be transferred and used
   58.12 +   across multiple applications.  For example, player IPD can be configured once 
   58.13 +   and reused for a unified experience across games.  Configuration and saving of profiles
   58.14 +   can be accomplished in game via the Profile API or by the official Oculus Configuration
   58.15 +   Utility.
   58.16 +
   58.17 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   58.18 +
   58.19 +Use of this software is subject to the terms of the Oculus license
   58.20 +agreement provided at the time of installation or download, or which
   58.21 +otherwise accompanies this software in either electronic or hard copy form.
   58.22 +
   58.23 +************************************************************************************/
   58.24 +
   58.25 +#ifndef OVR_Profile_h
   58.26 +#define OVR_Profile_h
   58.27 +
   58.28 +#include "Kernel/OVR_String.h"
   58.29 +#include "Kernel/OVR_RefCount.h"
   58.30 +#include "Kernel/OVR_Array.h"
   58.31 +
   58.32 +namespace OVR {
   58.33 +
   58.34 +// Defines the profile object for each device type
   58.35 +enum ProfileType
   58.36 +{
   58.37 +    Profile_Unknown       = 0,
   58.38 +    Profile_RiftDK1       = 1,
   58.39 +    Profile_RiftDKHD      = 2,
   58.40 +};
   58.41 +
   58.42 +class Profile;
   58.43 +
   58.44 +// -----------------------------------------------------------------------------
   58.45 +// ***** ProfileManager
   58.46 +
   58.47 +// Profiles are interfaced through a ProfileManager object.  Applications should
   58.48 +// create a ProfileManager each time they intend to read or write user profile data.
   58.49 +// The scope of the ProfileManager object defines when disk I/O is performed.  Disk
   58.50 +// reads are performed on the first profile access and disk writes are performed when
   58.51 +// the ProfileManager goes out of scope.  All profile interactions between these times
   58.52 +// are performed in local memory and are fast.  A typical profile interaction might
   58.53 +// look like this:
   58.54 +//
   58.55 +// {
   58.56 +//     Ptr<ProfileManager> pm      = *ProfileManager::Create();
   58.57 +//     Ptr<Profile>        profile = pm->LoadProfile(Profile_RiftDK1,
   58.58 +//                                                   pm->GetDefaultProfileName(Profile_RiftDK1));
   58.59 +//     if (profile)
   58.60 +//     {   // Retrieve the current profile settings
   58.61 +//     }
   58.62 +// }   // Profile will be destroyed and any disk I/O completed when going out of scope
   58.63 +
   58.64 +class ProfileManager : public RefCountBase<ProfileManager>
   58.65 +{
   58.66 +protected:
   58.67 +    // Synchronize ProfileManager access since it may be accessed from multiple threads,
   58.68 +    // as it's shared through DeviceManager.
   58.69 +    Lock                    ProfileLock;
   58.70 +    Array<Ptr<Profile> >    ProfileCache;
   58.71 +    ProfileType             CacheDevice;
   58.72 +    String                  DefaultProfile;
   58.73 +    bool                    Changed;
   58.74 +    char                    NameBuff[32];
   58.75 +    
   58.76 +public:
   58.77 +    static ProfileManager* Create();
   58.78 +
   58.79 +    // Static interface functions
   58.80 +    int                 GetProfileCount(ProfileType device);
   58.81 +    const char*         GetProfileName(ProfileType device, unsigned int index);
   58.82 +    bool                HasProfile(ProfileType device, const char* name);
   58.83 +    Profile*            LoadProfile(ProfileType device, unsigned int index);
   58.84 +    Profile*            LoadProfile(ProfileType device, const char* name);
   58.85 +    Profile*            GetDeviceDefaultProfile(ProfileType device);
   58.86 +    const char*         GetDefaultProfileName(ProfileType device);
   58.87 +    bool                SetDefaultProfileName(ProfileType device, const char* name);
   58.88 +    bool                Save(const Profile* profile);
   58.89 +    bool                Delete(const Profile* profile);
   58.90 +
   58.91 +protected:
   58.92 +    ProfileManager();
   58.93 +    ~ProfileManager();
   58.94 +    void                LoadCache(ProfileType device);
   58.95 +    void                SaveCache();
   58.96 +    void                ClearCache();
   58.97 +    Profile*            CreateProfileObject(const char* user,
   58.98 +                                            ProfileType device,
   58.99 +                                            const char** device_name);
  58.100 +};
  58.101 +
  58.102 +//-------------------------------------------------------------------
  58.103 +// ***** Profile
  58.104 +
  58.105 +// The base profile for all HMD devices.  This object is never created directly.
  58.106 +// Instead derived objects provide specific data implementations.  Some settings
  58.107 +// such as IPD will be tied to a specific user and be consistent between ,
  58.108 +// implementations but other settings like optical distortion may vary between devices.
  58.109 +
  58.110 +class Profile : public RefCountBase<Profile>
  58.111 +{
  58.112 +public:
  58.113 +    enum { MaxNameLen    = 32 };
  58.114 +
  58.115 +    enum GenderType
  58.116 +    {
  58.117 +        Gender_Unspecified  = 0,
  58.118 +        Gender_Male         = 1,
  58.119 +        Gender_Female       = 2
  58.120 +    };
  58.121 +
  58.122 +    ProfileType Type;              // The type of device profile
  58.123 +    char        Name[MaxNameLen];  // The name given to this profile
  58.124 +
  58.125 +protected:
  58.126 +    GenderType  Gender;            // The gender of the user
  58.127 +    float       PlayerHeight;      // The height of the user in meters
  58.128 +    float       IPD;               // Distance between eyes in meters
  58.129 +
  58.130 +public:
  58.131 +    // These are properties which are intrinsic to the user and affect scene setup
  58.132 +    GenderType      GetGender()                     { return Gender; };
  58.133 +    float           GetPlayerHeight()               { return PlayerHeight; };
  58.134 +    float           GetIPD()                        { return IPD; };
  58.135 +    float           GetEyeHeight();    
  58.136 +    
  58.137 +    void            SetGender(GenderType gender)    { Gender = gender; };
  58.138 +    void            SetPlayerHeight(float height)   { PlayerHeight = height; };
  58.139 +    void            SetIPD(float ipd)               { IPD = ipd; };
  58.140 +
  58.141 +
  58.142 +protected:
  58.143 +    Profile(ProfileType type, const char* name);
  58.144 +
  58.145 +    virtual Profile*     Clone() const = 0;
  58.146 +    virtual bool         ParseProperty(const char* prop, const char* sval);
  58.147 +    
  58.148 +    friend class ProfileManager;
  58.149 +};
  58.150 +
  58.151 +
  58.152 +//-----------------------------------------------------------------------------
  58.153 +// ***** RiftDK1Profile
  58.154 +
  58.155 +// This profile is specific to the Rift Dev Kit 1 and contains overrides specific 
  58.156 +// to that device and lens cup settings.
  58.157 +class RiftDK1Profile : public Profile
  58.158 +{
  58.159 +public:
  58.160 +    enum EyeCupType
  58.161 +    {
  58.162 +        EyeCup_A = 0,
  58.163 +        EyeCup_B = 1,
  58.164 +        EyeCup_C = 2
  58.165 +    };
  58.166 +
  58.167 +protected:
  58.168 +    EyeCupType  EyeCups;            // Which eye cup does the player use
  58.169 +    int         LL;                 // Configuration Utility IPD setting
  58.170 +    int         LR;                 // Configuration Utility IPD setting
  58.171 +    int         RL;                 // Configuration Utility IPD setting
  58.172 +    int         RR;                 // Configuration Utility IPD setting
  58.173 +
  58.174 +public:
  58.175 +    EyeCupType          GetEyeCup() { return EyeCups; };
  58.176 +    void                SetEyeCup(EyeCupType cup) { EyeCups = cup; };
  58.177 +
  58.178 +protected:
  58.179 +    RiftDK1Profile(const char* name);
  58.180 +
  58.181 +    virtual Profile*    Clone() const;
  58.182 +    virtual bool        ParseProperty(const char* prop, const char* sval);
  58.183 +
  58.184 +    friend class ProfileManager;
  58.185 +};
  58.186 +
  58.187 +
  58.188 +String GetBaseOVRPath(bool create_dir);
  58.189 +
  58.190 +}
  58.191 +
  58.192 +#endif // OVR_Profile_h
  58.193 \ No newline at end of file
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/libovr/Src/OVR_SensorFilter.cpp	Sat Sep 14 16:14:59 2013 +0300
    59.3 @@ -0,0 +1,201 @@
    59.4 +/************************************************************************************
    59.5 +
    59.6 +PublicHeader:   OVR.h
    59.7 +Filename    :   OVR_SensorFilter.cpp
    59.8 +Content     :   Basic filtering of sensor data
    59.9 +Created     :   March 7, 2013
   59.10 +Authors     :   Steve LaValle, Anna Yershova
   59.11 +
   59.12 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   59.13 +
   59.14 +Use of this software is subject to the terms of the Oculus license
   59.15 +agreement provided at the time of installation or download, or which
   59.16 +otherwise accompanies this software in either electronic or hard copy form.
   59.17 +
   59.18 +*************************************************************************************/
   59.19 +
   59.20 +#include "OVR_SensorFilter.h"
   59.21 +
   59.22 +namespace OVR {
   59.23 +
   59.24 +Vector3f SensorFilter::Total() const
   59.25 +{
   59.26 +    Vector3f total = Vector3f(0.0f, 0.0f, 0.0f);
   59.27 +    for (int i = 0; i < Size; i++)
   59.28 +        total += Elements[i];
   59.29 +    return total;
   59.30 +}
   59.31 +
   59.32 +Vector3f SensorFilter::Mean() const
   59.33 +{
   59.34 +    Vector3f total = Vector3f(0.0f, 0.0f, 0.0f);
   59.35 +    for (int i = 0; i < Size; i++)
   59.36 +        total += Elements[i];
   59.37 +    return total / (float) Size;
   59.38 +}
   59.39 +
   59.40 +Vector3f SensorFilter::Median() const
   59.41 +{
   59.42 +    int half_window = (int) Size / 2;
   59.43 +    float sortx[MaxFilterSize];
   59.44 +    float resultx = 0.0f;
   59.45 +
   59.46 +    float sorty[MaxFilterSize];
   59.47 +    float resulty = 0.0f;
   59.48 +
   59.49 +    float sortz[MaxFilterSize];
   59.50 +    float resultz = 0.0f;
   59.51 +
   59.52 +    for (int i = 0; i < Size; i++) 
   59.53 +    {
   59.54 +        sortx[i] = Elements[i].x;
   59.55 +        sorty[i] = Elements[i].y;
   59.56 +        sortz[i] = Elements[i].z;
   59.57 +    }
   59.58 +    for (int j = 0; j <= half_window; j++) 
   59.59 +    {
   59.60 +        int minx = j;
   59.61 +        int miny = j;
   59.62 +        int minz = j;
   59.63 +        for (int k = j + 1; k < Size; k++) 
   59.64 +        {
   59.65 +            if (sortx[k] < sortx[minx]) minx = k;
   59.66 +            if (sorty[k] < sorty[miny]) miny = k;
   59.67 +            if (sortz[k] < sortz[minz]) minz = k;
   59.68 +        }
   59.69 +        const float tempx = sortx[j];
   59.70 +        const float tempy = sorty[j];
   59.71 +        const float tempz = sortz[j];
   59.72 +        sortx[j] = sortx[minx];
   59.73 +        sortx[minx] = tempx;
   59.74 +
   59.75 +        sorty[j] = sorty[miny];
   59.76 +        sorty[miny] = tempy;
   59.77 +
   59.78 +        sortz[j] = sortz[minz];
   59.79 +        sortz[minz] = tempz;
   59.80 +    }
   59.81 +    resultx = sortx[half_window];
   59.82 +    resulty = sorty[half_window];
   59.83 +    resultz = sortz[half_window];
   59.84 +
   59.85 +    return Vector3f(resultx, resulty, resultz);
   59.86 +}
   59.87 +
   59.88 +//  Only the diagonal of the covariance matrix.
   59.89 +Vector3f SensorFilter::Variance() const
   59.90 +{
   59.91 +    Vector3f mean = Mean();
   59.92 +    Vector3f total = Vector3f(0.0f, 0.0f, 0.0f);
   59.93 +    for (int i = 0; i < Size; i++) 
   59.94 +    {
   59.95 +        total.x += (Elements[i].x - mean.x) * (Elements[i].x - mean.x);
   59.96 +        total.y += (Elements[i].y - mean.y) * (Elements[i].y - mean.y);
   59.97 +        total.z += (Elements[i].z - mean.z) * (Elements[i].z - mean.z);
   59.98 +    }
   59.99 +    return total / (float) Size;
  59.100 +}
  59.101 +
  59.102 +// Should be a 3x3 matrix returned, but OVR_math.h doesn't have one
  59.103 +Matrix4f SensorFilter::Covariance() const
  59.104 +{
  59.105 +    Vector3f mean = Mean();
  59.106 +    Matrix4f total = Matrix4f(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0);
  59.107 +    for (int i = 0; i < Size; i++) 
  59.108 +    {
  59.109 +        total.M[0][0] += (Elements[i].x - mean.x) * (Elements[i].x - mean.x);
  59.110 +        total.M[1][0] += (Elements[i].y - mean.y) * (Elements[i].x - mean.x);
  59.111 +        total.M[2][0] += (Elements[i].z - mean.z) * (Elements[i].x - mean.x);
  59.112 +        total.M[1][1] += (Elements[i].y - mean.y) * (Elements[i].y - mean.y);
  59.113 +        total.M[2][1] += (Elements[i].z - mean.z) * (Elements[i].y - mean.y);
  59.114 +        total.M[2][2] += (Elements[i].z - mean.z) * (Elements[i].z - mean.z);
  59.115 +    }
  59.116 +    total.M[0][1] = total.M[1][0];
  59.117 +    total.M[0][2] = total.M[2][0];
  59.118 +    total.M[1][2] = total.M[2][1];
  59.119 +    for (int i = 0; i < 3; i++)
  59.120 +        for (int j = 0; j < 3; j++)
  59.121 +            total.M[i][j] *= 1.0f / Size;
  59.122 +    return total;
  59.123 +}
  59.124 +
  59.125 +Vector3f SensorFilter::PearsonCoefficient() const
  59.126 +{
  59.127 +    Matrix4f cov = Covariance();
  59.128 +    Vector3f pearson = Vector3f();
  59.129 +    pearson.x = cov.M[0][1]/(sqrt(cov.M[0][0])*sqrt(cov.M[1][1]));
  59.130 +    pearson.y = cov.M[1][2]/(sqrt(cov.M[1][1])*sqrt(cov.M[2][2]));
  59.131 +    pearson.z = cov.M[2][0]/(sqrt(cov.M[2][2])*sqrt(cov.M[0][0]));
  59.132 +
  59.133 +    return pearson;
  59.134 +}
  59.135 +
  59.136 +
  59.137 +Vector3f SensorFilter::SavitzkyGolaySmooth8() const
  59.138 +{
  59.139 +    OVR_ASSERT(Size >= 8);
  59.140 +    return GetPrev(0)*0.41667f +
  59.141 +            GetPrev(1)*0.33333f +
  59.142 +            GetPrev(2)*0.25f +
  59.143 +            GetPrev(3)*0.16667f +
  59.144 +            GetPrev(4)*0.08333f -
  59.145 +            GetPrev(6)*0.08333f -
  59.146 +            GetPrev(7)*0.16667f;
  59.147 +}
  59.148 +
  59.149 +
  59.150 +Vector3f SensorFilter::SavitzkyGolayDerivative4() const
  59.151 +{
  59.152 +    OVR_ASSERT(Size >= 4);
  59.153 +    return GetPrev(0)*0.3f +
  59.154 +            GetPrev(1)*0.1f -
  59.155 +            GetPrev(2)*0.1f -
  59.156 +            GetPrev(3)*0.3f;
  59.157 +}
  59.158 +
  59.159 +Vector3f SensorFilter::SavitzkyGolayDerivative5() const
  59.160 +{
  59.161 +    OVR_ASSERT(Size >= 5);
  59.162 +    return GetPrev(0)*0.2f +
  59.163 +            GetPrev(1)*0.1f -
  59.164 +            GetPrev(3)*0.1f -
  59.165 +            GetPrev(4)*0.2f;
  59.166 +}
  59.167 +
  59.168 +Vector3f SensorFilter::SavitzkyGolayDerivative12() const
  59.169 +{
  59.170 +    OVR_ASSERT(Size >= 12);
  59.171 +    return GetPrev(0)*0.03846f +
  59.172 +            GetPrev(1)*0.03147f +
  59.173 +            GetPrev(2)*0.02448f +
  59.174 +            GetPrev(3)*0.01748f +
  59.175 +            GetPrev(4)*0.01049f +
  59.176 +            GetPrev(5)*0.0035f -
  59.177 +            GetPrev(6)*0.0035f -
  59.178 +            GetPrev(7)*0.01049f -
  59.179 +            GetPrev(8)*0.01748f -
  59.180 +            GetPrev(9)*0.02448f -
  59.181 +            GetPrev(10)*0.03147f -
  59.182 +            GetPrev(11)*0.03846f;
  59.183 +}
  59.184 +
  59.185 +Vector3f SensorFilter::SavitzkyGolayDerivativeN(int n) const
  59.186 +{    
  59.187 +    OVR_ASSERT(Size >= n);
  59.188 +    int m = (n-1)/2;
  59.189 +    Vector3f result = Vector3f();
  59.190 +    for (int k = 1; k <= m; k++) 
  59.191 +    {
  59.192 +        int ind1 = m - k;
  59.193 +        int ind2 = n - m + k - 1;
  59.194 +        result += (GetPrev(ind1) - GetPrev(ind2)) * (float) k;
  59.195 +    }
  59.196 +    float coef = 3.0f/(m*(m+1.0f)*(2.0f*m+1.0f));
  59.197 +    result = result*coef;
  59.198 +    return result;
  59.199 +}
  59.200 +
  59.201 +
  59.202 +
  59.203 +
  59.204 +} //namespace OVR
  59.205 \ No newline at end of file
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/libovr/Src/OVR_SensorFilter.h	Sat Sep 14 16:14:59 2013 +0300
    60.3 @@ -0,0 +1,99 @@
    60.4 +/************************************************************************************
    60.5 +
    60.6 +PublicHeader:   OVR.h
    60.7 +Filename    :   OVR_SensorFilter.h
    60.8 +Content     :   Basic filtering of sensor data
    60.9 +Created     :   March 7, 2013
   60.10 +Authors     :   Steve LaValle, Anna Yershova
   60.11 +
   60.12 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   60.13 +
   60.14 +Use of this software is subject to the terms of the Oculus license
   60.15 +agreement provided at the time of installation or download, or which
   60.16 +otherwise accompanies this software in either electronic or hard copy form.
   60.17 +
   60.18 +*************************************************************************************/
   60.19 +
   60.20 +#ifndef OVR_SensorFilter_h
   60.21 +#define OVR_SensorFilter_h
   60.22 +
   60.23 +#include "Kernel/OVR_Math.h"
   60.24 +
   60.25 +
   60.26 +namespace OVR {
   60.27 +
   60.28 +// This class maintains a sliding window of sensor data taken over time and implements
   60.29 +// various simple filters, most of which are linear functions of the data history.
   60.30 +class SensorFilter
   60.31 +{
   60.32 +    enum
   60.33 +    {
   60.34 +        MaxFilterSize     = 100,
   60.35 +        DefaultFilterSize = 20
   60.36 +    };
   60.37 +
   60.38 +private:
   60.39 +    int         LastIdx;                    // The index of the last element that was added to the array
   60.40 +    int         Size;                       // The window size (number of elements)
   60.41 +    Vector3f    Elements[MaxFilterSize]; 
   60.42 +
   60.43 +public:
   60.44 +    // Create a new filter with default size
   60.45 +    SensorFilter() 
   60.46 +    {
   60.47 +        LastIdx = -1;
   60.48 +        Size = DefaultFilterSize;
   60.49 +    };
   60.50 +
   60.51 +    // Create a new filter with size i
   60.52 +    SensorFilter(int i) 
   60.53 +    {
   60.54 +        OVR_ASSERT(i <= MaxFilterSize);
   60.55 +        LastIdx = -1;
   60.56 +        Size = i;
   60.57 +    };
   60.58 +
   60.59 +
   60.60 +    // Create a new element to the filter
   60.61 +    void AddElement (const Vector3f &e) 
   60.62 +    {
   60.63 +        if (LastIdx == Size - 1) 
   60.64 +            LastIdx = 0;
   60.65 +        else                            
   60.66 +            LastIdx++;
   60.67 +
   60.68 +        Elements[LastIdx] = e;
   60.69 +    };
   60.70 +
   60.71 +    // Get element i.  0 is the most recent, 1 is one step ago, 2 is two steps ago, ...
   60.72 +    Vector3f GetPrev(int i) const
   60.73 +    {
   60.74 +		OVR_ASSERT(i >= 0); // 
   60.75 +        int idx = (LastIdx - i);
   60.76 +        if (idx < 0) // Fix the wraparound case
   60.77 +            idx += Size;
   60.78 +		OVR_ASSERT(idx >= 0); // Multiple wraparounds not allowed
   60.79 +        return Elements[idx];
   60.80 +    };
   60.81 +
   60.82 +    // Simple statistics
   60.83 +    Vector3f Total() const;
   60.84 +    Vector3f Mean() const;
   60.85 +    Vector3f Median() const;
   60.86 +    Vector3f Variance() const; // The diagonal of covariance matrix
   60.87 +    Matrix4f Covariance() const;
   60.88 +    Vector3f PearsonCoefficient() const;
   60.89 +
   60.90 +    // A popular family of smoothing filters and smoothed derivatives
   60.91 +    Vector3f SavitzkyGolaySmooth8() const;
   60.92 +    Vector3f SavitzkyGolayDerivative4() const;
   60.93 +    Vector3f SavitzkyGolayDerivative5() const;
   60.94 +    Vector3f SavitzkyGolayDerivative12() const; 
   60.95 +    Vector3f SavitzkyGolayDerivativeN(int n) const;
   60.96 +
   60.97 +    ~SensorFilter() {};
   60.98 +};
   60.99 +
  60.100 +} //namespace OVR
  60.101 +
  60.102 +#endif // OVR_SensorFilter_h
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/libovr/Src/OVR_SensorFusion.cpp	Sat Sep 14 16:14:59 2013 +0300
    61.3 @@ -0,0 +1,696 @@
    61.4 +/************************************************************************************
    61.5 +
    61.6 +Filename    :   OVR_SensorFusion.cpp
    61.7 +Content     :   Methods that determine head orientation from sensor data over time
    61.8 +Created     :   October 9, 2012
    61.9 +Authors     :   Michael Antonov, Steve LaValle
   61.10 +
   61.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   61.12 +
   61.13 +Use of this software is subject to the terms of the Oculus license
   61.14 +agreement provided at the time of installation or download, or which
   61.15 +otherwise accompanies this software in either electronic or hard copy form.
   61.16 +
   61.17 +*************************************************************************************/
   61.18 +
   61.19 +#include "OVR_SensorFusion.h"
   61.20 +#include "Kernel/OVR_Log.h"
   61.21 +#include "Kernel/OVR_System.h"
   61.22 +#include "OVR_JSON.h"
   61.23 +#include "OVR_Profile.h"
   61.24 +
   61.25 +namespace OVR {
   61.26 +
   61.27 +//-------------------------------------------------------------------------------------
   61.28 +// ***** Sensor Fusion
   61.29 +
   61.30 +SensorFusion::SensorFusion(SensorDevice* sensor)
   61.31 +  : Handler(getThis()), pDelegate(0),
   61.32 +    Gain(0.05f), YawMult(1), EnableGravity(true), Stage(0), RunningTime(0), DeltaT(0.001f),
   61.33 +	EnablePrediction(true), PredictionDT(0.03f), PredictionTimeIncrement(0.001f),
   61.34 +    FRawMag(10), FAccW(20), FAngV(20),
   61.35 +    TiltCondCount(0), TiltErrorAngle(0), 
   61.36 +    TiltErrorAxis(0,1,0),
   61.37 +    MagCondCount(0), MagCalibrated(false), MagRefQ(0, 0, 0, 1), 
   61.38 +	MagRefM(0), MagRefYaw(0), YawErrorAngle(0), MagRefDistance(0.5f),
   61.39 +    YawErrorCount(0), YawCorrectionActivated(false), YawCorrectionInProgress(false), 
   61.40 +	EnableYawCorrection(false), MagNumReferences(0), MagHasNearbyReference(false),
   61.41 +    MotionTrackingEnabled(true)
   61.42 +{
   61.43 +   if (sensor)
   61.44 +       AttachToSensor(sensor);
   61.45 +   MagCalibrationMatrix.SetIdentity();
   61.46 +}
   61.47 +
   61.48 +SensorFusion::~SensorFusion()
   61.49 +{
   61.50 +}
   61.51 +
   61.52 +
   61.53 +bool SensorFusion::AttachToSensor(SensorDevice* sensor)
   61.54 +{
   61.55 +    // clear the cached device information
   61.56 +    CachedSensorInfo.SerialNumber[0] = 0;   
   61.57 +    CachedSensorInfo.VendorId = 0;
   61.58 +    CachedSensorInfo.ProductId = 0;
   61.59 +
   61.60 +    if (sensor != NULL)
   61.61 +    {
   61.62 +        // Cache the sensor device so we can access this information during
   61.63 +        // mag saving and loading (avoid holding a reference to sensor to prevent 
   61.64 +        // deadlock on shutdown)
   61.65 +        sensor->GetDeviceInfo(&CachedSensorInfo);   // save the device information
   61.66 +        MessageHandler* pCurrentHandler = sensor->GetMessageHandler();
   61.67 +
   61.68 +        if (pCurrentHandler == &Handler)
   61.69 +        {
   61.70 +            Reset();
   61.71 +            return true;
   61.72 +        }
   61.73 +
   61.74 +        if (pCurrentHandler != NULL)
   61.75 +        {
   61.76 +            OVR_DEBUG_LOG(
   61.77 +                ("SensorFusion::AttachToSensor failed - sensor %p already has handler", sensor));
   61.78 +            return false;
   61.79 +        }
   61.80 +
   61.81 +        // Automatically load the default mag calibration for this sensor
   61.82 +        LoadMagCalibration();        
   61.83 +    }
   61.84 +
   61.85 +    if (Handler.IsHandlerInstalled())
   61.86 +    {
   61.87 +        Handler.RemoveHandlerFromDevices();
   61.88 +    }
   61.89 +
   61.90 +    if (sensor != NULL)
   61.91 +    {
   61.92 +        sensor->SetMessageHandler(&Handler);
   61.93 +    }
   61.94 +
   61.95 +    Reset();
   61.96 +    return true;
   61.97 +}
   61.98 +
   61.99 +
  61.100 +    // Resets the current orientation
  61.101 +void SensorFusion::Reset()
  61.102 +{
  61.103 +    Lock::Locker lockScope(Handler.GetHandlerLock());
  61.104 +    Q                     = Quatf();
  61.105 +    QUncorrected          = Quatf();
  61.106 +    Stage                 = 0;
  61.107 +	RunningTime           = 0;
  61.108 +	MagNumReferences      = 0;
  61.109 +	MagHasNearbyReference = false;
  61.110 +}
  61.111 +
  61.112 +
  61.113 +void SensorFusion::handleMessage(const MessageBodyFrame& msg)
  61.114 +{
  61.115 +    if (msg.Type != Message_BodyFrame || !IsMotionTrackingEnabled())
  61.116 +        return;
  61.117 +  
  61.118 +    // Put the sensor readings into convenient local variables
  61.119 +    Vector3f angVel    = msg.RotationRate; 
  61.120 +    Vector3f rawAccel  = msg.Acceleration;
  61.121 +    Vector3f mag       = msg.MagneticField;
  61.122 +
  61.123 +    // Set variables accessible through the class API
  61.124 +	DeltaT = msg.TimeDelta;
  61.125 +    AngV = msg.RotationRate;
  61.126 +    AngV.y *= YawMult;  // Warning: If YawMult != 1, then AngV is not true angular velocity
  61.127 +    A = rawAccel;
  61.128 +
  61.129 +    // Allow external access to uncalibrated magnetometer values
  61.130 +    RawMag = mag;  
  61.131 +
  61.132 +    // Apply the calibration parameters to raw mag
  61.133 +    if (HasMagCalibration())
  61.134 +    {
  61.135 +        mag.x += MagCalibrationMatrix.M[0][3];
  61.136 +        mag.y += MagCalibrationMatrix.M[1][3];
  61.137 +        mag.z += MagCalibrationMatrix.M[2][3];
  61.138 +    }
  61.139 +
  61.140 +    // Provide external access to calibrated mag values
  61.141 +    // (if the mag is not calibrated, then the raw value is returned)
  61.142 +    CalMag = mag;
  61.143 +
  61.144 +    float angVelLength = angVel.Length();
  61.145 +    float accLength    = rawAccel.Length();
  61.146 +
  61.147 +
  61.148 +    // Acceleration in the world frame (Q is current HMD orientation)
  61.149 +    Vector3f accWorld  = Q.Rotate(rawAccel);
  61.150 +
  61.151 +    // Keep track of time
  61.152 +    Stage++;
  61.153 +    RunningTime += DeltaT;
  61.154 +
  61.155 +    // Insert current sensor data into filter history
  61.156 +    FRawMag.AddElement(RawMag);
  61.157 +    FAccW.AddElement(accWorld);
  61.158 +    FAngV.AddElement(angVel);
  61.159 +
  61.160 +    // Update orientation Q based on gyro outputs.  This technique is
  61.161 +    // based on direct properties of the angular velocity vector:
  61.162 +    // Its direction is the current rotation axis, and its magnitude
  61.163 +    // is the rotation rate (rad/sec) about that axis.  Our sensor
  61.164 +    // sampling rate is so fast that we need not worry about integral
  61.165 +    // approximation error (not yet, anyway).
  61.166 +    if (angVelLength > 0.0f)
  61.167 +    {
  61.168 +        Vector3f     rotAxis      = angVel / angVelLength;  
  61.169 +        float        halfRotAngle = angVelLength * DeltaT * 0.5f;
  61.170 +        float        sinHRA       = sin(halfRotAngle);
  61.171 +        Quatf        deltaQ(rotAxis.x*sinHRA, rotAxis.y*sinHRA, rotAxis.z*sinHRA, cos(halfRotAngle));
  61.172 +
  61.173 +        Q =  Q * deltaQ;
  61.174 +    }
  61.175 +    
  61.176 +    // The quaternion magnitude may slowly drift due to numerical error,
  61.177 +    // so it is periodically normalized.
  61.178 +    if (Stage % 5000 == 0)
  61.179 +        Q.Normalize();
  61.180 +    
  61.181 +	// Maintain the uncorrected orientation for later use by predictive filtering
  61.182 +	QUncorrected = Q;
  61.183 +
  61.184 +    // Perform tilt correction using the accelerometer data. This enables 
  61.185 +    // drift errors in pitch and roll to be corrected. Note that yaw cannot be corrected
  61.186 +    // because the rotation axis is parallel to the gravity vector.
  61.187 +    if (EnableGravity)
  61.188 +    {
  61.189 +        // Correcting for tilt error by using accelerometer data
  61.190 +        const float  gravityEpsilon = 0.4f;
  61.191 +        const float  angVelEpsilon  = 0.1f; // Relatively slow rotation
  61.192 +        const int    tiltPeriod     = 50;   // Required time steps of stability
  61.193 +        const float  maxTiltError   = 0.05f;
  61.194 +        const float  minTiltError   = 0.01f;
  61.195 +
  61.196 +        // This condition estimates whether the only measured acceleration is due to gravity 
  61.197 +        // (the Rift is not linearly accelerating).  It is often wrong, but tends to average
  61.198 +        // out well over time.
  61.199 +        if ((fabs(accLength - 9.81f) < gravityEpsilon) &&
  61.200 +            (angVelLength < angVelEpsilon))
  61.201 +            TiltCondCount++;
  61.202 +        else
  61.203 +            TiltCondCount = 0;
  61.204 +    
  61.205 +        // After stable measurements have been taken over a sufficiently long period,
  61.206 +        // estimate the amount of tilt error and calculate the tilt axis for later correction.
  61.207 +        if (TiltCondCount >= tiltPeriod)
  61.208 +        {   // Update TiltErrorEstimate
  61.209 +            TiltCondCount = 0;
  61.210 +            // Use an average value to reduce noise (could alternatively use an LPF)
  61.211 +            Vector3f accWMean = FAccW.Mean();
  61.212 +            // Project the acceleration vector into the XZ plane
  61.213 +            Vector3f xzAcc = Vector3f(accWMean.x, 0.0f, accWMean.z);
  61.214 +            // The unit normal of xzAcc will be the rotation axis for tilt correction
  61.215 +            Vector3f tiltAxis = Vector3f(xzAcc.z, 0.0f, -xzAcc.x).Normalized();
  61.216 +            Vector3f yUp = Vector3f(0.0f, 1.0f, 0.0f);
  61.217 +            // This is the amount of rotation
  61.218 +            float    tiltAngle = yUp.Angle(accWMean);
  61.219 +            // Record values if the tilt error is intolerable
  61.220 +            if (tiltAngle > maxTiltError) 
  61.221 +            {
  61.222 +                TiltErrorAngle = tiltAngle;
  61.223 +                TiltErrorAxis = tiltAxis;
  61.224 +            }
  61.225 +        }
  61.226 +
  61.227 +        // This part performs the actual tilt correction as needed
  61.228 +        if (TiltErrorAngle > minTiltError) 
  61.229 +        {
  61.230 +            if ((TiltErrorAngle > 0.4f)&&(RunningTime < 8.0f))
  61.231 +            {   // Tilt completely to correct orientation
  61.232 +                Q = Quatf(TiltErrorAxis, -TiltErrorAngle) * Q;
  61.233 +                TiltErrorAngle = 0.0f;
  61.234 +            }
  61.235 +            else 
  61.236 +            {
  61.237 +                //LogText("Performing tilt correction  -  Angle: %f   Axis: %f %f %f\n",
  61.238 +                //        TiltErrorAngle,TiltErrorAxis.x,TiltErrorAxis.y,TiltErrorAxis.z);
  61.239 +                //float deltaTiltAngle = -Gain*TiltErrorAngle*0.005f;
  61.240 +                // This uses aggressive correction steps while your head is moving fast
  61.241 +                float deltaTiltAngle = -Gain*TiltErrorAngle*0.005f*(5.0f*angVelLength+1.0f);
  61.242 +                // Incrementally "un-tilt" by a small step size
  61.243 +                Q = Quatf(TiltErrorAxis, deltaTiltAngle) * Q;
  61.244 +                TiltErrorAngle += deltaTiltAngle;
  61.245 +            }
  61.246 +        }
  61.247 +    }
  61.248 +
  61.249 +    // Yaw drift correction based on magnetometer data.  This corrects the part of the drift
  61.250 +    // that the accelerometer cannot handle.
  61.251 +    // This will only work if the magnetometer has been enabled, calibrated, and a reference
  61.252 +    // point has been set.
  61.253 +    const float maxAngVelLength = 3.0f;
  61.254 +    const int   magWindow = 5;
  61.255 +    const float yawErrorMax = 0.1f;
  61.256 +    const float yawErrorMin = 0.01f;
  61.257 +    const int   yawErrorCountLimit = 50;
  61.258 +    const float yawRotationStep = 0.00002f;
  61.259 +
  61.260 +    if (angVelLength < maxAngVelLength)
  61.261 +        MagCondCount++;
  61.262 +    else
  61.263 +        MagCondCount = 0;
  61.264 +
  61.265 +	// Find, create, and utilize reference points for the magnetometer
  61.266 +	// Need to be careful not to set reference points while there is significant tilt error
  61.267 +    if ((EnableYawCorrection && MagCalibrated)&&(RunningTime > 10.0f)&&(TiltErrorAngle < 0.2f))
  61.268 +	{
  61.269 +	  if (MagNumReferences == 0)
  61.270 +      {
  61.271 +		  setMagReference(); // Use the current direction
  61.272 +      }
  61.273 +	  else if (Q.Distance(MagRefQ) > MagRefDistance) 
  61.274 +      {
  61.275 +		  MagHasNearbyReference = false;
  61.276 +          float bestDist = 100000.0f;
  61.277 +          int bestNdx = 0;
  61.278 +          float dist;
  61.279 +          for (int i = 0; i < MagNumReferences; i++)
  61.280 +          {
  61.281 +              dist = Q.Distance(MagRefTableQ[i]);
  61.282 +              if (dist < bestDist)
  61.283 +              {
  61.284 +                  bestNdx = i;
  61.285 +                  bestDist = dist;
  61.286 +              }
  61.287 +          }
  61.288 +
  61.289 +          if (bestDist < MagRefDistance)
  61.290 +          {
  61.291 +              MagHasNearbyReference = true;
  61.292 +              MagRefQ   = MagRefTableQ[bestNdx];
  61.293 +              MagRefM   = MagRefTableM[bestNdx];
  61.294 +              MagRefYaw = MagRefTableYaw[bestNdx];
  61.295 +              //LogText("Using reference %d\n",bestNdx);
  61.296 +          }
  61.297 +          else if (MagNumReferences < MagMaxReferences)
  61.298 +              setMagReference();
  61.299 +	  }
  61.300 +	}
  61.301 +
  61.302 +	YawCorrectionInProgress = false;
  61.303 +    if (EnableYawCorrection && MagCalibrated && (RunningTime > 2.0f) && (MagCondCount >= magWindow) &&
  61.304 +        MagHasNearbyReference)
  61.305 +    {
  61.306 +        // Use rotational invariance to bring reference mag value into global frame
  61.307 +        Vector3f grefmag = MagRefQ.Rotate(GetCalibratedMagValue(MagRefM));
  61.308 +        // Bring current (averaged) mag reading into global frame
  61.309 +        Vector3f gmag = Q.Rotate(GetCalibratedMagValue(FRawMag.Mean()));
  61.310 +        // Calculate the reference yaw in the global frame
  61.311 +        Anglef gryaw = Anglef(atan2(grefmag.x,grefmag.z));
  61.312 +        // Calculate the current yaw in the global frame
  61.313 +        Anglef gyaw = Anglef(atan2(gmag.x,gmag.z));
  61.314 +        // The difference between reference and current yaws is the perceived error
  61.315 +        Anglef YawErrorAngle = gyaw - gryaw;
  61.316 +
  61.317 +        //LogText("Yaw error estimate: %f\n",YawErrorAngle.Get());
  61.318 +        // If the perceived error is large, keep count
  61.319 +        if ((YawErrorAngle.Abs() > yawErrorMax) && (!YawCorrectionActivated))
  61.320 +            YawErrorCount++;
  61.321 +        // After enough iterations of high perceived error, start the correction process
  61.322 +        if (YawErrorCount > yawErrorCountLimit)
  61.323 +            YawCorrectionActivated = true;
  61.324 +        // If the perceived error becomes small, turn off the yaw correction
  61.325 +        if ((YawErrorAngle.Abs() < yawErrorMin) && YawCorrectionActivated) 
  61.326 +        {
  61.327 +            YawCorrectionActivated = false;
  61.328 +            YawErrorCount = 0;
  61.329 +        }
  61.330 +        
  61.331 +        // Perform the actual yaw correction, due to previously detected, large yaw error
  61.332 +        if (YawCorrectionActivated) 
  61.333 +        {
  61.334 +			YawCorrectionInProgress = true;
  61.335 +            // Incrementally "unyaw" by a small step size
  61.336 +            Q = Quatf(Vector3f(0.0f,1.0f,0.0f), -yawRotationStep * YawErrorAngle.Sign()) * Q;
  61.337 +        }
  61.338 +    }
  61.339 +}
  61.340 +
  61.341 + 
  61.342 +//  A predictive filter based on extrapolating the smoothed, current angular velocity
  61.343 +Quatf SensorFusion::GetPredictedOrientation(float pdt)
  61.344 +{		
  61.345 +	Lock::Locker lockScope(Handler.GetHandlerLock());
  61.346 +	Quatf        qP = QUncorrected;
  61.347 +	
  61.348 +    if (EnablePrediction)
  61.349 +    {
  61.350 +		// This method assumes a constant angular velocity
  61.351 +	    Vector3f angVelF  = FAngV.SavitzkyGolaySmooth8();
  61.352 +        float    angVelFL = angVelF.Length();
  61.353 +
  61.354 +		// Force back to raw measurement
  61.355 +        angVelF  = AngV;
  61.356 +		angVelFL = AngV.Length();
  61.357 +
  61.358 +		// Dynamic prediction interval: Based on angular velocity to reduce vibration
  61.359 +		const float minPdt   = 0.001f;
  61.360 +		const float slopePdt = 0.1f;
  61.361 +		float       newpdt   = pdt;
  61.362 +		float       tpdt     = minPdt + slopePdt * angVelFL;
  61.363 +		if (tpdt < pdt)
  61.364 +			newpdt = tpdt;
  61.365 +		//LogText("PredictonDTs: %d\n",(int)(newpdt / PredictionTimeIncrement + 0.5f));
  61.366 +
  61.367 +        if (angVelFL > 0.001f)
  61.368 +        {
  61.369 +            Vector3f    rotAxisP      = angVelF / angVelFL;  
  61.370 +            float       halfRotAngleP = angVelFL * newpdt * 0.5f;
  61.371 +            float       sinaHRAP      = sin(halfRotAngleP);
  61.372 +		    Quatf       deltaQP(rotAxisP.x*sinaHRAP, rotAxisP.y*sinaHRAP,
  61.373 +                                rotAxisP.z*sinaHRAP, cos(halfRotAngleP));
  61.374 +            qP = QUncorrected * deltaQP;
  61.375 +		}
  61.376 +	}
  61.377 +    return qP;
  61.378 +}    
  61.379 +
  61.380 +
  61.381 +Vector3f SensorFusion::GetCalibratedMagValue(const Vector3f& rawMag) const
  61.382 +{
  61.383 +    Vector3f mag = rawMag;
  61.384 +    OVR_ASSERT(HasMagCalibration());
  61.385 +    mag.x += MagCalibrationMatrix.M[0][3];
  61.386 +    mag.y += MagCalibrationMatrix.M[1][3];
  61.387 +    mag.z += MagCalibrationMatrix.M[2][3];
  61.388 +    return mag;
  61.389 +}
  61.390 +
  61.391 +
  61.392 +void SensorFusion::setMagReference(const Quatf& q, const Vector3f& rawMag) 
  61.393 +{
  61.394 +    if (MagNumReferences < MagMaxReferences)
  61.395 +    {
  61.396 +        MagRefTableQ[MagNumReferences] = q;
  61.397 +        MagRefTableM[MagNumReferences] = rawMag; //FRawMag.Mean();
  61.398 +
  61.399 +		//LogText("Inserting reference %d\n",MagNumReferences);
  61.400 +        
  61.401 +		MagRefQ   = q;
  61.402 +        MagRefM   = rawMag;
  61.403 +
  61.404 +        float pitch, roll, yaw;
  61.405 +		Quatf q2 = q;
  61.406 +        q2.GetEulerAngles<Axis_X, Axis_Z, Axis_Y>(&pitch, &roll, &yaw);
  61.407 +        MagRefTableYaw[MagNumReferences] = yaw;
  61.408 +		MagRefYaw = yaw;
  61.409 +
  61.410 +        MagNumReferences++;
  61.411 +
  61.412 +        MagHasNearbyReference = true;
  61.413 +    }
  61.414 +}
  61.415 +
  61.416 +
  61.417 +SensorFusion::BodyFrameHandler::~BodyFrameHandler()
  61.418 +{
  61.419 +    RemoveHandlerFromDevices();
  61.420 +}
  61.421 +
  61.422 +void SensorFusion::BodyFrameHandler::OnMessage(const Message& msg)
  61.423 +{
  61.424 +    if (msg.Type == Message_BodyFrame)
  61.425 +        pFusion->handleMessage(static_cast<const MessageBodyFrame&>(msg));
  61.426 +    if (pFusion->pDelegate)
  61.427 +        pFusion->pDelegate->OnMessage(msg);
  61.428 +}
  61.429 +
  61.430 +bool SensorFusion::BodyFrameHandler::SupportsMessageType(MessageType type) const
  61.431 +{
  61.432 +    return (type == Message_BodyFrame);
  61.433 +}
  61.434 +
  61.435 +// Writes the current calibration for a particular device to a device profile file
  61.436 +// sensor - the sensor that was calibrated
  61.437 +// cal_name - an optional name for the calibration or default if cal_name == NULL
  61.438 +bool SensorFusion::SaveMagCalibration(const char* calibrationName) const
  61.439 +{
  61.440 +    if (CachedSensorInfo.SerialNumber[0] == NULL || !HasMagCalibration())
  61.441 +        return false;
  61.442 +    
  61.443 +    // A named calibration may be specified for calibration in different
  61.444 +    // environments, otherwise the default calibration is used
  61.445 +    if (calibrationName == NULL)
  61.446 +        calibrationName = "default";
  61.447 +
  61.448 +    // Generate a mag calibration event
  61.449 +    JSON* calibration = JSON::CreateObject();
  61.450 +    // (hardcoded for now) the measurement and representation method 
  61.451 +    calibration->AddStringItem("Version", "1.0");   
  61.452 +    calibration->AddStringItem("Name", "default");
  61.453 +
  61.454 +    // time stamp the calibration
  61.455 +    char time_str[64];
  61.456 +   
  61.457 +#ifdef OVR_OS_WIN32
  61.458 +    struct tm caltime;
  61.459 +    localtime_s(&caltime, &MagCalibrationTime);
  61.460 +    strftime(time_str, 64, "%Y-%m-%d %H:%M:%S", &caltime);
  61.461 +#else
  61.462 +    struct tm* caltime;
  61.463 +    caltime = localtime(&MagCalibrationTime);
  61.464 +    strftime(time_str, 64, "%Y-%m-%d %H:%M:%S", caltime);
  61.465 +#endif
  61.466 +   
  61.467 +    calibration->AddStringItem("Time", time_str);
  61.468 +
  61.469 +    // write the full calibration matrix
  61.470 +    Matrix4f calmat = GetMagCalibration();
  61.471 +    char matrix[128];
  61.472 +    int pos = 0;
  61.473 +    for (int r=0; r<4; r++)
  61.474 +    {
  61.475 +        for (int c=0; c<4; c++)
  61.476 +        {
  61.477 +            pos += (int)OVR_sprintf(matrix+pos, 128, "%g ", calmat.M[r][c]);
  61.478 +        }
  61.479 +    }
  61.480 +    calibration->AddStringItem("Calibration", matrix);
  61.481 +
  61.482 +    
  61.483 +    String path = GetBaseOVRPath(true);
  61.484 +    path += "/Devices.json";
  61.485 +
  61.486 +    // Look for a prexisting device file to edit
  61.487 +    Ptr<JSON> root = *JSON::Load(path);
  61.488 +    if (root)
  61.489 +    {   // Quick sanity check of the file type and format before we parse it
  61.490 +        JSON* version = root->GetFirstItem();
  61.491 +        if (version && version->Name == "Oculus Device Profile Version")
  61.492 +        {   // In the future I may need to check versioning to determine parse method
  61.493 +        }
  61.494 +        else
  61.495 +        {
  61.496 +            root->Release();
  61.497 +            root = NULL;
  61.498 +        }
  61.499 +    }
  61.500 +
  61.501 +    JSON* device = NULL;
  61.502 +    if (root)
  61.503 +    {
  61.504 +        device = root->GetFirstItem();   // skip the header
  61.505 +        device = root->GetNextItem(device);
  61.506 +        while (device)
  61.507 +        {   // Search for a previous calibration with the same name for this device
  61.508 +            // and remove it before adding the new one
  61.509 +            if (device->Name == "Device")
  61.510 +            {   
  61.511 +                JSON* item = device->GetItemByName("Serial");
  61.512 +                if (item && item->Value == CachedSensorInfo.SerialNumber)
  61.513 +                {   // found an entry for this device
  61.514 +                    item = device->GetNextItem(item);
  61.515 +                    while (item)
  61.516 +                    {
  61.517 +                        if (item->Name == "MagCalibration")
  61.518 +                        {   
  61.519 +                            JSON* name = item->GetItemByName("Name");
  61.520 +                            if (name && name->Value == calibrationName)
  61.521 +                            {   // found a calibration of the same name
  61.522 +                                item->RemoveNode();
  61.523 +                                item->Release();
  61.524 +                                break;
  61.525 +                            } 
  61.526 +                        }
  61.527 +                        item = device->GetNextItem(item);
  61.528 +                    }
  61.529 +
  61.530 +                    // update the auto-mag flag
  61.531 +                    item = device->GetItemByName("EnableYawCorrection");
  61.532 +                    if (item)
  61.533 +                        item->dValue = (double)EnableYawCorrection;
  61.534 +                    else
  61.535 +                        device->AddBoolItem("EnableYawCorrection", EnableYawCorrection);
  61.536 +
  61.537 +                    break;
  61.538 +                }
  61.539 +            }
  61.540 +
  61.541 +            device = root->GetNextItem(device);
  61.542 +        }
  61.543 +    }
  61.544 +    else
  61.545 +    {   // Create a new device root
  61.546 +        root = *JSON::CreateObject();
  61.547 +        root->AddStringItem("Oculus Device Profile Version", "1.0");
  61.548 +    }
  61.549 +
  61.550 +    if (device == NULL)
  61.551 +    {
  61.552 +        device = JSON::CreateObject();
  61.553 +        device->AddStringItem("Product", CachedSensorInfo.ProductName);
  61.554 +        device->AddNumberItem("ProductID", CachedSensorInfo.ProductId);
  61.555 +        device->AddStringItem("Serial", CachedSensorInfo.SerialNumber);
  61.556 +        device->AddBoolItem("EnableYawCorrection", EnableYawCorrection);
  61.557 +
  61.558 +        root->AddItem("Device", device);
  61.559 +    }
  61.560 +
  61.561 +    // Create and the add the new calibration event to the device
  61.562 +    device->AddItem("MagCalibration", calibration);
  61.563 +
  61.564 +    return root->Save(path);
  61.565 +}
  61.566 +
  61.567 +// Loads a saved calibration for the specified device from the device profile file
  61.568 +// sensor - the sensor that the calibration was saved for
  61.569 +// cal_name - an optional name for the calibration or the default if cal_name == NULL
  61.570 +bool SensorFusion::LoadMagCalibration(const char* calibrationName)
  61.571 +{
  61.572 +    if (CachedSensorInfo.SerialNumber[0] == NULL)
  61.573 +        return false;
  61.574 +
  61.575 +    // A named calibration may be specified for calibration in different
  61.576 +    // environments, otherwise the default calibration is used
  61.577 +    if (calibrationName == NULL)
  61.578 +        calibrationName = "default";
  61.579 +
  61.580 +    String path = GetBaseOVRPath(true);
  61.581 +    path += "/Devices.json";
  61.582 +
  61.583 +    // Load the device profiles
  61.584 +    Ptr<JSON> root = *JSON::Load(path);
  61.585 +    if (root == NULL)
  61.586 +        return false;
  61.587 +
  61.588 +    // Quick sanity check of the file type and format before we parse it
  61.589 +    JSON* version = root->GetFirstItem();
  61.590 +    if (version && version->Name == "Oculus Device Profile Version")
  61.591 +    {   // In the future I may need to check versioning to determine parse method
  61.592 +    }
  61.593 +    else
  61.594 +    {
  61.595 +        return false;
  61.596 +    }
  61.597 +
  61.598 +    bool autoEnableCorrection = false;    
  61.599 +
  61.600 +    JSON* device = root->GetNextItem(version);
  61.601 +    while (device)
  61.602 +    {   // Search for a previous calibration with the same name for this device
  61.603 +        // and remove it before adding the new one
  61.604 +        if (device->Name == "Device")
  61.605 +        {   
  61.606 +            JSON* item = device->GetItemByName("Serial");
  61.607 +            if (item && item->Value == CachedSensorInfo.SerialNumber)
  61.608 +            {   // found an entry for this device
  61.609 +
  61.610 +                JSON* autoyaw = device->GetItemByName("EnableYawCorrection");
  61.611 +                if (autoyaw)
  61.612 +                    autoEnableCorrection = (autoyaw->dValue != 0);
  61.613 +
  61.614 +                item = device->GetNextItem(item);
  61.615 +                while (item)
  61.616 +                {
  61.617 +                    if (item->Name == "MagCalibration")
  61.618 +                    {   
  61.619 +                        JSON* calibration = item;
  61.620 +                        JSON* name = calibration->GetItemByName("Name");
  61.621 +                        if (name && name->Value == calibrationName)
  61.622 +                        {   // found a calibration with this name
  61.623 +                            
  61.624 +                            time_t now;
  61.625 +                            time(&now);
  61.626 +
  61.627 +                            // parse the calibration time
  61.628 +                            time_t calibration_time = now;
  61.629 +                            JSON* caltime = calibration->GetItemByName("Time");
  61.630 +                            if (caltime)
  61.631 +                            {
  61.632 +                                const char* caltime_str = caltime->Value.ToCStr();
  61.633 +
  61.634 +                                tm ct;
  61.635 +                                memset(&ct, 0, sizeof(tm));
  61.636 +                            
  61.637 +#ifdef OVR_OS_WIN32
  61.638 +                                struct tm nowtime;
  61.639 +                                localtime_s(&nowtime, &now);
  61.640 +                                ct.tm_isdst = nowtime.tm_isdst;
  61.641 +                                sscanf_s(caltime_str, "%d-%d-%d %d:%d:%d", 
  61.642 +                                    &ct.tm_year, &ct.tm_mon, &ct.tm_mday,
  61.643 +                                    &ct.tm_hour, &ct.tm_min, &ct.tm_sec);
  61.644 +#else
  61.645 +                                struct tm* nowtime = localtime(&now);
  61.646 +                                ct.tm_isdst = nowtime->tm_isdst;
  61.647 +                                sscanf(caltime_str, "%d-%d-%d %d:%d:%d", 
  61.648 +                                    &ct.tm_year, &ct.tm_mon, &ct.tm_mday,
  61.649 +                                    &ct.tm_hour, &ct.tm_min, &ct.tm_sec);
  61.650 +#endif
  61.651 +                                ct.tm_year -= 1900;
  61.652 +                                ct.tm_mon--;
  61.653 +                                calibration_time = mktime(&ct);
  61.654 +                            }
  61.655 +                                                        
  61.656 +                            // parse the calibration matrix
  61.657 +                            JSON* cal = calibration->GetItemByName("Calibration");
  61.658 +                            if (cal)
  61.659 +                            {
  61.660 +                                const char* data_str = cal->Value.ToCStr();
  61.661 +                                Matrix4f calmat;
  61.662 +                                for (int r=0; r<4; r++)
  61.663 +                                {
  61.664 +                                    for (int c=0; c<4; c++)
  61.665 +                                    {
  61.666 +                                        calmat.M[r][c] = (float)atof(data_str);
  61.667 +                                        while (data_str && *data_str != ' ')
  61.668 +                                            data_str++;
  61.669 +
  61.670 +                                        if (data_str)
  61.671 +                                            data_str++;
  61.672 +                                    }
  61.673 +                                }
  61.674 +
  61.675 +                                SetMagCalibration(calmat);
  61.676 +                                MagCalibrationTime  = calibration_time;
  61.677 +                                EnableYawCorrection = autoEnableCorrection;
  61.678 +
  61.679 +                                return true;
  61.680 +                            }
  61.681 +                        } 
  61.682 +                    }
  61.683 +                    item = device->GetNextItem(item);
  61.684 +                }
  61.685 +
  61.686 +                break;
  61.687 +            }
  61.688 +        }
  61.689 +
  61.690 +        device = root->GetNextItem(device);
  61.691 +    }
  61.692 +    
  61.693 +    return false;
  61.694 +}
  61.695 +
  61.696 +
  61.697 +
  61.698 +} // namespace OVR
  61.699 +
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/libovr/Src/OVR_SensorFusion.h	Sat Sep 14 16:14:59 2013 +0300
    62.3 @@ -0,0 +1,277 @@
    62.4 +/************************************************************************************
    62.5 +
    62.6 +PublicHeader:   OVR.h
    62.7 +Filename    :   OVR_SensorFusion.h
    62.8 +Content     :   Methods that determine head orientation from sensor data over time
    62.9 +Created     :   October 9, 2012
   62.10 +Authors     :   Michael Antonov, Steve LaValle
   62.11 +
   62.12 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   62.13 +
   62.14 +Use of this software is subject to the terms of the Oculus license
   62.15 +agreement provided at the time of installation or download, or which
   62.16 +otherwise accompanies this software in either electronic or hard copy form.
   62.17 +
   62.18 +*************************************************************************************/
   62.19 +
   62.20 +#ifndef OVR_SensorFusion_h
   62.21 +#define OVR_SensorFusion_h
   62.22 +
   62.23 +#include "OVR_Device.h"
   62.24 +#include "OVR_SensorFilter.h"
   62.25 +#include <time.h>
   62.26 +
   62.27 +namespace OVR {
   62.28 +
   62.29 +//-------------------------------------------------------------------------------------
   62.30 +// ***** SensorFusion
   62.31 +
   62.32 +// SensorFusion class accumulates Sensor notification messages to keep track of
   62.33 +// orientation, which involves integrating the gyro and doing correction with gravity.
   62.34 +// Magnetometer based yaw drift correction is also supported; it is usually enabled
   62.35 +// automatically based on loaded magnetometer configuration.
   62.36 +// Orientation is reported as a quaternion, from which users can obtain either the
   62.37 +// rotation matrix or Euler angles.
   62.38 +//
   62.39 +// The class can operate in two ways:
   62.40 +//  - By user manually passing MessageBodyFrame messages to the OnMessage() function. 
   62.41 +//  - By attaching SensorFusion to a SensorDevice, in which case it will
   62.42 +//    automatically handle notifications from that device.
   62.43 +
   62.44 +
   62.45 +class SensorFusion : public NewOverrideBase
   62.46 +{
   62.47 +    enum
   62.48 +    {
   62.49 +        MagMaxReferences = 80
   62.50 +    };        
   62.51 +
   62.52 +public:
   62.53 +    SensorFusion(SensorDevice* sensor = 0);
   62.54 +    ~SensorFusion();
   62.55 +
   62.56 +
   62.57 +    // *** Setup
   62.58 +    
   62.59 +    // Attaches this SensorFusion to a sensor device, from which it will receive
   62.60 +    // notification messages. If a sensor is attached, manual message notification
   62.61 +    // is not necessary. Calling this function also resets SensorFusion state.
   62.62 +    bool        AttachToSensor(SensorDevice* sensor);
   62.63 +
   62.64 +    // Returns true if this Sensor fusion object is attached to a sensor.
   62.65 +    bool        IsAttachedToSensor() const  { return Handler.IsHandlerInstalled(); }
   62.66 +
   62.67 +
   62.68 +
   62.69 +    // *** State Query
   62.70 +
   62.71 +    // Obtain the current accumulated orientation. Many apps will want to use GetPredictedOrientation
   62.72 +    // instead to reduce latency.
   62.73 +    Quatf       GetOrientation() const      { return lockedGet(&Q); }
   62.74 +
   62.75 +    // Get predicted orientaion in the near future; predictDt is lookahead amount in seconds.
   62.76 +    Quatf       GetPredictedOrientation(float predictDt);
   62.77 +    Quatf       GetPredictedOrientation()   { return GetPredictedOrientation(PredictionDT); }
   62.78 +
   62.79 +    // Obtain the last absolute acceleration reading, in m/s^2.
   62.80 +    Vector3f    GetAcceleration() const     { return lockedGet(&A); }
   62.81 +    // Obtain the last angular velocity reading, in rad/s.
   62.82 +    Vector3f    GetAngularVelocity() const  { return lockedGet(&AngV); }
   62.83 +
   62.84 +    // Obtain the last raw magnetometer reading, in Gauss
   62.85 +    Vector3f    GetMagnetometer() const     { return lockedGet(&RawMag); }   
   62.86 +    // Obtain the calibrated magnetometer reading (direction and field strength)
   62.87 +    Vector3f    GetCalibratedMagnetometer() const  { OVR_ASSERT(MagCalibrated); return lockedGet(&CalMag); }
   62.88 +
   62.89 +
   62.90 +    // Resets the current orientation.
   62.91 +    void        Reset();
   62.92 +
   62.93 +
   62.94 +
   62.95 +    // *** Configuration
   62.96 +
   62.97 +    void        EnableMotionTracking(bool enable = true)    { MotionTrackingEnabled = enable; }
   62.98 +    bool        IsMotionTrackingEnabled() const             { return MotionTrackingEnabled;   }
   62.99 +
  62.100 +    // Multiplier for yaw rotation (turning); setting this higher than 1 (the default) can allow the game
  62.101 +    // to be played without auxillary rotation controls, possibly making it more immersive.
  62.102 +    // Whether this is more or less likely to cause motion sickness is unknown.
  62.103 +    float       GetYawMultiplier() const  { return YawMult; }
  62.104 +    void        SetYawMultiplier(float y) { YawMult = y; }
  62.105 +
  62.106 +
  62.107 +    // *** Prediction Control
  62.108 +
  62.109 +    // Prediction functions.
  62.110 +    // Prediction delta specifes how much prediction should be applied in seconds; it should in
  62.111 +    // general be under the average rendering latency. Call GetPredictedOrientation() to get
  62.112 +    // predicted orientation.
  62.113 +    float       GetPredictionDelta() const                  { return PredictionDT; }
  62.114 +    void        SetPrediction(float dt, bool enable = true) { PredictionDT = dt; EnablePrediction = enable; }
  62.115 +    void		SetPredictionEnabled(bool enable = true)    { EnablePrediction = enable; }    
  62.116 +    bool		IsPredictionEnabled()                       { return EnablePrediction; }
  62.117 +
  62.118 +
  62.119 +    // *** Accelerometer/Gravity Correction Control
  62.120 +
  62.121 +    // Enables/disables gravity correction (on by default).
  62.122 +    void        SetGravityEnabled(bool enableGravity)       { EnableGravity = enableGravity; }   
  62.123 +    bool        IsGravityEnabled() const                    { return EnableGravity;}
  62.124 +
  62.125 +    // Gain used to correct gyro with accel. Default value is appropriate for typical use.
  62.126 +    float       GetAccelGain() const                        { return Gain; }
  62.127 +    void        SetAccelGain(float ag)                      { Gain = ag; }
  62.128 +
  62.129 +
  62.130 +
  62.131 +    // *** Magnetometer and Yaw Drift Correction Control
  62.132 +
  62.133 +    // Methods to load and save a mag calibration.  Calibrations can optionally
  62.134 +    // be specified by name to differentiate multiple calibrations under different conditions
  62.135 +    // If LoadMagCalibration succeeds, it will override YawCorrectionEnabled based on
  62.136 +    // saved calibration setting.
  62.137 +    bool        SaveMagCalibration(const char* calibrationName = NULL) const;
  62.138 +    bool        LoadMagCalibration(const char* calibrationName = NULL);
  62.139 +
  62.140 +    // Enables/disables magnetometer based yaw drift correction. Must also have mag calibration
  62.141 +    // data for this correction to work.
  62.142 +	void        SetYawCorrectionEnabled(bool enable)    { EnableYawCorrection = enable; }
  62.143 +    // Determines if yaw correction is enabled.
  62.144 +    bool        IsYawCorrectionEnabled() const          { return EnableYawCorrection;}
  62.145 +
  62.146 +    // Yaw correction is currently working (forcing a corrective yaw rotation)
  62.147 +    bool        IsYawCorrectionInProgress() const       { return YawCorrectionInProgress;}
  62.148 +
  62.149 +    // Store the calibration matrix for the magnetometer
  62.150 +    void        SetMagCalibration(const Matrix4f& m)
  62.151 +    {
  62.152 +        MagCalibrationMatrix = m;
  62.153 +        time(&MagCalibrationTime);   // time stamp the calibration
  62.154 +        MagCalibrated = true;
  62.155 +    }
  62.156 +
  62.157 +    // Retrieves the magnetometer calibration matrix
  62.158 +    Matrix4f    GetMagCalibration() const        { return MagCalibrationMatrix; }
  62.159 +    // Retrieve the time of the calibration
  62.160 +    time_t      GetMagCalibrationTime() const    { return MagCalibrationTime; }
  62.161 +
  62.162 +    // True only if the mag has calibration values stored
  62.163 +    bool        HasMagCalibration() const        { return MagCalibrated;}  
  62.164 +    // Force the mag into the uncalibrated state
  62.165 +    void        ClearMagCalibration()            { MagCalibrated = false; }
  62.166 +
  62.167 +	// These refer to reference points that associate mag readings with orientations
  62.168 +	void        ClearMagReferences()             { MagNumReferences = 0; }
  62.169 +    void        SetMagRefDistance(const float d) { MagRefDistance = d; }
  62.170 +
  62.171 +
  62.172 +    Vector3f    GetCalibratedMagValue(const Vector3f& rawMag) const;
  62.173 +
  62.174 +    float       GetMagRefYaw() const             { return MagRefYaw; }
  62.175 +    float       GetYawErrorAngle() const         { return YawErrorAngle; }
  62.176 +
  62.177 +
  62.178 +
  62.179 +    // *** Message Handler Logic
  62.180 +
  62.181 +    // Notifies SensorFusion object about a new BodyFrame message from a sensor.
  62.182 +    // Should be called by user if not attaching to a sensor.
  62.183 +    void        OnMessage(const MessageBodyFrame& msg)
  62.184 +    {
  62.185 +        OVR_ASSERT(!IsAttachedToSensor());
  62.186 +        handleMessage(msg);
  62.187 +    }
  62.188 +
  62.189 +    void        SetDelegateMessageHandler(MessageHandler* handler)
  62.190 +    { pDelegate = handler; }
  62.191 +
  62.192 +
  62.193 +
  62.194 +private:
  62.195 +
  62.196 +    SensorFusion* getThis()  { return this; }
  62.197 +
  62.198 +    // Helper used to read and return value within a Lock.
  62.199 +    template<class C>
  62.200 +    C lockedGet(const C* p) const
  62.201 +    {
  62.202 +        Lock::Locker lockScope(Handler.GetHandlerLock());
  62.203 +        return *p;
  62.204 +    }
  62.205 +
  62.206 +    // Internal handler for messages; bypasses error checking.
  62.207 +    void        handleMessage(const MessageBodyFrame& msg);
  62.208 +
  62.209 +    // Set the magnetometer's reference orientation for use in yaw correction
  62.210 +    // The supplied mag is an uncalibrated value
  62.211 +    void        setMagReference(const Quatf& q, const Vector3f& rawMag);
  62.212 +    // Default to current HMD orientation
  62.213 +    void        setMagReference()  { setMagReference(Q, RawMag); }
  62.214 +
  62.215 +	class BodyFrameHandler : public MessageHandler
  62.216 +    {
  62.217 +        SensorFusion* pFusion;
  62.218 +    public:
  62.219 +        BodyFrameHandler(SensorFusion* fusion) : pFusion(fusion) { }
  62.220 +        ~BodyFrameHandler();
  62.221 +
  62.222 +        virtual void OnMessage(const Message& msg);
  62.223 +        virtual bool SupportsMessageType(MessageType type) const;
  62.224 +    };   
  62.225 +
  62.226 +    SensorInfo        CachedSensorInfo;
  62.227 +    
  62.228 +    Quatf             Q;
  62.229 +	Quatf			  QUncorrected;
  62.230 +    Vector3f          A;    
  62.231 +    Vector3f          AngV;
  62.232 +    Vector3f          CalMag;
  62.233 +    Vector3f          RawMag;
  62.234 +    unsigned int      Stage;
  62.235 +	float             RunningTime;
  62.236 +	float             DeltaT;
  62.237 +    BodyFrameHandler  Handler;
  62.238 +    MessageHandler*   pDelegate;
  62.239 +    float             Gain;
  62.240 +    float             YawMult;
  62.241 +    volatile bool     EnableGravity;
  62.242 +
  62.243 +    bool              EnablePrediction;
  62.244 +    float             PredictionDT;
  62.245 +	float             PredictionTimeIncrement;
  62.246 +
  62.247 +    SensorFilter      FRawMag;
  62.248 +    SensorFilter      FAccW;
  62.249 +    SensorFilter      FAngV;
  62.250 +
  62.251 +    int               TiltCondCount;
  62.252 +    float             TiltErrorAngle;
  62.253 +    Vector3f          TiltErrorAxis;
  62.254 +
  62.255 +    bool              EnableYawCorrection;
  62.256 +    Matrix4f          MagCalibrationMatrix;
  62.257 +    time_t            MagCalibrationTime;    
  62.258 +    bool              MagCalibrated;
  62.259 +    int               MagCondCount;
  62.260 +    float             MagRefDistance;
  62.261 +    Quatf             MagRefQ;
  62.262 +    Vector3f          MagRefM;
  62.263 +    float             MagRefYaw;
  62.264 +    bool              MagHasNearbyReference;
  62.265 +    Quatf             MagRefTableQ[MagMaxReferences];
  62.266 +    Vector3f          MagRefTableM[MagMaxReferences];
  62.267 +    float             MagRefTableYaw[MagMaxReferences];
  62.268 +    int               MagNumReferences;
  62.269 +    float             YawErrorAngle;
  62.270 +    int               YawErrorCount;
  62.271 +    bool              YawCorrectionInProgress;
  62.272 +	bool			  YawCorrectionActivated;
  62.273 +
  62.274 +    bool              MotionTrackingEnabled;
  62.275 +};
  62.276 +
  62.277 +
  62.278 +} // namespace OVR
  62.279 +
  62.280 +#endif
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/libovr/Src/OVR_SensorImpl.cpp	Sat Sep 14 16:14:59 2013 +0300
    63.3 @@ -0,0 +1,882 @@
    63.4 +/************************************************************************************
    63.5 +
    63.6 +Filename    :   OVR_SensorImpl.cpp
    63.7 +Content     :   Oculus Sensor device implementation.
    63.8 +Created     :   March 7, 2013
    63.9 +Authors     :   Lee Cooper
   63.10 +
   63.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   63.12 +
   63.13 +Use of this software is subject to the terms of the Oculus license
   63.14 +agreement provided at the time of installation or download, or which
   63.15 +otherwise accompanies this software in either electronic or hard copy form.
   63.16 +
   63.17 +*************************************************************************************/
   63.18 +
   63.19 +#include "OVR_SensorImpl.h"
   63.20 +
   63.21 +// HMDDeviceDesc can be created/updated through Sensor carrying DisplayInfo.
   63.22 +
   63.23 +#include "Kernel/OVR_Timer.h"
   63.24 +
   63.25 +namespace OVR {
   63.26 +    
   63.27 +//-------------------------------------------------------------------------------------
   63.28 +// ***** Oculus Sensor-specific packet data structures
   63.29 +
   63.30 +enum {    
   63.31 +    Sensor_VendorId  = Oculus_VendorId,
   63.32 +    Sensor_ProductId = 0x0001,
   63.33 +
   63.34 +    // ST's VID used originally; should be removed in the future
   63.35 +    Sensor_OldVendorId  = 0x0483,
   63.36 +    Sensor_OldProductId = 0x5750,
   63.37 +
   63.38 +    Sensor_DefaultReportRate = 500, // Hz
   63.39 +    Sensor_MaxReportRate     = 1000 // Hz
   63.40 +};
   63.41 +
   63.42 +// Reported data is little-endian now
   63.43 +static UInt16 DecodeUInt16(const UByte* buffer)
   63.44 +{
   63.45 +    return (UInt16(buffer[1]) << 8) | UInt16(buffer[0]);
   63.46 +}
   63.47 +
   63.48 +static SInt16 DecodeSInt16(const UByte* buffer)
   63.49 +{
   63.50 +    return (SInt16(buffer[1]) << 8) | SInt16(buffer[0]);
   63.51 +}
   63.52 +
   63.53 +static UInt32 DecodeUInt32(const UByte* buffer)
   63.54 +{    
   63.55 +    return (buffer[0]) | UInt32(buffer[1] << 8) | UInt32(buffer[2] << 16) | UInt32(buffer[3] << 24);    
   63.56 +}
   63.57 +
   63.58 +static float DecodeFloat(const UByte* buffer)
   63.59 +{
   63.60 +    union {
   63.61 +        UInt32 U;
   63.62 +        float  F;
   63.63 +    };
   63.64 +
   63.65 +    U = DecodeUInt32(buffer);
   63.66 +    return F;
   63.67 +}
   63.68 +
   63.69 +
   63.70 +static void UnpackSensor(const UByte* buffer, SInt32* x, SInt32* y, SInt32* z)
   63.71 +{
   63.72 +    // Sign extending trick
   63.73 +    // from http://graphics.stanford.edu/~seander/bithacks.html#FixedSignExtend
   63.74 +    struct {SInt32 x:21;} s;
   63.75 +
   63.76 +    *x = s.x = (buffer[0] << 13) | (buffer[1] << 5) | ((buffer[2] & 0xF8) >> 3);
   63.77 +    *y = s.x = ((buffer[2] & 0x07) << 18) | (buffer[3] << 10) | (buffer[4] << 2) |
   63.78 +               ((buffer[5] & 0xC0) >> 6);
   63.79 +    *z = s.x = ((buffer[5] & 0x3F) << 15) | (buffer[6] << 7) | (buffer[7] >> 1);
   63.80 +}
   63.81 +
   63.82 +// Messages we care for
   63.83 +enum TrackerMessageType
   63.84 +{
   63.85 +    TrackerMessage_None              = 0,
   63.86 +    TrackerMessage_Sensors           = 1,
   63.87 +    TrackerMessage_Unknown           = 0x100,
   63.88 +    TrackerMessage_SizeError         = 0x101,
   63.89 +};
   63.90 +
   63.91 +struct TrackerSample
   63.92 +{
   63.93 +    SInt32 AccelX, AccelY, AccelZ;
   63.94 +    SInt32 GyroX, GyroY, GyroZ;
   63.95 +};
   63.96 +
   63.97 +
   63.98 +struct TrackerSensors
   63.99 +{
  63.100 +    UByte	SampleCount;
  63.101 +    UInt16	Timestamp;
  63.102 +    UInt16	LastCommandID;
  63.103 +    SInt16	Temperature;
  63.104 +
  63.105 +    TrackerSample Samples[3];
  63.106 +
  63.107 +    SInt16	MagX, MagY, MagZ;
  63.108 +
  63.109 +    TrackerMessageType Decode(const UByte* buffer, int size)
  63.110 +    {
  63.111 +        if (size < 62)
  63.112 +            return TrackerMessage_SizeError;
  63.113 +
  63.114 +        SampleCount		= buffer[1];
  63.115 +        Timestamp		= DecodeUInt16(buffer + 2);
  63.116 +        LastCommandID	= DecodeUInt16(buffer + 4);
  63.117 +        Temperature		= DecodeSInt16(buffer + 6);
  63.118 +        
  63.119 +        //if (SampleCount > 2)        
  63.120 +        //    OVR_DEBUG_LOG_TEXT(("TackerSensor::Decode SampleCount=%d\n", SampleCount));        
  63.121 +
  63.122 +        // Only unpack as many samples as there actually are
  63.123 +        UByte iterationCount = (SampleCount > 2) ? 3 : SampleCount;
  63.124 +
  63.125 +        for (UByte i = 0; i < iterationCount; i++)
  63.126 +        {
  63.127 +            UnpackSensor(buffer + 8 + 16 * i,  &Samples[i].AccelX, &Samples[i].AccelY, &Samples[i].AccelZ);
  63.128 +            UnpackSensor(buffer + 16 + 16 * i, &Samples[i].GyroX,  &Samples[i].GyroY,  &Samples[i].GyroZ);
  63.129 +        }
  63.130 +
  63.131 +        MagX = DecodeSInt16(buffer + 56);
  63.132 +        MagY = DecodeSInt16(buffer + 58);
  63.133 +        MagZ = DecodeSInt16(buffer + 60);
  63.134 +
  63.135 +        return TrackerMessage_Sensors;
  63.136 +    }
  63.137 +};
  63.138 +
  63.139 +struct TrackerMessage
  63.140 +{
  63.141 +    TrackerMessageType Type;
  63.142 +    TrackerSensors     Sensors;
  63.143 +};
  63.144 +
  63.145 +bool DecodeTrackerMessage(TrackerMessage* message, UByte* buffer, int size)
  63.146 +{
  63.147 +    memset(message, 0, sizeof(TrackerMessage));
  63.148 +
  63.149 +    if (size < 4)
  63.150 +    {
  63.151 +        message->Type = TrackerMessage_SizeError;
  63.152 +        return false;
  63.153 +    }
  63.154 +
  63.155 +    switch (buffer[0])
  63.156 +    {
  63.157 +    case TrackerMessage_Sensors:
  63.158 +        message->Type = message->Sensors.Decode(buffer, size);
  63.159 +        break;
  63.160 +
  63.161 +    default:
  63.162 +        message->Type = TrackerMessage_Unknown;
  63.163 +        break;
  63.164 +    }
  63.165 +
  63.166 +    return (message->Type < TrackerMessage_Unknown) && (message->Type != TrackerMessage_None);
  63.167 +}
  63.168 +
  63.169 +
  63.170 +// ***** SensorRangeImpl Implementation
  63.171 +
  63.172 +// Sensor HW only accepts specific maximum range values, used to maximize
  63.173 +// the 16-bit sensor outputs. Use these ramps to specify and report appropriate values.
  63.174 +static const UInt16 AccelRangeRamp[] = { 2, 4, 8, 16 };
  63.175 +static const UInt16 GyroRangeRamp[]  = { 250, 500, 1000, 2000 };
  63.176 +static const UInt16 MagRangeRamp[]   = { 880, 1300, 1900, 2500 };
  63.177 +
  63.178 +static UInt16 SelectSensorRampValue(const UInt16* ramp, unsigned count,
  63.179 +                                    float val, float factor, const char* label)
  63.180 +{    
  63.181 +    UInt16 threshold = (UInt16)(val * factor);
  63.182 +
  63.183 +    for (unsigned i = 0; i<count; i++)
  63.184 +    {
  63.185 +        if (ramp[i] >= threshold)
  63.186 +            return ramp[i];
  63.187 +    }
  63.188 +    OVR_DEBUG_LOG(("SensorDevice::SetRange - %s clamped to %0.4f",
  63.189 +                   label, float(ramp[count-1]) / factor));
  63.190 +    OVR_UNUSED2(factor, label);
  63.191 +    return ramp[count-1];
  63.192 +}
  63.193 +
  63.194 +// SensorScaleImpl provides buffer packing logic for the Sensor Range
  63.195 +// record that can be applied to DK1 sensor through Get/SetFeature. We expose this
  63.196 +// through SensorRange class, which has different units.
  63.197 +struct SensorRangeImpl
  63.198 +{
  63.199 +    enum  { PacketSize = 8 };
  63.200 +    UByte   Buffer[PacketSize];
  63.201 +    
  63.202 +    UInt16  CommandId;
  63.203 +    UInt16  AccelScale;
  63.204 +    UInt16  GyroScale;
  63.205 +    UInt16  MagScale;
  63.206 +
  63.207 +    SensorRangeImpl(const SensorRange& r, UInt16 commandId = 0)
  63.208 +    {
  63.209 +        SetSensorRange(r, commandId);
  63.210 +    }
  63.211 +
  63.212 +    void SetSensorRange(const SensorRange& r, UInt16 commandId = 0)
  63.213 +    {
  63.214 +        CommandId  = commandId;
  63.215 +        AccelScale = SelectSensorRampValue(AccelRangeRamp, sizeof(AccelRangeRamp)/sizeof(AccelRangeRamp[0]),
  63.216 +                                           r.MaxAcceleration, (1.0f / 9.81f), "MaxAcceleration");
  63.217 +        GyroScale  = SelectSensorRampValue(GyroRangeRamp, sizeof(GyroRangeRamp)/sizeof(GyroRangeRamp[0]),
  63.218 +                                           r.MaxRotationRate, Math<float>::RadToDegreeFactor, "MaxRotationRate");
  63.219 +        MagScale   = SelectSensorRampValue(MagRangeRamp, sizeof(MagRangeRamp)/sizeof(MagRangeRamp[0]),
  63.220 +                                           r.MaxMagneticField, 1000.0f, "MaxMagneticField");
  63.221 +        Pack();
  63.222 +    }
  63.223 +
  63.224 +    void GetSensorRange(SensorRange* r)
  63.225 +    {
  63.226 +        r->MaxAcceleration = AccelScale * 9.81f;
  63.227 +        r->MaxRotationRate = DegreeToRad((float)GyroScale);
  63.228 +        r->MaxMagneticField= MagScale * 0.001f;
  63.229 +    }
  63.230 +
  63.231 +    static SensorRange GetMaxSensorRange()
  63.232 +    {
  63.233 +        return SensorRange(AccelRangeRamp[sizeof(AccelRangeRamp)/sizeof(AccelRangeRamp[0]) - 1] * 9.81f,
  63.234 +                           GyroRangeRamp[sizeof(GyroRangeRamp)/sizeof(GyroRangeRamp[0]) - 1] *
  63.235 +                                Math<float>::DegreeToRadFactor,
  63.236 +                           MagRangeRamp[sizeof(MagRangeRamp)/sizeof(MagRangeRamp[0]) - 1] * 0.001f);
  63.237 +    }
  63.238 +
  63.239 +    void  Pack()
  63.240 +    {
  63.241 +        Buffer[0] = 4;
  63.242 +        Buffer[1] = UByte(CommandId & 0xFF);
  63.243 +        Buffer[2] = UByte(CommandId >> 8);
  63.244 +        Buffer[3] = UByte(AccelScale);
  63.245 +        Buffer[4] = UByte(GyroScale & 0xFF);
  63.246 +        Buffer[5] = UByte(GyroScale >> 8);
  63.247 +        Buffer[6] = UByte(MagScale & 0xFF);
  63.248 +        Buffer[7] = UByte(MagScale >> 8);
  63.249 +    }
  63.250 +
  63.251 +    void Unpack()
  63.252 +    {
  63.253 +        CommandId = Buffer[1] | (UInt16(Buffer[2]) << 8);
  63.254 +        AccelScale= Buffer[3];
  63.255 +        GyroScale = Buffer[4] | (UInt16(Buffer[5]) << 8);
  63.256 +        MagScale  = Buffer[6] | (UInt16(Buffer[7]) << 8);
  63.257 +    }
  63.258 +};
  63.259 +
  63.260 +
  63.261 +// Sensor configuration command, ReportId == 2.
  63.262 +
  63.263 +struct SensorConfigImpl
  63.264 +{
  63.265 +    enum  { PacketSize = 7 };
  63.266 +    UByte   Buffer[PacketSize];
  63.267 +
  63.268 +    // Flag values for Flags.
  63.269 +    enum {
  63.270 +        Flag_RawMode            = 0x01,
  63.271 +        Flag_CallibrationTest   = 0x02, // Internal test mode
  63.272 +        Flag_UseCallibration    = 0x04,
  63.273 +        Flag_AutoCallibration   = 0x08,
  63.274 +        Flag_MotionKeepAlive    = 0x10,
  63.275 +        Flag_CommandKeepAlive   = 0x20,
  63.276 +        Flag_SensorCoordinates  = 0x40
  63.277 +    };
  63.278 +
  63.279 +    UInt16  CommandId;
  63.280 +    UByte   Flags;
  63.281 +    UInt16  PacketInterval;
  63.282 +    UInt16  KeepAliveIntervalMs;
  63.283 +
  63.284 +    SensorConfigImpl() : CommandId(0), Flags(0), PacketInterval(0), KeepAliveIntervalMs(0)
  63.285 +    {
  63.286 +        memset(Buffer, 0, PacketSize);
  63.287 +        Buffer[0] = 2;
  63.288 +    }
  63.289 +
  63.290 +    void    SetSensorCoordinates(bool sensorCoordinates)
  63.291 +    { Flags = (Flags & ~Flag_SensorCoordinates) | (sensorCoordinates ? Flag_SensorCoordinates : 0); }
  63.292 +    bool    IsUsingSensorCoordinates() const
  63.293 +    { return (Flags & Flag_SensorCoordinates) != 0; }
  63.294 +
  63.295 +    void Pack()
  63.296 +    {
  63.297 +        Buffer[0] = 2;
  63.298 +        Buffer[1] = UByte(CommandId & 0xFF);
  63.299 +        Buffer[2] = UByte(CommandId >> 8);
  63.300 +        Buffer[3] = Flags;
  63.301 +        Buffer[4] = UByte(PacketInterval);
  63.302 +        Buffer[5] = UByte(KeepAliveIntervalMs & 0xFF);
  63.303 +        Buffer[6] = UByte(KeepAliveIntervalMs >> 8);
  63.304 +    }
  63.305 +
  63.306 +    void Unpack()
  63.307 +    {
  63.308 +        CommandId          = Buffer[1] | (UInt16(Buffer[2]) << 8);
  63.309 +        Flags              = Buffer[3];
  63.310 +        PacketInterval     = Buffer[4];
  63.311 +        KeepAliveIntervalMs= Buffer[5] | (UInt16(Buffer[6]) << 8);
  63.312 +    }
  63.313 +    
  63.314 +};
  63.315 +
  63.316 +
  63.317 +// SensorKeepAlive - feature report that needs to be sent at regular intervals for sensor
  63.318 +// to receive commands.
  63.319 +struct SensorKeepAliveImpl
  63.320 +{
  63.321 +    enum  { PacketSize = 5 };
  63.322 +    UByte   Buffer[PacketSize];
  63.323 +
  63.324 +    UInt16  CommandId;
  63.325 +    UInt16  KeepAliveIntervalMs;
  63.326 +
  63.327 +    SensorKeepAliveImpl(UInt16 interval = 0, UInt16 commandId = 0)
  63.328 +        : CommandId(commandId), KeepAliveIntervalMs(interval)
  63.329 +    {
  63.330 +        Pack();
  63.331 +    }
  63.332 +
  63.333 +    void  Pack()
  63.334 +    {
  63.335 +        Buffer[0] = 8;
  63.336 +        Buffer[1] = UByte(CommandId & 0xFF);
  63.337 +        Buffer[2] = UByte(CommandId >> 8);
  63.338 +        Buffer[3] = UByte(KeepAliveIntervalMs & 0xFF);
  63.339 +        Buffer[4] = UByte(KeepAliveIntervalMs >> 8);
  63.340 +    }
  63.341 +
  63.342 +    void Unpack()
  63.343 +    {
  63.344 +        CommandId          = Buffer[1] | (UInt16(Buffer[2]) << 8);
  63.345 +        KeepAliveIntervalMs= Buffer[3] | (UInt16(Buffer[4]) << 8);
  63.346 +    }
  63.347 +};
  63.348 +
  63.349 +
  63.350 +//-------------------------------------------------------------------------------------
  63.351 +// ***** SensorDisplayInfoImpl
  63.352 +SensorDisplayInfoImpl::SensorDisplayInfoImpl()
  63.353 + :  CommandId(0), DistortionType(Base_None)
  63.354 +{
  63.355 +    memset(Buffer, 0, PacketSize);
  63.356 +    Buffer[0] = 9;
  63.357 +}
  63.358 +
  63.359 +void SensorDisplayInfoImpl::Unpack()
  63.360 +{
  63.361 +    CommandId               = Buffer[1] | (UInt16(Buffer[2]) << 8);
  63.362 +    DistortionType          = Buffer[3];
  63.363 +    HResolution             = DecodeUInt16(Buffer+4);
  63.364 +    VResolution             = DecodeUInt16(Buffer+6);
  63.365 +    HScreenSize             = DecodeUInt32(Buffer+8) *  (1/1000000.f);
  63.366 +    VScreenSize             = DecodeUInt32(Buffer+12) * (1/1000000.f);
  63.367 +    VCenter                 = DecodeUInt32(Buffer+16) * (1/1000000.f);
  63.368 +    LensSeparation          = DecodeUInt32(Buffer+20) * (1/1000000.f);
  63.369 +    EyeToScreenDistance[0]  = DecodeUInt32(Buffer+24) * (1/1000000.f);
  63.370 +    EyeToScreenDistance[1]  = DecodeUInt32(Buffer+28) * (1/1000000.f);
  63.371 +    DistortionK[0]          = DecodeFloat(Buffer+32);
  63.372 +    DistortionK[1]          = DecodeFloat(Buffer+36);
  63.373 +    DistortionK[2]          = DecodeFloat(Buffer+40);
  63.374 +    DistortionK[3]          = DecodeFloat(Buffer+44);
  63.375 +    DistortionK[4]          = DecodeFloat(Buffer+48);
  63.376 +    DistortionK[5]          = DecodeFloat(Buffer+52);
  63.377 +}
  63.378 +
  63.379 +
  63.380 +//-------------------------------------------------------------------------------------
  63.381 +// ***** SensorDeviceFactory
  63.382 +
  63.383 +SensorDeviceFactory SensorDeviceFactory::Instance;
  63.384 +
  63.385 +void SensorDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
  63.386 +{
  63.387 +
  63.388 +    class SensorEnumerator : public HIDEnumerateVisitor
  63.389 +    {
  63.390 +        // Assign not supported; suppress MSVC warning.
  63.391 +        void operator = (const SensorEnumerator&) { }
  63.392 +
  63.393 +        DeviceFactory*     pFactory;
  63.394 +        EnumerateVisitor&  ExternalVisitor;   
  63.395 +    public:
  63.396 +        SensorEnumerator(DeviceFactory* factory, EnumerateVisitor& externalVisitor)
  63.397 +            : pFactory(factory), ExternalVisitor(externalVisitor) { }
  63.398 +
  63.399 +        virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId)
  63.400 +        {
  63.401 +            return pFactory->MatchVendorProduct(vendorId, productId);
  63.402 +        }
  63.403 +
  63.404 +        virtual void Visit(HIDDevice& device, const HIDDeviceDesc& desc)
  63.405 +        {
  63.406 +            SensorDeviceCreateDesc createDesc(pFactory, desc);
  63.407 +            ExternalVisitor.Visit(createDesc);
  63.408 +
  63.409 +            // Check if the sensor returns DisplayInfo. If so, try to use it to override potentially
  63.410 +            // mismatching monitor information (in case wrong EDID is reported by splitter),
  63.411 +            // or to create a new "virtualized" HMD Device.
  63.412 +            
  63.413 +            SensorDisplayInfoImpl displayInfo;
  63.414 +
  63.415 +            if (device.GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize))
  63.416 +            {
  63.417 +                displayInfo.Unpack();
  63.418 +
  63.419 +                // If we got display info, try to match / create HMDDevice as well
  63.420 +                // so that sensor settings give preference.
  63.421 +                if (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt)
  63.422 +                {
  63.423 +                    SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(displayInfo, ExternalVisitor);
  63.424 +                }
  63.425 +            }
  63.426 +        }
  63.427 +    };
  63.428 +
  63.429 +    //double start = Timer::GetProfileSeconds();
  63.430 +
  63.431 +    SensorEnumerator sensorEnumerator(this, visitor);
  63.432 +    GetManagerImpl()->GetHIDDeviceManager()->Enumerate(&sensorEnumerator);
  63.433 +
  63.434 +    //double totalSeconds = Timer::GetProfileSeconds() - start; 
  63.435 +}
  63.436 +
  63.437 +bool SensorDeviceFactory::MatchVendorProduct(UInt16 vendorId, UInt16 productId) const
  63.438 +{
  63.439 +    return ((vendorId == Sensor_VendorId) && (productId == Sensor_ProductId)) ||
  63.440 +        ((vendorId == Sensor_OldVendorId) && (productId == Sensor_OldProductId));
  63.441 +}
  63.442 +
  63.443 +bool SensorDeviceFactory::DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc)
  63.444 +{
  63.445 +    if (MatchVendorProduct(desc.VendorId, desc.ProductId))
  63.446 +    {
  63.447 +        SensorDeviceCreateDesc createDesc(this, desc);
  63.448 +        return pdevMgr->AddDevice_NeedsLock(createDesc).GetPtr() != NULL;
  63.449 +    }
  63.450 +    return false;
  63.451 +}
  63.452 +
  63.453 +//-------------------------------------------------------------------------------------
  63.454 +// ***** SensorDeviceCreateDesc
  63.455 +
  63.456 +DeviceBase* SensorDeviceCreateDesc::NewDeviceInstance()
  63.457 +{
  63.458 +    return new SensorDeviceImpl(this);
  63.459 +}
  63.460 +
  63.461 +bool SensorDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
  63.462 +{
  63.463 +    if ((info->InfoClassType != Device_Sensor) &&
  63.464 +        (info->InfoClassType != Device_None))
  63.465 +        return false;
  63.466 +
  63.467 +    OVR_strcpy(info->ProductName,  DeviceInfo::MaxNameLength, HIDDesc.Product.ToCStr());
  63.468 +    OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, HIDDesc.Manufacturer.ToCStr());
  63.469 +    info->Type    = Device_Sensor;
  63.470 +    info->Version = 0;
  63.471 +
  63.472 +    if (info->InfoClassType == Device_Sensor)
  63.473 +    {
  63.474 +        SensorInfo* sinfo = (SensorInfo*)info;
  63.475 +        sinfo->VendorId  = HIDDesc.VendorId;
  63.476 +        sinfo->ProductId = HIDDesc.ProductId;
  63.477 +        sinfo->MaxRanges = SensorRangeImpl::GetMaxSensorRange();
  63.478 +        OVR_strcpy(sinfo->SerialNumber, sizeof(sinfo->SerialNumber),HIDDesc.SerialNumber.ToCStr());
  63.479 +    }
  63.480 +    return true;
  63.481 +}
  63.482 +
  63.483 +
  63.484 +//-------------------------------------------------------------------------------------
  63.485 +// ***** SensorDevice
  63.486 +
  63.487 +SensorDeviceImpl::SensorDeviceImpl(SensorDeviceCreateDesc* createDesc)
  63.488 +    : OVR::HIDDeviceImpl<OVR::SensorDevice>(createDesc, 0),
  63.489 +      Coordinates(SensorDevice::Coord_Sensor),
  63.490 +      HWCoordinates(SensorDevice::Coord_HMD), // HW reports HMD coordinates by default.
  63.491 +      NextKeepAliveTicks(0),
  63.492 +      MaxValidRange(SensorRangeImpl::GetMaxSensorRange())
  63.493 +{
  63.494 +    SequenceValid  = false;
  63.495 +    LastSampleCount= 0;
  63.496 +    LastTimestamp   = 0;
  63.497 +
  63.498 +    OldCommandId = 0;
  63.499 +}
  63.500 +
  63.501 +SensorDeviceImpl::~SensorDeviceImpl()
  63.502 +{
  63.503 +    // Check that Shutdown() was called.
  63.504 +    OVR_ASSERT(!pCreateDesc->pDevice);    
  63.505 +}
  63.506 +
  63.507 +// Internal creation APIs.
  63.508 +bool SensorDeviceImpl::Initialize(DeviceBase* parent)
  63.509 +{
  63.510 +    if (HIDDeviceImpl<OVR::SensorDevice>::Initialize(parent))
  63.511 +    {
  63.512 +        openDevice();
  63.513 +
  63.514 +        LogText("OVR::SensorDevice initialized.\n");
  63.515 +
  63.516 +        return true;
  63.517 +    }
  63.518 +
  63.519 +    return false;
  63.520 +}
  63.521 +
  63.522 +void SensorDeviceImpl::openDevice()
  63.523 +{
  63.524 +
  63.525 +    // Read the currently configured range from sensor.
  63.526 +    SensorRangeImpl sr(SensorRange(), 0);
  63.527 +
  63.528 +    if (GetInternalDevice()->GetFeatureReport(sr.Buffer, SensorRangeImpl::PacketSize))
  63.529 +    {
  63.530 +        sr.Unpack();
  63.531 +        sr.GetSensorRange(&CurrentRange);
  63.532 +    }
  63.533 +
  63.534 +
  63.535 +    // If the sensor has "DisplayInfo" data, use HMD coordinate frame by default.
  63.536 +    SensorDisplayInfoImpl displayInfo;
  63.537 +    if (GetInternalDevice()->GetFeatureReport(displayInfo.Buffer, SensorDisplayInfoImpl::PacketSize))
  63.538 +    {
  63.539 +        displayInfo.Unpack();
  63.540 +        Coordinates = (displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) ?
  63.541 +                      Coord_HMD : Coord_Sensor;
  63.542 +    }
  63.543 +
  63.544 +    // Read/Apply sensor config.
  63.545 +    setCoordinateFrame(Coordinates);
  63.546 +    setReportRate(Sensor_DefaultReportRate);
  63.547 +
  63.548 +    // Set Keep-alive at 10 seconds.
  63.549 +    SensorKeepAliveImpl skeepAlive(10 * 1000);
  63.550 +    GetInternalDevice()->SetFeatureReport(skeepAlive.Buffer, SensorKeepAliveImpl::PacketSize);
  63.551 +}
  63.552 +
  63.553 +void SensorDeviceImpl::closeDeviceOnError()
  63.554 +{
  63.555 +    LogText("OVR::SensorDevice - Lost connection to '%s'\n", getHIDDesc()->Path.ToCStr());
  63.556 +    NextKeepAliveTicks = 0;
  63.557 +}
  63.558 +
  63.559 +void SensorDeviceImpl::Shutdown()
  63.560 +{   
  63.561 +    HIDDeviceImpl<OVR::SensorDevice>::Shutdown();
  63.562 +
  63.563 +    LogText("OVR::SensorDevice - Closed '%s'\n", getHIDDesc()->Path.ToCStr());
  63.564 +}
  63.565 +
  63.566 +
  63.567 +void SensorDeviceImpl::OnInputReport(UByte* pData, UInt32 length)
  63.568 +{
  63.569 +
  63.570 +    bool processed = false;
  63.571 +    if (!processed)
  63.572 +    {
  63.573 +
  63.574 +        TrackerMessage message;
  63.575 +        if (DecodeTrackerMessage(&message, pData, length))
  63.576 +        {
  63.577 +            processed = true;
  63.578 +            onTrackerMessage(&message);
  63.579 +        }
  63.580 +    }
  63.581 +}
  63.582 +
  63.583 +UInt64 SensorDeviceImpl::OnTicks(UInt64 ticksMks)
  63.584 +{
  63.585 +
  63.586 +    if (ticksMks >= NextKeepAliveTicks)
  63.587 +    {
  63.588 +        // Use 3-seconds keep alive by default.
  63.589 +        UInt64 keepAliveDelta = Timer::MksPerSecond * 3;
  63.590 +
  63.591 +        // Set Keep-alive at 10 seconds.
  63.592 +        SensorKeepAliveImpl skeepAlive(10 * 1000);
  63.593 +        // OnTicks is called from background thread so we don't need to add this to the command queue.
  63.594 +        GetInternalDevice()->SetFeatureReport(skeepAlive.Buffer, SensorKeepAliveImpl::PacketSize);
  63.595 +
  63.596 +		// Emit keep-alive every few seconds.
  63.597 +        NextKeepAliveTicks = ticksMks + keepAliveDelta;
  63.598 +    }
  63.599 +    return NextKeepAliveTicks - ticksMks;
  63.600 +}
  63.601 +
  63.602 +bool SensorDeviceImpl::SetRange(const SensorRange& range, bool waitFlag)
  63.603 +{
  63.604 +    bool                 result = 0;
  63.605 +    ThreadCommandQueue * threadQueue = GetManagerImpl()->GetThreadQueue();
  63.606 +
  63.607 +    if (!waitFlag)
  63.608 +    {
  63.609 +        return threadQueue->PushCall(this, &SensorDeviceImpl::setRange, range);
  63.610 +    }
  63.611 +    
  63.612 +    if (!threadQueue->PushCallAndWaitResult(this, 
  63.613 +                                            &SensorDeviceImpl::setRange,
  63.614 +                                            &result, 
  63.615 +                                            range))
  63.616 +    {
  63.617 +        return false;
  63.618 +    }
  63.619 +
  63.620 +    return result;
  63.621 +}
  63.622 +
  63.623 +void SensorDeviceImpl::GetRange(SensorRange* range) const
  63.624 +{
  63.625 +    Lock::Locker lockScope(GetLock());
  63.626 +    *range = CurrentRange;
  63.627 +}
  63.628 +
  63.629 +bool SensorDeviceImpl::setRange(const SensorRange& range)
  63.630 +{
  63.631 +    SensorRangeImpl sr(range);
  63.632 +    
  63.633 +    if (GetInternalDevice()->SetFeatureReport(sr.Buffer, SensorRangeImpl::PacketSize))
  63.634 +    {
  63.635 +        Lock::Locker lockScope(GetLock());
  63.636 +        sr.GetSensorRange(&CurrentRange);
  63.637 +        return true;
  63.638 +    }
  63.639 +    
  63.640 +    return false;
  63.641 +}
  63.642 +
  63.643 +void SensorDeviceImpl::SetCoordinateFrame(CoordinateFrame coordframe)
  63.644 +{ 
  63.645 +    // Push call with wait.
  63.646 +    GetManagerImpl()->GetThreadQueue()->
  63.647 +        PushCall(this, &SensorDeviceImpl::setCoordinateFrame, coordframe, true);
  63.648 +}
  63.649 +
  63.650 +SensorDevice::CoordinateFrame SensorDeviceImpl::GetCoordinateFrame() const
  63.651 +{
  63.652 +    return Coordinates;
  63.653 +}
  63.654 +
  63.655 +Void SensorDeviceImpl::setCoordinateFrame(CoordinateFrame coordframe)
  63.656 +{
  63.657 +
  63.658 +    Coordinates = coordframe;
  63.659 +
  63.660 +    // Read the original coordinate frame, then try to change it.
  63.661 +    SensorConfigImpl scfg;
  63.662 +    if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize))
  63.663 +    {
  63.664 +        scfg.Unpack();
  63.665 +    }
  63.666 +
  63.667 +    scfg.SetSensorCoordinates(coordframe == Coord_Sensor);
  63.668 +    scfg.Pack();
  63.669 +
  63.670 +    GetInternalDevice()->SetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize);
  63.671 +    
  63.672 +    // Re-read the state, in case of older firmware that doesn't support Sensor coordinates.
  63.673 +    if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize))
  63.674 +    {
  63.675 +        scfg.Unpack();
  63.676 +        HWCoordinates = scfg.IsUsingSensorCoordinates() ? Coord_Sensor : Coord_HMD;
  63.677 +    }
  63.678 +    else
  63.679 +    {
  63.680 +        HWCoordinates = Coord_HMD;
  63.681 +    }
  63.682 +    return 0;
  63.683 +}
  63.684 +
  63.685 +void SensorDeviceImpl::SetReportRate(unsigned rateHz)
  63.686 +{ 
  63.687 +    // Push call with wait.
  63.688 +    GetManagerImpl()->GetThreadQueue()->
  63.689 +        PushCall(this, &SensorDeviceImpl::setReportRate, rateHz, true);
  63.690 +}
  63.691 +
  63.692 +unsigned SensorDeviceImpl::GetReportRate() const
  63.693 +{
  63.694 +    // Read the original configuration
  63.695 +    SensorConfigImpl scfg;
  63.696 +    if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize))
  63.697 +    {
  63.698 +        scfg.Unpack();
  63.699 +        return Sensor_MaxReportRate / (scfg.PacketInterval + 1);
  63.700 +    }
  63.701 +    return 0; // error
  63.702 +}
  63.703 +
  63.704 +Void SensorDeviceImpl::setReportRate(unsigned rateHz)
  63.705 +{
  63.706 +    // Read the original configuration
  63.707 +    SensorConfigImpl scfg;
  63.708 +    if (GetInternalDevice()->GetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize))
  63.709 +    {
  63.710 +        scfg.Unpack();
  63.711 +    }
  63.712 +
  63.713 +    if (rateHz > Sensor_MaxReportRate)
  63.714 +        rateHz = Sensor_MaxReportRate;
  63.715 +    else if (rateHz == 0)
  63.716 +        rateHz = Sensor_DefaultReportRate;
  63.717 +
  63.718 +    scfg.PacketInterval = UInt16((Sensor_MaxReportRate / rateHz) - 1);
  63.719 +
  63.720 +    scfg.Pack();
  63.721 +
  63.722 +    GetInternalDevice()->SetFeatureReport(scfg.Buffer, SensorConfigImpl::PacketSize);
  63.723 +    return 0;
  63.724 +}
  63.725 +
  63.726 +void SensorDeviceImpl::SetMessageHandler(MessageHandler* handler)
  63.727 +{
  63.728 +    if (handler)
  63.729 +    {
  63.730 +        SequenceValid = false;
  63.731 +        DeviceBase::SetMessageHandler(handler);
  63.732 +    }
  63.733 +    else
  63.734 +    {       
  63.735 +        DeviceBase::SetMessageHandler(handler);
  63.736 +    }    
  63.737 +}
  63.738 +
  63.739 +// Sensor reports data in the following coordinate system:
  63.740 +// Accelerometer: 10^-4 m/s^2; X forward, Y right, Z Down.
  63.741 +// Gyro:          10^-4 rad/s; X positive roll right, Y positive pitch up; Z positive yaw right.
  63.742 +
  63.743 +
  63.744 +// We need to convert it to the following RHS coordinate system:
  63.745 +// X right, Y Up, Z Back (out of screen)
  63.746 +//
  63.747 +Vector3f AccelFromBodyFrameUpdate(const TrackerSensors& update, UByte sampleNumber,
  63.748 +                                  bool convertHMDToSensor = false)
  63.749 +{
  63.750 +    const TrackerSample& sample = update.Samples[sampleNumber];
  63.751 +    float                ax = (float)sample.AccelX;
  63.752 +    float                ay = (float)sample.AccelY;
  63.753 +    float                az = (float)sample.AccelZ;
  63.754 +
  63.755 +    Vector3f val = convertHMDToSensor ? Vector3f(ax, az, -ay) :  Vector3f(ax, ay, az);
  63.756 +    return val * 0.0001f;
  63.757 +}
  63.758 +
  63.759 +
  63.760 +Vector3f MagFromBodyFrameUpdate(const TrackerSensors& update,
  63.761 +                                bool convertHMDToSensor = false)
  63.762 +{   
  63.763 +    // Note: Y and Z are swapped in comparison to the Accel.  
  63.764 +    // This accounts for DK1 sensor firmware axis swap, which should be undone in future releases.
  63.765 +    if (!convertHMDToSensor)
  63.766 +    {
  63.767 +        return Vector3f( (float)update.MagX,
  63.768 +                         (float)update.MagZ,
  63.769 +                         (float)update.MagY) * 0.0001f;
  63.770 +    }    
  63.771 +
  63.772 +    return Vector3f( (float)update.MagX,
  63.773 +                     (float)update.MagY,
  63.774 +                    -(float)update.MagZ) * 0.0001f;
  63.775 +}
  63.776 +
  63.777 +Vector3f EulerFromBodyFrameUpdate(const TrackerSensors& update, UByte sampleNumber,
  63.778 +                                  bool convertHMDToSensor = false)
  63.779 +{
  63.780 +    const TrackerSample& sample = update.Samples[sampleNumber];
  63.781 +    float                gx = (float)sample.GyroX;
  63.782 +    float                gy = (float)sample.GyroY;
  63.783 +    float                gz = (float)sample.GyroZ;
  63.784 +
  63.785 +    Vector3f val = convertHMDToSensor ? Vector3f(gx, gz, -gy) :  Vector3f(gx, gy, gz);
  63.786 +    return val * 0.0001f;
  63.787 +}
  63.788 +
  63.789 +
  63.790 +void SensorDeviceImpl::onTrackerMessage(TrackerMessage* message)
  63.791 +{
  63.792 +    if (message->Type != TrackerMessage_Sensors)
  63.793 +        return;
  63.794 +    
  63.795 +    const float     timeUnit   = (1.0f / 1000.f);
  63.796 +    TrackerSensors& s = message->Sensors;
  63.797 +    
  63.798 +
  63.799 +    // Call OnMessage() within a lock to avoid conflicts with handlers.
  63.800 +    Lock::Locker scopeLock(HandlerRef.GetLock());
  63.801 +
  63.802 +
  63.803 +    if (SequenceValid)
  63.804 +    {
  63.805 +        unsigned timestampDelta;
  63.806 +
  63.807 +        if (s.Timestamp < LastTimestamp)
  63.808 +            timestampDelta = ((((int)s.Timestamp) + 0x10000) - (int)LastTimestamp);
  63.809 +        else
  63.810 +            timestampDelta = (s.Timestamp - LastTimestamp);
  63.811 +
  63.812 +        // If we missed a small number of samples, replicate the last sample.
  63.813 +        if ((timestampDelta > LastSampleCount) && (timestampDelta <= 254))
  63.814 +        {
  63.815 +            if (HandlerRef.GetHandler())
  63.816 +            {
  63.817 +                MessageBodyFrame sensors(this);
  63.818 +                sensors.TimeDelta     = (timestampDelta - LastSampleCount) * timeUnit;
  63.819 +                sensors.Acceleration  = LastAcceleration;
  63.820 +                sensors.RotationRate  = LastRotationRate;
  63.821 +                sensors.MagneticField = LastMagneticField;
  63.822 +                sensors.Temperature   = LastTemperature;
  63.823 +
  63.824 +                HandlerRef.GetHandler()->OnMessage(sensors);
  63.825 +            }
  63.826 +        }
  63.827 +    }
  63.828 +    else
  63.829 +    {
  63.830 +        LastAcceleration = Vector3f(0);
  63.831 +        LastRotationRate = Vector3f(0);
  63.832 +        LastMagneticField= Vector3f(0);
  63.833 +        LastTemperature  = 0;
  63.834 +        SequenceValid    = true;
  63.835 +    }
  63.836 +
  63.837 +    LastSampleCount = s.SampleCount;
  63.838 +    LastTimestamp   = s.Timestamp;
  63.839 +
  63.840 +    bool convertHMDToSensor = (Coordinates == Coord_Sensor) && (HWCoordinates == Coord_HMD);
  63.841 +
  63.842 +    if (HandlerRef.GetHandler())
  63.843 +    {
  63.844 +        MessageBodyFrame sensors(this);                
  63.845 +        UByte            iterations = s.SampleCount;
  63.846 +
  63.847 +        if (s.SampleCount > 3)
  63.848 +        {
  63.849 +            iterations        = 3;
  63.850 +            sensors.TimeDelta = (s.SampleCount - 2) * timeUnit;
  63.851 +        }
  63.852 +        else
  63.853 +        {
  63.854 +            sensors.TimeDelta = timeUnit;
  63.855 +        }
  63.856 +
  63.857 +        for (UByte i = 0; i < iterations; i++)
  63.858 +        {            
  63.859 +            sensors.Acceleration = AccelFromBodyFrameUpdate(s, i, convertHMDToSensor);
  63.860 +            sensors.RotationRate = EulerFromBodyFrameUpdate(s, i, convertHMDToSensor);
  63.861 +            sensors.MagneticField= MagFromBodyFrameUpdate(s, convertHMDToSensor);
  63.862 +            sensors.Temperature  = s.Temperature * 0.01f;
  63.863 +            HandlerRef.GetHandler()->OnMessage(sensors);
  63.864 +            // TimeDelta for the last two sample is always fixed.
  63.865 +            sensors.TimeDelta = timeUnit;
  63.866 +        }
  63.867 +
  63.868 +        LastAcceleration = sensors.Acceleration;
  63.869 +        LastRotationRate = sensors.RotationRate;
  63.870 +        LastMagneticField= sensors.MagneticField;
  63.871 +        LastTemperature  = sensors.Temperature;
  63.872 +    }
  63.873 +    else
  63.874 +    {
  63.875 +        UByte i = (s.SampleCount > 3) ? 2 : (s.SampleCount - 1);
  63.876 +        LastAcceleration  = AccelFromBodyFrameUpdate(s, i, convertHMDToSensor);
  63.877 +        LastRotationRate  = EulerFromBodyFrameUpdate(s, i, convertHMDToSensor);
  63.878 +        LastMagneticField = MagFromBodyFrameUpdate(s, convertHMDToSensor);
  63.879 +        LastTemperature   = s.Temperature * 0.01f;
  63.880 +    }
  63.881 +}
  63.882 +
  63.883 +} // namespace OVR
  63.884 +
  63.885 +
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/libovr/Src/OVR_SensorImpl.h	Sat Sep 14 16:14:59 2013 +0300
    64.3 @@ -0,0 +1,208 @@
    64.4 +/************************************************************************************
    64.5 +
    64.6 +Filename    :   OVR_SensorImpl.h
    64.7 +Content     :   Sensor device specific implementation.
    64.8 +Created     :   March 7, 2013
    64.9 +Authors     :   Lee Cooper
   64.10 +
   64.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   64.12 +
   64.13 +Use of this software is subject to the terms of the Oculus license
   64.14 +agreement provided at the time of installation or download, or which
   64.15 +otherwise accompanies this software in either electronic or hard copy form.
   64.16 +
   64.17 +*************************************************************************************/
   64.18 +
   64.19 +#ifndef OVR_SensorImpl_h
   64.20 +#define OVR_SensorImpl_h
   64.21 +
   64.22 +#include "OVR_HIDDeviceImpl.h"
   64.23 +
   64.24 +namespace OVR {
   64.25 +    
   64.26 +struct TrackerMessage;
   64.27 +class ExternalVisitor;
   64.28 +
   64.29 +//-------------------------------------------------------------------------------------
   64.30 +// SensorDeviceFactory enumerates Oculus Sensor devices.
   64.31 +class SensorDeviceFactory : public DeviceFactory
   64.32 +{
   64.33 +public:
   64.34 +    static SensorDeviceFactory Instance;
   64.35 +
   64.36 +    // Enumerates devices, creating and destroying relevant objects in manager.
   64.37 +    virtual void EnumerateDevices(EnumerateVisitor& visitor);
   64.38 +
   64.39 +    virtual bool MatchVendorProduct(UInt16 vendorId, UInt16 productId) const;
   64.40 +    virtual bool DetectHIDDevice(DeviceManager* pdevMgr, const HIDDeviceDesc& desc);
   64.41 +protected:
   64.42 +    DeviceManager* getManager() const { return (DeviceManager*) pManager; }   
   64.43 +};
   64.44 +
   64.45 +
   64.46 +// Describes a single a Oculus Sensor device and supports creating its instance.
   64.47 +class SensorDeviceCreateDesc : public HIDDeviceCreateDesc
   64.48 +{
   64.49 +public:
   64.50 +    SensorDeviceCreateDesc(DeviceFactory* factory, const HIDDeviceDesc& hidDesc)
   64.51 +        : HIDDeviceCreateDesc(factory, Device_Sensor, hidDesc) { }
   64.52 +    
   64.53 +    virtual DeviceCreateDesc* Clone() const
   64.54 +    {
   64.55 +        return new SensorDeviceCreateDesc(*this);
   64.56 +    }
   64.57 +
   64.58 +    virtual DeviceBase* NewDeviceInstance();
   64.59 +
   64.60 +    virtual MatchResult MatchDevice(const DeviceCreateDesc& other,
   64.61 +                                    DeviceCreateDesc**) const
   64.62 +    {
   64.63 +        if ((other.Type == Device_Sensor) && (pFactory == other.pFactory))
   64.64 +        {
   64.65 +            const SensorDeviceCreateDesc& s2 = (const SensorDeviceCreateDesc&) other;
   64.66 +            if (MatchHIDDevice(s2.HIDDesc))
   64.67 +                return Match_Found;
   64.68 +        }
   64.69 +        return Match_None;
   64.70 +    }
   64.71 +
   64.72 +    virtual bool MatchHIDDevice(const HIDDeviceDesc& hidDesc) const
   64.73 +    {
   64.74 +        // should paths comparison be case insensitive?
   64.75 +        return ((HIDDesc.Path.CompareNoCase(hidDesc.Path) == 0) &&
   64.76 +                (HIDDesc.SerialNumber == hidDesc.SerialNumber));
   64.77 +    }
   64.78 +
   64.79 +    virtual bool        GetDeviceInfo(DeviceInfo* info) const;
   64.80 +};
   64.81 +
   64.82 +
   64.83 +//-------------------------------------------------------------------------------------
   64.84 +// ***** OVR::SensorDisplayInfoImpl
   64.85 +
   64.86 +// DisplayInfo obtained from sensor; these values are used to report distortion
   64.87 +// settings and other coefficients.
   64.88 +// Older SensorDisplayInfo will have all zeros, causing the library to apply hard-coded defaults.
   64.89 +// Currently, only resolutions and sizes are used.
   64.90 +struct SensorDisplayInfoImpl
   64.91 +{
   64.92 +    enum  { PacketSize = 56 };
   64.93 +    UByte   Buffer[PacketSize];
   64.94 +
   64.95 +    enum
   64.96 +    {
   64.97 +        Mask_BaseFmt    = 0x0f,
   64.98 +        Mask_OptionFmts = 0xf0,
   64.99 +        Base_None       = 0,
  64.100 +        Base_ScreenOnly = 1,
  64.101 +        Base_Distortion = 2,
  64.102 +    };
  64.103 +
  64.104 +    UInt16  CommandId;
  64.105 +    UByte   DistortionType;    
  64.106 +    UInt16  HResolution, VResolution;
  64.107 +    float   HScreenSize, VScreenSize;
  64.108 +    float   VCenter;
  64.109 +    float   LensSeparation;
  64.110 +    float   EyeToScreenDistance[2];
  64.111 +    float   DistortionK[6];
  64.112 +
  64.113 +    SensorDisplayInfoImpl();
  64.114 +
  64.115 +    void Unpack();
  64.116 +};
  64.117 +
  64.118 +
  64.119 +//-------------------------------------------------------------------------------------
  64.120 +// ***** OVR::SensorDeviceImpl
  64.121 +
  64.122 +// Oculus Sensor interface.
  64.123 +
  64.124 +class SensorDeviceImpl : public HIDDeviceImpl<OVR::SensorDevice>
  64.125 +{
  64.126 +public:
  64.127 +     SensorDeviceImpl(SensorDeviceCreateDesc* createDesc);
  64.128 +    ~SensorDeviceImpl();
  64.129 +
  64.130 +
  64.131 +    // DeviceCommaon interface
  64.132 +    virtual bool Initialize(DeviceBase* parent);
  64.133 +    virtual void Shutdown();
  64.134 +    
  64.135 +    virtual void SetMessageHandler(MessageHandler* handler);
  64.136 +
  64.137 +    // HIDDevice::Notifier interface.
  64.138 +    virtual void OnInputReport(UByte* pData, UInt32 length);
  64.139 +    virtual UInt64 OnTicks(UInt64 ticksMks);
  64.140 +
  64.141 +    // HMD-Mounted sensor has a different coordinate frame.
  64.142 +    virtual void SetCoordinateFrame(CoordinateFrame coordframe);    
  64.143 +    virtual CoordinateFrame GetCoordinateFrame() const;    
  64.144 +
  64.145 +    // SensorDevice interface
  64.146 +    virtual bool SetRange(const SensorRange& range, bool waitFlag);
  64.147 +    virtual void GetRange(SensorRange* range) const;
  64.148 +
  64.149 +    // Sets report rate (in Hz) of MessageBodyFrame messages (delivered through MessageHandler::OnMessage call). 
  64.150 +    // Currently supported maximum rate is 1000Hz. If the rate is set to 500 or 333 Hz then OnMessage will be 
  64.151 +    // called twice or thrice at the same 'tick'. 
  64.152 +    // If the rate is  < 333 then the OnMessage / MessageBodyFrame will be called three
  64.153 +    // times for each 'tick': the first call will contain averaged values, the second
  64.154 +    // and third calls will provide with most recent two recorded samples.
  64.155 +    virtual void        SetReportRate(unsigned rateHz);
  64.156 +    // Returns currently set report rate, in Hz. If 0 - error occurred.
  64.157 +    // Note, this value may be different from the one provided for SetReportRate. The return
  64.158 +    // value will contain the actual rate.
  64.159 +    virtual unsigned    GetReportRate() const;
  64.160 +
  64.161 +    // Hack to create HMD device from sensor display info.
  64.162 +    static void EnumerateHMDFromSensorDisplayInfo(const SensorDisplayInfoImpl& displayInfo, 
  64.163 +                                                  DeviceFactory::EnumerateVisitor& visitor);
  64.164 +protected:
  64.165 +
  64.166 +    void openDevice();
  64.167 +    void closeDeviceOnError();
  64.168 +
  64.169 +    Void    setCoordinateFrame(CoordinateFrame coordframe);
  64.170 +    bool    setRange(const SensorRange& range);
  64.171 +
  64.172 +    Void    setReportRate(unsigned rateHz);
  64.173 +
  64.174 +    // Called for decoded messages
  64.175 +    void        onTrackerMessage(TrackerMessage* message);
  64.176 +
  64.177 +    // Helpers to reduce casting.
  64.178 +/*
  64.179 +    SensorDeviceCreateDesc* getCreateDesc() const
  64.180 +    { return (SensorDeviceCreateDesc*)pCreateDesc.GetPtr(); }
  64.181 +
  64.182 +    HIDDeviceDesc* getHIDDesc() const
  64.183 +    { return &getCreateDesc()->HIDDesc; }    
  64.184 +*/
  64.185 +
  64.186 +    // Set if the sensor is located on the HMD.
  64.187 +    // Older prototype firmware doesn't support changing HW coordinates,
  64.188 +    // so we track its state.
  64.189 +    CoordinateFrame Coordinates;
  64.190 +    CoordinateFrame HWCoordinates;
  64.191 +    UInt64      NextKeepAliveTicks;
  64.192 +
  64.193 +    bool        SequenceValid;
  64.194 +    SInt16      LastTimestamp;
  64.195 +    UByte       LastSampleCount;
  64.196 +    float       LastTemperature;
  64.197 +    Vector3f    LastAcceleration;
  64.198 +    Vector3f    LastRotationRate;
  64.199 +    Vector3f    LastMagneticField;
  64.200 +
  64.201 +    // Current sensor range obtained from device. 
  64.202 +    SensorRange MaxValidRange;
  64.203 +    SensorRange CurrentRange;
  64.204 +    
  64.205 +    UInt16      OldCommandId;
  64.206 +};
  64.207 +
  64.208 +
  64.209 +} // namespace OVR
  64.210 +
  64.211 +#endif // OVR_SensorImpl_h
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/libovr/Src/OVR_ThreadCommandQueue.cpp	Sat Sep 14 16:14:59 2013 +0300
    65.3 @@ -0,0 +1,370 @@
    65.4 +/************************************************************************************
    65.5 +
    65.6 +PublicHeader:   None
    65.7 +Filename    :   OVR_ThreadCommandQueue.cpp
    65.8 +Content     :   Command queue for operations executed on a thread
    65.9 +Created     :   October 29, 2012
   65.10 +
   65.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   65.12 +
   65.13 +Use of this software is subject to the terms of the Oculus license
   65.14 +agreement provided at the time of installation or download, or which
   65.15 +otherwise accompanies this software in either electronic or hard copy form.
   65.16 +
   65.17 +************************************************************************************/
   65.18 +
   65.19 +#include "OVR_ThreadCommandQueue.h"
   65.20 +
   65.21 +namespace OVR {
   65.22 +
   65.23 +
   65.24 +//------------------------------------------------------------------------
   65.25 +// ***** CircularBuffer
   65.26 +
   65.27 +// CircularBuffer is a FIFO buffer implemented in a single block of memory,
   65.28 +// which allows writing and reading variable-size data chucks. Write fails
   65.29 +// if buffer is full.
   65.30 +
   65.31 +class CircularBuffer
   65.32 +{
   65.33 +    enum {
   65.34 +        AlignSize = 16,
   65.35 +        AlignMask = AlignSize - 1
   65.36 +    };
   65.37 +
   65.38 +    UByte*  pBuffer;
   65.39 +    UPInt   Size;
   65.40 +    UPInt   Tail;   // Byte offset of next item to be popped.
   65.41 +    UPInt   Head;   // Byte offset of where next push will take place.
   65.42 +    UPInt   End;    // When Head < Tail, this is used instead of Size.    
   65.43 +
   65.44 +    inline UPInt roundUpSize(UPInt size)
   65.45 +    { return (size + AlignMask) & ~(UPInt)AlignMask; }
   65.46 +
   65.47 +public:
   65.48 +
   65.49 +    CircularBuffer(UPInt size)
   65.50 +        : Size(size), Tail(0), Head(0), End(0)
   65.51 +    {
   65.52 +        pBuffer = (UByte*)OVR_ALLOC_ALIGNED(roundUpSize(size), AlignSize);
   65.53 +    }
   65.54 +    ~CircularBuffer()
   65.55 +    {
   65.56 +        // For ThreadCommands, we must consume everything before shutdown.
   65.57 +        OVR_ASSERT(IsEmpty());
   65.58 +        OVR_FREE_ALIGNED(pBuffer);
   65.59 +    }
   65.60 +
   65.61 +    bool    IsEmpty() const { return (Head == Tail); }
   65.62 +
   65.63 +    // Allocates a state block of specified size and advances pointers,
   65.64 +    // returning 0 if buffer is full.
   65.65 +    UByte*  Write(UPInt size);
   65.66 +
   65.67 +    // Returns a pointer to next available data block; 0 if none available.
   65.68 +    UByte*  ReadBegin()
   65.69 +    { return (Head != Tail) ? (pBuffer + Tail) : 0; }
   65.70 +    // Consumes data of specified size; this must match size passed to Write.
   65.71 +    void    ReadEnd(UPInt size);
   65.72 +};
   65.73 +
   65.74 +
   65.75 +// Allocates a state block of specified size and advances pointers,
   65.76 +// returning 0 if buffer is full.
   65.77 +UByte* CircularBuffer::Write(UPInt size)
   65.78 +{
   65.79 +    UByte* p = 0;
   65.80 +
   65.81 +    size = roundUpSize(size);
   65.82 +    // Since this is circular buffer, always allow at least one item.
   65.83 +    OVR_ASSERT(size < Size/2);
   65.84 +
   65.85 +    if (Head >= Tail)
   65.86 +    {
   65.87 +        OVR_ASSERT(End == 0);
   65.88 +        
   65.89 +        if (size <= (Size - Head))
   65.90 +        {
   65.91 +            p    = pBuffer + Head;
   65.92 +            Head += size;
   65.93 +        }
   65.94 +        else if (size < Tail)
   65.95 +        {
   65.96 +            p    = pBuffer;
   65.97 +            End  = Head;
   65.98 +            Head = size;
   65.99 +            OVR_ASSERT(Head != Tail);
  65.100 +        }
  65.101 +    }
  65.102 +    else
  65.103 +    {
  65.104 +        OVR_ASSERT(End != 0);
  65.105 +
  65.106 +        if ((Tail - Head) > size)
  65.107 +        {
  65.108 +            p    = pBuffer + Head;
  65.109 +            Head += size;
  65.110 +            OVR_ASSERT(Head != Tail);
  65.111 +        }
  65.112 +    }
  65.113 +
  65.114 +    return p;
  65.115 +}
  65.116 +
  65.117 +void CircularBuffer::ReadEnd(UPInt size)
  65.118 +{
  65.119 +    OVR_ASSERT(Head != Tail);
  65.120 +    size = roundUpSize(size);
  65.121 +    
  65.122 +    Tail += size;        
  65.123 +    if (Tail == End)
  65.124 +    {
  65.125 +        Tail = End = 0;
  65.126 +    }
  65.127 +    else if (Tail == Head)
  65.128 +    {        
  65.129 +        OVR_ASSERT(End == 0);
  65.130 +        Tail = Head = 0;
  65.131 +    }
  65.132 +}
  65.133 +
  65.134 +
  65.135 +//-------------------------------------------------------------------------------------
  65.136 +// ***** ThreadCommand
  65.137 +
  65.138 +ThreadCommand::PopBuffer::~PopBuffer()
  65.139 +{
  65.140 +    if (Size)
  65.141 +        Destruct<ThreadCommand>(toCommand());
  65.142 +}
  65.143 +
  65.144 +void ThreadCommand::PopBuffer::InitFromBuffer(void* data)
  65.145 +{
  65.146 +    ThreadCommand* cmd = (ThreadCommand*)data;
  65.147 +    OVR_ASSERT(cmd->Size <= MaxSize);
  65.148 +
  65.149 +    if (Size)
  65.150 +        Destruct<ThreadCommand>(toCommand());    
  65.151 +    Size = cmd->Size;    
  65.152 +    memcpy(Buffer, (void*)cmd, Size);
  65.153 +}
  65.154 +
  65.155 +void ThreadCommand::PopBuffer::Execute()
  65.156 +{
  65.157 +    ThreadCommand* command = toCommand();
  65.158 +    OVR_ASSERT(command);
  65.159 +    command->Execute();
  65.160 +    if (NeedsWait())
  65.161 +        GetEvent()->PulseEvent();
  65.162 +}
  65.163 +
  65.164 +//-------------------------------------------------------------------------------------
  65.165 +
  65.166 +class ThreadCommandQueueImpl : public NewOverrideBase
  65.167 +{
  65.168 +    typedef ThreadCommand::NotifyEvent NotifyEvent;
  65.169 +    friend class ThreadCommandQueue;
  65.170 +    
  65.171 +public:
  65.172 +
  65.173 +    ThreadCommandQueueImpl(ThreadCommandQueue* queue)
  65.174 +        : pQueue(queue), CommandBuffer(2048),
  65.175 +          ExitEnqueued(false), ExitProcessed(false)
  65.176 +    {
  65.177 +    }
  65.178 +    ~ThreadCommandQueueImpl();
  65.179 +
  65.180 +
  65.181 +    bool PushCommand(const ThreadCommand& command);
  65.182 +    bool PopCommand(ThreadCommand::PopBuffer* popBuffer);
  65.183 +
  65.184 +
  65.185 +    // ExitCommand is used by notify us that Thread is shutting down.
  65.186 +    struct ExitCommand : public ThreadCommand
  65.187 +    {
  65.188 +        ThreadCommandQueueImpl* pImpl;
  65.189 +        
  65.190 +        ExitCommand(ThreadCommandQueueImpl* impl, bool wait)
  65.191 +            : ThreadCommand(sizeof(ExitCommand), wait, true), pImpl(impl) { }
  65.192 +
  65.193 +        virtual void Execute() const
  65.194 +        {
  65.195 +            Lock::Locker lock(&pImpl->QueueLock);
  65.196 +            pImpl->ExitProcessed = true;
  65.197 +        }
  65.198 +        virtual ThreadCommand* CopyConstruct(void* p) const 
  65.199 +        { return Construct<ExitCommand>(p, *this); }
  65.200 +    };
  65.201 +
  65.202 +
  65.203 +    NotifyEvent* AllocNotifyEvent_NTS()
  65.204 +    {
  65.205 +        NotifyEvent* p = AvailableEvents.GetFirst();
  65.206 +
  65.207 +        if (!AvailableEvents.IsNull(p))
  65.208 +            p->RemoveNode();        
  65.209 +        else
  65.210 +            p = new NotifyEvent;
  65.211 +        return p;
  65.212 +    }
  65.213 +
  65.214 +    void         FreeNotifyEvent_NTS(NotifyEvent* p)
  65.215 +    {
  65.216 +        AvailableEvents.PushBack(p);
  65.217 +    }
  65.218 +
  65.219 +    void        FreeNotifyEvents_NTS()
  65.220 +    {
  65.221 +        while(!AvailableEvents.IsEmpty())
  65.222 +        {
  65.223 +            NotifyEvent* p = AvailableEvents.GetFirst();
  65.224 +            p->RemoveNode();
  65.225 +            delete p;
  65.226 +        }
  65.227 +    }
  65.228 +
  65.229 +    ThreadCommandQueue* pQueue;
  65.230 +    Lock                QueueLock;
  65.231 +    volatile bool       ExitEnqueued;
  65.232 +    volatile bool       ExitProcessed;
  65.233 +    List<NotifyEvent>   AvailableEvents;
  65.234 +    List<NotifyEvent>   BlockedProducers;
  65.235 +    CircularBuffer      CommandBuffer;
  65.236 +};
  65.237 +
  65.238 +
  65.239 +
  65.240 +ThreadCommandQueueImpl::~ThreadCommandQueueImpl()
  65.241 +{
  65.242 +    Lock::Locker lock(&QueueLock);
  65.243 +    OVR_ASSERT(BlockedProducers.IsEmpty());
  65.244 +    FreeNotifyEvents_NTS();
  65.245 +}
  65.246 +
  65.247 +bool ThreadCommandQueueImpl::PushCommand(const ThreadCommand& command)
  65.248 +{
  65.249 +    ThreadCommand::NotifyEvent* completeEvent = 0;
  65.250 +    ThreadCommand::NotifyEvent* queueAvailableEvent = 0;
  65.251 +
  65.252 +    // Repeat  writing command into buffer until it is available.    
  65.253 +    do {
  65.254 +
  65.255 +        { // Lock Scope
  65.256 +            Lock::Locker lock(&QueueLock);
  65.257 +
  65.258 +            if (queueAvailableEvent)
  65.259 +            {
  65.260 +                FreeNotifyEvent_NTS(queueAvailableEvent);
  65.261 +                queueAvailableEvent = 0;
  65.262 +            }
  65.263 +
  65.264 +            // Don't allow any commands after PushExitCommand() is called.
  65.265 +            if (ExitEnqueued && !command.ExitFlag)
  65.266 +                return false;
  65.267 +
  65.268 +
  65.269 +            bool   bufferWasEmpty = CommandBuffer.IsEmpty();
  65.270 +            UByte* buffer = CommandBuffer.Write(command.GetSize());
  65.271 +            if  (buffer)
  65.272 +            {
  65.273 +                ThreadCommand* c = command.CopyConstruct(buffer);
  65.274 +                if (c->NeedsWait())
  65.275 +                    completeEvent = c->pEvent = AllocNotifyEvent_NTS();
  65.276 +                // Signal-waker consumer when we add data to buffer.
  65.277 +                if (bufferWasEmpty)
  65.278 +                    pQueue->OnPushNonEmpty_Locked();
  65.279 +                break;
  65.280 +            }
  65.281 +
  65.282 +            queueAvailableEvent = AllocNotifyEvent_NTS();
  65.283 +            BlockedProducers.PushBack(queueAvailableEvent);
  65.284 +        } // Lock Scope
  65.285 +
  65.286 +        queueAvailableEvent->Wait();
  65.287 +
  65.288 +    } while(1);
  65.289 +
  65.290 +    // Command was enqueued, wait if necessary.
  65.291 +    if (completeEvent)
  65.292 +    {
  65.293 +        completeEvent->Wait();
  65.294 +        Lock::Locker lock(&QueueLock);
  65.295 +        FreeNotifyEvent_NTS(completeEvent);
  65.296 +    }
  65.297 +
  65.298 +    return true;
  65.299 +}
  65.300 +
  65.301 +
  65.302 +// Pops the next command from the thread queue, if any is available.
  65.303 +bool ThreadCommandQueueImpl::PopCommand(ThreadCommand::PopBuffer* popBuffer)
  65.304 +{    
  65.305 +    Lock::Locker lock(&QueueLock);
  65.306 +
  65.307 +    UByte* buffer = CommandBuffer.ReadBegin();
  65.308 +    if (!buffer)
  65.309 +    {
  65.310 +        // Notify thread while in lock scope, enabling initialization of wait.
  65.311 +        pQueue->OnPopEmpty_Locked();
  65.312 +        return false;
  65.313 +    }
  65.314 +
  65.315 +    popBuffer->InitFromBuffer(buffer);
  65.316 +    CommandBuffer.ReadEnd(popBuffer->GetSize());
  65.317 +
  65.318 +    if (!BlockedProducers.IsEmpty())
  65.319 +    {
  65.320 +        ThreadCommand::NotifyEvent* queueAvailableEvent = BlockedProducers.GetFirst();
  65.321 +        queueAvailableEvent->RemoveNode();
  65.322 +        queueAvailableEvent->PulseEvent();
  65.323 +        // Event is freed later by waiter.
  65.324 +    }    
  65.325 +    return true;
  65.326 +}
  65.327 +
  65.328 +
  65.329 +//-------------------------------------------------------------------------------------
  65.330 +
  65.331 +ThreadCommandQueue::ThreadCommandQueue()
  65.332 +{
  65.333 +    pImpl = new ThreadCommandQueueImpl(this);
  65.334 +}
  65.335 +ThreadCommandQueue::~ThreadCommandQueue()
  65.336 +{
  65.337 +    delete pImpl;
  65.338 +}
  65.339 +
  65.340 +bool ThreadCommandQueue::PushCommand(const ThreadCommand& command)
  65.341 +{
  65.342 +    return pImpl->PushCommand(command);
  65.343 +}
  65.344 +
  65.345 +bool ThreadCommandQueue::PopCommand(ThreadCommand::PopBuffer* popBuffer)
  65.346 +{    
  65.347 +    return pImpl->PopCommand(popBuffer);
  65.348 +}
  65.349 +
  65.350 +void ThreadCommandQueue::PushExitCommand(bool wait)
  65.351 +{
  65.352 +    // Exit is processed in two stages:
  65.353 +    //  - First, ExitEnqueued flag is set to block further commands from queuing up.
  65.354 +    //  - Second, the actual exit call is processed on the consumer thread, flushing
  65.355 +    //    any prior commands.
  65.356 +    //    IsExiting() only returns true after exit has flushed.
  65.357 +    {
  65.358 +        Lock::Locker lock(&pImpl->QueueLock);
  65.359 +        if (pImpl->ExitEnqueued)
  65.360 +            return;
  65.361 +        pImpl->ExitEnqueued = true;
  65.362 +    }
  65.363 +
  65.364 +    PushCommand(ThreadCommandQueueImpl::ExitCommand(pImpl, wait));
  65.365 +}
  65.366 +
  65.367 +bool ThreadCommandQueue::IsExiting() const
  65.368 +{
  65.369 +    return pImpl->ExitProcessed;
  65.370 +}
  65.371 +
  65.372 +
  65.373 +} // namespace OVR
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/libovr/Src/OVR_ThreadCommandQueue.h	Sat Sep 14 16:14:59 2013 +0300
    66.3 @@ -0,0 +1,308 @@
    66.4 +/************************************************************************************
    66.5 +
    66.6 +PublicHeader:   None
    66.7 +Filename    :   OVR_ThreadCommandQueue.h
    66.8 +Content     :   Command queue for operations executed on a thread
    66.9 +Created     :   October 29, 2012
   66.10 +Author      :   Michael Antonov
   66.11 +
   66.12 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   66.13 +
   66.14 +Use of this software is subject to the terms of the Oculus license
   66.15 +agreement provided at the time of installation or download, or which
   66.16 +otherwise accompanies this software in either electronic or hard copy form.
   66.17 +
   66.18 +************************************************************************************/
   66.19 +
   66.20 +#ifndef OVR_ThreadCommandQueue_h
   66.21 +#define OVR_ThreadCommandQueue_h
   66.22 +
   66.23 +#include "Kernel/OVR_Types.h"
   66.24 +#include "Kernel/OVR_List.h"
   66.25 +#include "Kernel/OVR_Atomic.h"
   66.26 +#include "Kernel/OVR_Threads.h"
   66.27 +
   66.28 +namespace OVR {
   66.29 +
   66.30 +class ThreadCommand;
   66.31 +class ThreadCommandQueue;
   66.32 +
   66.33 +
   66.34 +//-------------------------------------------------------------------------------------
   66.35 +// ***** ThreadCommand
   66.36 +
   66.37 +// ThreadCommand is a base class implementation for commands stored in ThreadCommandQueue.
   66.38 +class ThreadCommand
   66.39 +{
   66.40 +public:    
   66.41 +
   66.42 +    // NotifyEvent is used by ThreadCommandQueue::PushCallAndWait to notify the
   66.43 +    // calling (producer)  thread when command is completed or queue slot is available.
   66.44 +    class NotifyEvent : public ListNode<NotifyEvent>, public NewOverrideBase
   66.45 +    {
   66.46 +        Event E;
   66.47 +    public:   
   66.48 +        NotifyEvent() { }
   66.49 +
   66.50 +        void Wait()        { E.Wait(); }
   66.51 +        void PulseEvent()  { E.PulseEvent(); }
   66.52 +    };
   66.53 +
   66.54 +    // ThreadCommand::PopBuffer is temporary storage for a command popped off
   66.55 +    // by ThreadCommandQueue::PopCommand. 
   66.56 +    class PopBuffer
   66.57 +    {
   66.58 +        enum { MaxSize = 256 };
   66.59 +
   66.60 +        UPInt Size;
   66.61 +        union {            
   66.62 +            UByte Buffer[MaxSize];
   66.63 +            UPInt Align;
   66.64 +        };
   66.65 +
   66.66 +        ThreadCommand* toCommand() const { return (ThreadCommand*)Buffer; }
   66.67 +
   66.68 +    public:
   66.69 +        PopBuffer() : Size(0) { }
   66.70 +        ~PopBuffer();
   66.71 +
   66.72 +        void        InitFromBuffer(void* data);
   66.73 +
   66.74 +        bool        HasCommand() const  { return Size != 0; }
   66.75 +        UPInt       GetSize() const     { return Size; }
   66.76 +        bool        NeedsWait() const   { return toCommand()->NeedsWait(); }
   66.77 +        NotifyEvent* GetEvent() const   { return toCommand()->pEvent; }
   66.78 +
   66.79 +        // Execute the command and also notifies caller to finish waiting,
   66.80 +        // if necessary.
   66.81 +        void        Execute();
   66.82 +    };
   66.83 +    
   66.84 +    UInt16       Size;
   66.85 +    bool         WaitFlag; 
   66.86 +    bool         ExitFlag; // Marks the last exit command. 
   66.87 +    NotifyEvent* pEvent;
   66.88 +
   66.89 +    ThreadCommand(UPInt size, bool waitFlag, bool exitFlag = false)
   66.90 +        : Size((UInt16)size), WaitFlag(waitFlag), ExitFlag(exitFlag), pEvent(0) { }
   66.91 +    virtual ~ThreadCommand() { }
   66.92 +
   66.93 +    bool          NeedsWait() const { return WaitFlag; }
   66.94 +    UPInt         GetSize() const   { return Size; }
   66.95 +
   66.96 +    virtual void            Execute() const = 0;
   66.97 +    // Copy constructor used for serializing this to memory buffer.
   66.98 +    virtual ThreadCommand*  CopyConstruct(void* p) const = 0;
   66.99 +};
  66.100 +
  66.101 +
  66.102 +//-------------------------------------------------------------------------------------
  66.103 +
  66.104 +// CleanType is a template that strips 'const' and '&' modifiers from the argument type;
  66.105 +// for example, typename CleanType<A&>::Type is equivalent to A.
  66.106 +template<class T> struct CleanType           { typedef T Type; };
  66.107 +template<class T> struct CleanType<T&>       { typedef T Type; };
  66.108 +template<class T> struct CleanType<const T>  { typedef T Type; };
  66.109 +template<class T> struct CleanType<const T&> { typedef T Type; };
  66.110 +
  66.111 +// SelfType is a template that yields the argument type. This helps avoid conflicts with
  66.112 +// automatic template argument deduction for function calls when identical argument
  66.113 +// is already defined.
  66.114 +template<class T> struct SelfType { typedef T Type; };
  66.115 +
  66.116 +
  66.117 +
  66.118 +//-------------------------------------------------------------------------------------
  66.119 +// ThreadCommand specializations for member functions with different number of
  66.120 +// arguments and argument types.
  66.121 +
  66.122 +// Used to return nothing from a ThreadCommand, to avoid problems with 'void'.
  66.123 +struct Void
  66.124 +{
  66.125 +    Void() {}
  66.126 +    Void(int) {}
  66.127 +};
  66.128 +
  66.129 +// ThreadCommand for member function with 0 arguments.
  66.130 +template<class C, class R>
  66.131 +class ThreadCommandMF0 : public ThreadCommand
  66.132 +{   
  66.133 +    typedef R (C::*FnPtr)();
  66.134 +    C*      pClass;
  66.135 +    FnPtr   pFn;
  66.136 +    R*      pRet;
  66.137 +
  66.138 +    void executeImpl() const
  66.139 +    {
  66.140 +        pRet ? (void)(*pRet = (pClass->*pFn)()) :
  66.141 +	           (void)(pClass->*pFn)();
  66.142 +    }
  66.143 +
  66.144 +public:    
  66.145 +    ThreadCommandMF0(C* pclass, FnPtr fn, R* ret, bool needsWait)
  66.146 +        : ThreadCommand(sizeof(ThreadCommandMF0), needsWait),
  66.147 +          pClass(pclass), pFn(fn), pRet(ret) { }
  66.148 +
  66.149 +    virtual void           Execute() const { executeImpl(); }
  66.150 +    virtual ThreadCommand* CopyConstruct(void* p) const
  66.151 +    { return Construct<ThreadCommandMF0>(p, *this); }
  66.152 +};
  66.153 +
  66.154 +
  66.155 +// ThreadCommand for member function with 1 argument.
  66.156 +template<class C, class R, class A0>
  66.157 +class ThreadCommandMF1 : public ThreadCommand
  66.158 +{   
  66.159 +    typedef R (C::*FnPtr)(A0);
  66.160 +    C*                           pClass;
  66.161 +    FnPtr                        pFn;
  66.162 +    R*                           pRet;
  66.163 +    typename CleanType<A0>::Type AVal0;
  66.164 +
  66.165 +    void executeImpl() const
  66.166 +    {
  66.167 +      pRet ? (void)(*pRet = (pClass->*pFn)(AVal0)) :
  66.168 +	         (void)(pClass->*pFn)(AVal0);
  66.169 +    }
  66.170 +
  66.171 +public:    
  66.172 +    ThreadCommandMF1(C* pclass, FnPtr fn, R* ret, A0 a0, bool needsWait)
  66.173 +        : ThreadCommand(sizeof(ThreadCommandMF1), needsWait),
  66.174 +          pClass(pclass), pFn(fn), pRet(ret), AVal0(a0) { }
  66.175 +
  66.176 +    virtual void           Execute() const { executeImpl(); }
  66.177 +    virtual ThreadCommand* CopyConstruct(void* p) const
  66.178 +    { return Construct<ThreadCommandMF1>(p, *this); }
  66.179 +};
  66.180 +
  66.181 +// ThreadCommand for member function with 2 arguments.
  66.182 +template<class C, class R, class A0, class A1>
  66.183 +class ThreadCommandMF2 : public ThreadCommand
  66.184 +{   
  66.185 +    typedef R (C::*FnPtr)(A0, A1);
  66.186 +    C*                            pClass;
  66.187 +    FnPtr                         pFn;
  66.188 +    R*                            pRet;
  66.189 +    typename CleanType<A0>::Type  AVal0;
  66.190 +    typename CleanType<A1>::Type  AVal1;
  66.191 +
  66.192 +    void executeImpl() const
  66.193 +    {
  66.194 +        pRet ? (void)(*pRet = (pClass->*pFn)(AVal0, AVal1)) :
  66.195 +	           (void)(pClass->*pFn)(AVal0, AVal1);
  66.196 +    }
  66.197 +
  66.198 +public:    
  66.199 +    ThreadCommandMF2(C* pclass, FnPtr fn, R* ret, A0 a0, A1 a1, bool needsWait)
  66.200 +        : ThreadCommand(sizeof(ThreadCommandMF2), needsWait),
  66.201 +          pClass(pclass), pFn(fn), pRet(ret), AVal0(a0), AVal1(a1) { }
  66.202 +    
  66.203 +    virtual void           Execute() const { executeImpl(); }
  66.204 +    virtual ThreadCommand* CopyConstruct(void* p) const 
  66.205 +    { return Construct<ThreadCommandMF2>(p, *this); }
  66.206 +};
  66.207 +
  66.208 +
  66.209 +//-------------------------------------------------------------------------------------
  66.210 +// ***** ThreadCommandQueue
  66.211 +
  66.212 +// ThreadCommandQueue is a queue of executable function-call commands intended to be
  66.213 +// serviced by a single consumer thread. Commands are added to the queue with PushCall
  66.214 +// and removed with PopCall; they are processed in FIFO order. Multiple producer threads
  66.215 +// are supported and will be blocked if internal data buffer is full.
  66.216 +
  66.217 +class ThreadCommandQueue
  66.218 +{
  66.219 +public:
  66.220 +
  66.221 +    ThreadCommandQueue();
  66.222 +    virtual ~ThreadCommandQueue();
  66.223 +
  66.224 +
  66.225 +    // Pops the next command from the thread queue, if any is available.
  66.226 +    // The command should be executed by calling popBuffer->Execute().
  66.227 +    // Returns 'false' if no command is available at the time of the call.
  66.228 +    bool PopCommand(ThreadCommand::PopBuffer* popBuffer);
  66.229 +
  66.230 +    // Generic implementaion of PushCommand; enqueues a command for execution.
  66.231 +    // Returns 'false' if push failed, usually indicating thread shutdown.
  66.232 +    bool PushCommand(const ThreadCommand& command);
  66.233 +
  66.234 +    // 
  66.235 +    void PushExitCommand(bool wait);
  66.236 +
  66.237 +    // Returns 'true' once ExitCommand has been processed, so the thread can shut down.
  66.238 +    bool IsExiting() const;
  66.239 +
  66.240 +
  66.241 +    // These two virtual functions serve as notifications for derived
  66.242 +    // thread waiting.    
  66.243 +    virtual void OnPushNonEmpty_Locked() { }
  66.244 +    virtual void OnPopEmpty_Locked()     { }
  66.245 +
  66.246 +
  66.247 +    // *** PushCall with no result
  66.248 +    
  66.249 +    // Enqueue a member function of 'this' class to be called on consumer thread.
  66.250 +    // By default the function returns immediately; set 'wait' argument to 'true' to
  66.251 +    // wait for completion.
  66.252 +    template<class C, class R>
  66.253 +    bool PushCall(R (C::*fn)(), bool wait = false)
  66.254 +    { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, 0, wait)); }       
  66.255 +    template<class C, class R, class A0>
  66.256 +    bool PushCall(R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
  66.257 +    { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, 0, a0, wait)); }
  66.258 +    template<class C, class R, class A0, class A1>
  66.259 +    bool PushCall(R (C::*fn)(A0, A1),
  66.260 +                  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
  66.261 +    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, 0, a0, a1, wait)); }
  66.262 +    // Enqueue a specified member function call of class C.
  66.263 +    // By default the function returns immediately; set 'wait' argument to 'true' to
  66.264 +    // wait for completion.
  66.265 +    template<class C, class R>
  66.266 +    bool PushCall(C* p, R (C::*fn)(), bool wait = false)
  66.267 +    { return PushCommand(ThreadCommandMF0<C,R>(p, fn, 0, wait)); }
  66.268 +    template<class C, class R, class A0>
  66.269 +    bool PushCall(C* p, R (C::*fn)(A0), typename SelfType<A0>::Type a0, bool wait = false)
  66.270 +    { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, 0, a0, wait)); }
  66.271 +    template<class C, class R, class A0, class A1>
  66.272 +    bool PushCall(C* p, R (C::*fn)(A0, A1),
  66.273 +                  typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1, bool wait = false)
  66.274 +    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, 0, a0, a1, wait)); }
  66.275 +    
  66.276 +    
  66.277 +    // *** PushCall with Result
  66.278 +
  66.279 +    // Enqueue a member function of 'this' class call and wait for call to complete
  66.280 +    // on consumer thread before returning.
  66.281 +    template<class C, class R>
  66.282 +    bool PushCallAndWaitResult(R (C::*fn)(), R* ret)
  66.283 +    { return PushCommand(ThreadCommandMF0<C,R>(static_cast<C*>(this), fn, ret, true)); }       
  66.284 +    template<class C, class R, class A0>
  66.285 +    bool PushCallAndWaitResult(R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
  66.286 +    { return PushCommand(ThreadCommandMF1<C,R,A0>(static_cast<C*>(this), fn, ret, a0, true)); }
  66.287 +    template<class C, class R, class A0, class A1>
  66.288 +    bool PushCallAndWaitResult(R (C::*fn)(A0, A1), R* ret,
  66.289 +                               typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
  66.290 +    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(static_cast<C*>(this), fn, ret, a0, a1, true)); }
  66.291 +    // Enqueue a member function call for class C and wait for the call to complete
  66.292 +    // on consumer thread before returning.
  66.293 +    template<class C, class R>
  66.294 +    bool PushCallAndWaitResult(C* p, R (C::*fn)(), R* ret)
  66.295 +    { return PushCommand(ThreadCommandMF0<C,R>(p, fn, ret, true)); }
  66.296 +    template<class C, class R, class A0>
  66.297 +    bool PushCallAndWaitResult(C* p, R (C::*fn)(A0), R* ret, typename SelfType<A0>::Type a0)
  66.298 +    { return PushCommand(ThreadCommandMF1<C,R,A0>(p, fn, ret, a0, true)); }
  66.299 +    template<class C, class R, class A0, class A1>
  66.300 +    bool PushCallAndWaitResult(C* p, R (C::*fn)(A0, A1), R* ret,
  66.301 +                               typename SelfType<A0>::Type a0, typename SelfType<A1>::Type a1)
  66.302 +    { return PushCommand(ThreadCommandMF2<C,R,A0,A1>(p, fn, ret, a0, a1, true)); }
  66.303 +
  66.304 +private:
  66.305 +    class ThreadCommandQueueImpl* pImpl;
  66.306 +};
  66.307 +
  66.308 +
  66.309 +}
  66.310 +
  66.311 +#endif // OVR_ThreadCommandQueue_h
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/libovr/Src/Util/Util_LatencyTest.cpp	Sat Sep 14 16:14:59 2013 +0300
    67.3 @@ -0,0 +1,1 @@
    67.4 +/************************************************************************************
    67.5 
    67.6 Filename    :   Util_LatencyTest.cpp
    67.7 Content     :   Wraps the lower level LatencyTester interface and adds functionality.
    67.8 Created     :   February 14, 2013
    67.9 Authors     :   Lee Cooper
   67.10 
   67.11 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   67.12 
   67.13 Use of this software is subject to the terms of the Oculus license
   67.14 agreement provided at the time of installation or download, or which
   67.15 otherwise accompanies this software in either electronic or hard copy form.
   67.16 
   67.17 *************************************************************************************/
   67.18 
   67.19 #include "Util_LatencyTest.h"
   67.20 
   67.21 #include "../Kernel/OVR_Log.h"
   67.22 #include "../Kernel/OVR_Timer.h"
   67.23 
   67.24 namespace OVR { namespace Util {
   67.25 
   67.26 static const UInt32     TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION = 16*10;
   67.27 static const UInt32     TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION = 16*10;
   67.28 static const UInt32     TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT = 16*5;
   67.29 static const UInt32     TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS = 16*5;
   67.30 static const UInt32     DEFAULT_NUMBER_OF_SAMPLES = 10;                 // For both color 1->2 and color 2->1 transitions.
   67.31 static const UInt32     INITIAL_SAMPLES_TO_IGNORE = 4;
   67.32 static const UInt32     TIMEOUT_WAITING_FOR_TEST_STARTED = 1000;
   67.33 static const UInt32     TIMEOUT_WAITING_FOR_COLOR_DETECTED = 4000;
   67.34 static const Color      CALIBRATE_BLACK(0, 0, 0);
   67.35 static const Color      CALIBRATE_WHITE(255, 255, 255);
   67.36 static const Color      COLOR1(0, 0, 0);
   67.37 static const Color      COLOR2(255, 255, 255);
   67.38 static const Color      SENSOR_DETECT_THRESHOLD(128, 255, 255);
   67.39 static const float      BIG_FLOAT = 1000000.0f;
   67.40 static const float      SMALL_FLOAT = -1000000.0f;
   67.41 
   67.42 //-------------------------------------------------------------------------------------
   67.43 // ***** LatencyTest
   67.44 
   67.45 LatencyTest::LatencyTest(LatencyTestDevice* device)
   67.46  :  Handler(getThis())
   67.47 {
   67.48     if (device != NULL)
   67.49     {
   67.50         SetDevice(device);
   67.51     }
   67.52 
   67.53     reset();
   67.54 
   67.55     srand(Timer::GetTicksMs());
   67.56 }
   67.57 
   67.58 LatencyTest::~LatencyTest()
   67.59 {
   67.60      clearMeasurementResults();
   67.61 }
   67.62 
   67.63 bool LatencyTest::SetDevice(LatencyTestDevice* device)
   67.64 {
   67.65 
   67.66     if (device != Device)
   67.67     {
   67.68         if (device != NULL)
   67.69         {
   67.70             if (device->GetMessageHandler() != NULL)
   67.71             {
   67.72                 OVR_DEBUG_LOG(
   67.73                     ("LatencyTest::AttachToDevice failed - device %p already has handler", device));
   67.74                 return false;
   67.75             }
   67.76         }
   67.77 
   67.78         if (Device != NULL)
   67.79         {
   67.80             Device->SetMessageHandler(0);
   67.81         }
   67.82         Device = device;
   67.83 
   67.84         if (Device != NULL)
   67.85         {
   67.86             Device->SetMessageHandler(&Handler);
   67.87 
   67.88             // Set trigger threshold.
   67.89             LatencyTestConfiguration configuration(SENSOR_DETECT_THRESHOLD, false);     // No samples streaming.
   67.90             Device->SetConfiguration(configuration, true);
   67.91 
   67.92             // Set display to intial (3 dashes).
   67.93             LatencyTestDisplay ltd(2, 0x40400040);
   67.94             Device->SetDisplay(ltd);
   67.95         }
   67.96     }
   67.97 
   67.98     return true;
   67.99 }
  67.100 
  67.101 UInt32 LatencyTest::getRandomComponent(UInt32 range)
  67.102 {
  67.103     UInt32 val = rand() % range;
  67.104     return val;
  67.105 }
  67.106 
  67.107 void LatencyTest::BeginTest()
  67.108 {
  67.109      if (State == State_WaitingForButton)
  67.110     {
  67.111         // Set color to black and wait a while.
  67.112         RenderColor = CALIBRATE_BLACK;
  67.113 
  67.114         State = State_WaitingForSettlePreCalibrationColorBlack;
  67.115         OVR_DEBUG_LOG(("State_WaitingForButton -> State_WaitingForSettlePreCalibrationColorBlack."));
  67.116 
  67.117         setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION);
  67.118     }
  67.119 }
  67.120 
  67.121 void LatencyTest::handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage)
  67.122 {
  67.123     // For debugging.
  67.124 /*  if (msg.Type == Message_LatencyTestSamples)
  67.125     {
  67.126         MessageLatencyTestSamples* pSamples = (MessageLatencyTestSamples*) &msg;
  67.127 
  67.128         if (pSamples->Samples.GetSize() > 0)
  67.129         {
  67.130             // Just show the first one for now.
  67.131             Color c = pSamples->Samples[0];
  67.132             OVR_DEBUG_LOG(("%d %d %d", c.R, c.G, c.B));
  67.133         }
  67.134         return;
  67.135     }
  67.136 */
  67.137 
  67.138     if (latencyTestMessage == LatencyTest_Timer)
  67.139     {
  67.140         if (!Device)
  67.141         {
  67.142             reset();
  67.143             return;
  67.144         }
  67.145         
  67.146         if (State == State_WaitingForSettlePreCalibrationColorBlack)
  67.147         {
  67.148             // Send calibrate message to device and wait a while.
  67.149             Device->SetCalibrate(CALIBRATE_BLACK);
  67.150 
  67.151             State = State_WaitingForSettlePostCalibrationColorBlack;
  67.152             OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorBlack -> State_WaitingForSettlePostCalibrationColorBlack."));
  67.153 
  67.154             setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION);
  67.155         }
  67.156         else if (State == State_WaitingForSettlePostCalibrationColorBlack)
  67.157         {
  67.158             // Change color to white and wait a while.
  67.159             RenderColor = CALIBRATE_WHITE;
  67.160 
  67.161             State = State_WaitingForSettlePreCalibrationColorWhite;
  67.162             OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorBlack -> State_WaitingForSettlePreCalibrationColorWhite."));
  67.163 
  67.164             setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION);
  67.165         }
  67.166         else if (State == State_WaitingForSettlePreCalibrationColorWhite)
  67.167         {
  67.168             // Send calibrate message to device and wait a while.
  67.169             Device->SetCalibrate(CALIBRATE_WHITE);
  67.170 
  67.171             State = State_WaitingForSettlePostCalibrationColorWhite;
  67.172             OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorWhite -> State_WaitingForSettlePostCalibrationColorWhite."));
  67.173 
  67.174             setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION);
  67.175         }
  67.176         else if (State == State_WaitingForSettlePostCalibrationColorWhite)
  67.177         {
  67.178             // Calibration is done. Switch to color 1 and wait for it to settle.
  67.179             RenderColor = COLOR1;
  67.180 
  67.181             State = State_WaitingForSettlePostMeasurement;
  67.182             OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorWhite -> State_WaitingForSettlePostMeasurement."));
  67.183 
  67.184             UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS);
  67.185             setTimer(waitTime);
  67.186         }
  67.187         else if (State == State_WaitingForSettlePostMeasurement)
  67.188         {
  67.189             // Prepare for next measurement.
  67.190 
  67.191             // Create a new result object.
  67.192             MeasurementResult* pResult = new MeasurementResult();
  67.193             Results.PushBack(pResult);
  67.194 
  67.195             State = State_WaitingToTakeMeasurement;
  67.196             OVR_DEBUG_LOG(("State_WaitingForSettlePostMeasurement -> State_WaitingToTakeMeasurement."));
  67.197         }
  67.198         else if (State == State_WaitingForTestStarted)
  67.199         {
  67.200             // We timed out waiting for 'TestStarted'. Abandon this measurement and setup for the next.
  67.201             getActiveResult()->TimedOutWaitingForTestStarted = true;
  67.202 
  67.203             State = State_WaitingForSettlePostMeasurement;
  67.204             OVR_DEBUG_LOG(("** Timed out waiting for 'TestStarted'."));
  67.205             OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForSettlePostMeasurement."));
  67.206 
  67.207             UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS);
  67.208             setTimer(waitTime);
  67.209         }
  67.210         else if (State == State_WaitingForColorDetected)
  67.211         {
  67.212             // We timed out waiting for 'ColorDetected'. Abandon this measurement and setup for the next.
  67.213             getActiveResult()->TimedOutWaitingForColorDetected = true;
  67.214 
  67.215             State = State_WaitingForSettlePostMeasurement;
  67.216             OVR_DEBUG_LOG(("** Timed out waiting for 'ColorDetected'."));
  67.217             OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement."));
  67.218 
  67.219             UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS);
  67.220             setTimer(waitTime);
  67.221         }
  67.222     }
  67.223     else if (latencyTestMessage == LatencyTest_ProcessInputs)
  67.224     {
  67.225         if (State == State_WaitingToTakeMeasurement)
  67.226         {
  67.227             if (!Device)
  67.228             {
  67.229                 reset();
  67.230                 return;
  67.231             }
  67.232             
  67.233             // Send 'StartTest' feature report with opposite target color.
  67.234             if (RenderColor == COLOR1)
  67.235             {
  67.236                 RenderColor = COLOR2;
  67.237             }
  67.238             else
  67.239             {
  67.240                 RenderColor = COLOR1;
  67.241             }
  67.242 
  67.243             getActiveResult()->TargetColor = RenderColor;
  67.244             
  67.245             // Record time so we can determine usb roundtrip time.
  67.246             getActiveResult()->StartTestTicksMicroS = Timer::GetTicks();
  67.247 
  67.248             Device->SetStartTest(RenderColor);
  67.249 
  67.250             State = State_WaitingForTestStarted;
  67.251             OVR_DEBUG_LOG(("State_WaitingToTakeMeasurement -> State_WaitingForTestStarted."));
  67.252 
  67.253             setTimer(TIMEOUT_WAITING_FOR_TEST_STARTED);
  67.254 
  67.255             LatencyTestDisplay ltd(2, 0x40090040);
  67.256             Device->SetDisplay(ltd);
  67.257         }
  67.258     }
  67.259     else if (msg.Type == Message_LatencyTestButton)
  67.260     {
  67.261         BeginTest();
  67.262     }
  67.263     else if (msg.Type == Message_LatencyTestStarted)
  67.264     {
  67.265         if (State == State_WaitingForTestStarted)
  67.266         {
  67.267             clearTimer();
  67.268 
  67.269             // Record time so we can determine usb roundtrip time.
  67.270             getActiveResult()->TestStartedTicksMicroS = Timer::GetTicks();
  67.271             
  67.272             State = State_WaitingForColorDetected;
  67.273             OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForColorDetected."));
  67.274 
  67.275             setTimer(TIMEOUT_WAITING_FOR_COLOR_DETECTED);
  67.276         }
  67.277     }
  67.278     else if (msg.Type == Message_LatencyTestColorDetected)
  67.279     {
  67.280         if (State == State_WaitingForColorDetected)
  67.281         {
  67.282             // Record time to detect color.
  67.283             MessageLatencyTestColorDetected* pDetected = (MessageLatencyTestColorDetected*) &msg;
  67.284             UInt16 elapsedTime = pDetected->Elapsed;
  67.285             OVR_DEBUG_LOG(("Time to 'ColorDetected' = %d", elapsedTime));
  67.286             
  67.287             getActiveResult()->DeviceMeasuredElapsedMilliS = elapsedTime;
  67.288 
  67.289             if (areResultsComplete())
  67.290             {
  67.291                 // We're done.
  67.292                 processResults();
  67.293                 reset();
  67.294             }
  67.295             else
  67.296             {
  67.297                 // Run another measurement.
  67.298                 State = State_WaitingForSettlePostMeasurement;
  67.299                 OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement."));
  67.300 
  67.301                 UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS);
  67.302                 setTimer(waitTime);
  67.303 
  67.304                 LatencyTestDisplay ltd(2, 0x40400040);
  67.305                 Device->SetDisplay(ltd);
  67.306             }
  67.307         }
  67.308     }
  67.309     else if (msg.Type == Message_DeviceRemoved)
  67.310     {
  67.311         reset();
  67.312     }
  67.313 }
  67.314 
  67.315 LatencyTest::MeasurementResult* LatencyTest::getActiveResult()
  67.316 {
  67.317     OVR_ASSERT(!Results.IsEmpty());    
  67.318     return Results.GetLast();
  67.319 }
  67.320 
  67.321 void LatencyTest::setTimer(UInt32 timeMilliS)
  67.322 {
  67.323     ActiveTimerMilliS = timeMilliS;
  67.324 }
  67.325 
  67.326 void LatencyTest::clearTimer()
  67.327 {
  67.328     ActiveTimerMilliS = 0;
  67.329 }
  67.330 
  67.331 void LatencyTest::reset()
  67.332 {
  67.333     clearMeasurementResults();
  67.334     State = State_WaitingForButton;
  67.335 
  67.336     HaveOldTime = false;
  67.337     ActiveTimerMilliS = 0;
  67.338 }
  67.339 
  67.340 void LatencyTest::clearMeasurementResults()
  67.341 {
  67.342     while(!Results.IsEmpty())
  67.343     {
  67.344         MeasurementResult* pElem = Results.GetFirst();
  67.345         pElem->RemoveNode();
  67.346         delete pElem;
  67.347     }
  67.348 }
  67.349 
  67.350 LatencyTest::LatencyTestHandler::~LatencyTestHandler()
  67.351 {
  67.352     RemoveHandlerFromDevices();
  67.353 }
  67.354 
  67.355 void LatencyTest::LatencyTestHandler::OnMessage(const Message& msg)
  67.356 {
  67.357     pLatencyTestUtil->handleMessage(msg);
  67.358 }
  67.359 
  67.360 void LatencyTest::ProcessInputs()
  67.361 {
  67.362     updateForTimeouts();
  67.363     handleMessage(Message(), LatencyTest_ProcessInputs);
  67.364 }
  67.365 
  67.366 bool LatencyTest::DisplayScreenColor(Color& colorToDisplay)
  67.367 {
  67.368     updateForTimeouts();
  67.369 
  67.370     if (State == State_WaitingForButton)
  67.371     {
  67.372         return false;
  67.373     }
  67.374 
  67.375     colorToDisplay = RenderColor;
  67.376     return true;
  67.377 }
  67.378 
  67.379 const char*	LatencyTest::GetResultsString()
  67.380 {
  67.381 	if (!ResultsString.IsEmpty() && ReturnedResultString != ResultsString.ToCStr())
  67.382 	{
  67.383 		ReturnedResultString = ResultsString;
  67.384 		return ReturnedResultString.ToCStr();
  67.385 	}
  67.386     
  67.387 	return NULL;
  67.388 }
  67.389 
  67.390 bool LatencyTest::areResultsComplete()
  67.391 {
  67.392     UInt32 initialMeasurements = 0;
  67.393 
  67.394     UInt32 measurements1to2 = 0;
  67.395     UInt32 measurements2to1 = 0;
  67.396 
  67.397     MeasurementResult* pCurr = Results.GetFirst();
  67.398     while(true)
  67.399     {
  67.400         // Process.
  67.401         if (!pCurr->TimedOutWaitingForTestStarted &&
  67.402             !pCurr->TimedOutWaitingForColorDetected)
  67.403         {
  67.404             initialMeasurements++;
  67.405 
  67.406             if (initialMeasurements > INITIAL_SAMPLES_TO_IGNORE)
  67.407             {
  67.408                 if (pCurr->TargetColor == COLOR2)
  67.409                 {
  67.410                     measurements1to2++;
  67.411                 }
  67.412                 else
  67.413                 {
  67.414                     measurements2to1++;
  67.415                 }
  67.416             }
  67.417         }
  67.418 
  67.419         if (Results.IsLast(pCurr))
  67.420         {
  67.421             break;
  67.422         }
  67.423         pCurr = Results.GetNext(pCurr);
  67.424     }
  67.425 
  67.426     if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES &&
  67.427         measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES)
  67.428     {
  67.429         return true;
  67.430     }
  67.431 
  67.432     return false;
  67.433 }
  67.434 
  67.435 void LatencyTest::processResults()
  67.436 {
  67.437 
  67.438     UInt32 minTime1To2 = UINT_MAX;
  67.439     UInt32 maxTime1To2 = 0;
  67.440     float averageTime1To2 = 0.0f;
  67.441     UInt32 minTime2To1 = UINT_MAX;
  67.442     UInt32 maxTime2To1 = 0;
  67.443     float averageTime2To1 = 0.0f;
  67.444 
  67.445     float minUSBTripMilliS = BIG_FLOAT;
  67.446     float maxUSBTripMilliS = SMALL_FLOAT;
  67.447     float averageUSBTripMilliS = 0.0f;
  67.448     UInt32 countUSBTripTime = 0;
  67.449 
  67.450     UInt32 measurementsCount = 0;
  67.451     UInt32 measurements1to2 = 0;
  67.452     UInt32 measurements2to1 = 0;
  67.453 
  67.454     MeasurementResult* pCurr = Results.GetFirst();
  67.455     UInt32 count = 0;
  67.456     while(true)
  67.457     {
  67.458         count++;
  67.459 
  67.460         if (!pCurr->TimedOutWaitingForTestStarted &&
  67.461             !pCurr->TimedOutWaitingForColorDetected)
  67.462         {
  67.463             measurementsCount++;
  67.464 
  67.465             if (measurementsCount > INITIAL_SAMPLES_TO_IGNORE)
  67.466             {
  67.467                 if (pCurr->TargetColor == COLOR2)
  67.468                 {
  67.469                     measurements1to2++;
  67.470 
  67.471                     if (measurements1to2 <= DEFAULT_NUMBER_OF_SAMPLES)
  67.472                     {
  67.473                         UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS;
  67.474 
  67.475                         minTime1To2 = Alg::Min(elapsed, minTime1To2);
  67.476                         maxTime1To2 = Alg::Max(elapsed, maxTime1To2);
  67.477 
  67.478                         averageTime1To2 += (float) elapsed;
  67.479                     }
  67.480                 }
  67.481                 else
  67.482                 {
  67.483                     measurements2to1++;
  67.484 
  67.485                     if (measurements2to1 <= DEFAULT_NUMBER_OF_SAMPLES)
  67.486                     {
  67.487                         UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS;
  67.488 
  67.489                         minTime2To1 = Alg::Min(elapsed, minTime2To1);
  67.490                         maxTime2To1 = Alg::Max(elapsed, maxTime2To1);
  67.491 
  67.492                         averageTime2To1 += (float) elapsed;
  67.493                     }
  67.494                 }
  67.495 
  67.496                 float usbRountripElapsedMilliS = 0.001f * (float) (pCurr->TestStartedTicksMicroS - pCurr->StartTestTicksMicroS);
  67.497                 minUSBTripMilliS = Alg::Min(usbRountripElapsedMilliS, minUSBTripMilliS);
  67.498                 maxUSBTripMilliS = Alg::Max(usbRountripElapsedMilliS, maxUSBTripMilliS);
  67.499                 averageUSBTripMilliS += usbRountripElapsedMilliS;
  67.500                 countUSBTripTime++;
  67.501             }
  67.502         }
  67.503 
  67.504         if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES &&
  67.505             measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES)
  67.506         {
  67.507             break;
  67.508         }
  67.509 
  67.510         if (Results.IsLast(pCurr))
  67.511         {
  67.512             break;
  67.513         }
  67.514         pCurr = Results.GetNext(pCurr);
  67.515     }
  67.516 
  67.517     averageTime1To2 /= (float) DEFAULT_NUMBER_OF_SAMPLES;      
  67.518     averageTime2To1 /= (float) DEFAULT_NUMBER_OF_SAMPLES;
  67.519 
  67.520     averageUSBTripMilliS /= countUSBTripTime;
  67.521     
  67.522     float finalResult = 0.5f * (averageTime1To2 + averageTime2To1);
  67.523     finalResult += averageUSBTripMilliS;
  67.524 
  67.525     ResultsString.Clear();
  67.526     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]",  
  67.527                 finalResult, 
  67.528                 minTime1To2, averageTime1To2, maxTime1To2, 
  67.529                 minTime2To1, averageTime2To1, maxTime2To1,
  67.530                 minUSBTripMilliS, averageUSBTripMilliS, maxUSBTripMilliS,
  67.531                 DEFAULT_NUMBER_OF_SAMPLES*2, count - measurementsCount);
  67.532     
  67.533     // Display result on latency tester display.
  67.534     LatencyTestDisplay ltd(1, (int)finalResult);
  67.535     Device->SetDisplay(ltd);
  67.536 }
  67.537 
  67.538 void LatencyTest::updateForTimeouts()
  67.539 {
  67.540     if (!HaveOldTime)
  67.541     {
  67.542         HaveOldTime = true;
  67.543         OldTime = Timer::GetTicksMs();
  67.544         return;
  67.545     }
  67.546 
  67.547     UInt32 newTime = Timer::GetTicksMs();
  67.548     UInt32 elapsedMilliS = newTime - OldTime;
  67.549     if (newTime < OldTime)
  67.550     {
  67.551         elapsedMilliS = OldTime - newTime;
  67.552         elapsedMilliS = UINT_MAX - elapsedMilliS;
  67.553     }
  67.554     OldTime = newTime;
  67.555 
  67.556     elapsedMilliS = Alg::Min(elapsedMilliS, (UInt32) 100);   // Clamp at 100mS in case we're not being called very often.
  67.557 
  67.558 
  67.559     if (ActiveTimerMilliS == 0)
  67.560     {
  67.561         return;
  67.562     }
  67.563 
  67.564     if (elapsedMilliS >= ActiveTimerMilliS)
  67.565     {
  67.566         ActiveTimerMilliS = 0;
  67.567         handleMessage(Message(), LatencyTest_Timer);
  67.568         return;
  67.569     }
  67.570 
  67.571     ActiveTimerMilliS -= elapsedMilliS;
  67.572 }
  67.573 
  67.574 }} // namespace OVR::Util
  67.575 \ No newline at end of file
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/libovr/Src/Util/Util_LatencyTest.h	Sat Sep 14 16:14:59 2013 +0300
    68.3 @@ -0,0 +1,1 @@
    68.4 +/************************************************************************************
    68.5 
    68.6 PublicHeader:   OVR.h
    68.7 Filename    :   Util_LatencyTest.h
    68.8 Content     :   Wraps the lower level LatencyTesterDevice and adds functionality.
    68.9 Created     :   February 14, 2013
   68.10 Authors     :   Lee Cooper
   68.11 
   68.12 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   68.13 
   68.14 Use of this software is subject to the terms of the Oculus license
   68.15 agreement provided at the time of installation or download, or which
   68.16 otherwise accompanies this software in either electronic or hard copy form.
   68.17 
   68.18 *************************************************************************************/
   68.19 
   68.20 #ifndef OVR_Util_LatencyTest_h
   68.21 #define OVR_Util_LatencyTest_h
   68.22 
   68.23 #include "../OVR_Device.h"
   68.24 
   68.25 #include "../Kernel/OVR_String.h"
   68.26 #include "../Kernel/OVR_List.h"
   68.27 
   68.28 namespace OVR { namespace Util {
   68.29 
   68.30 
   68.31 //-------------------------------------------------------------------------------------
   68.32 // ***** LatencyTest
   68.33 //
   68.34 // LatencyTest utility class wraps the low level LatencyTestDevice and manages the scheduling
   68.35 // of a latency test. A single test is composed of a series of individual latency measurements
   68.36 // which are used to derive min, max, and an average latency value.
   68.37 //
   68.38 // Developers are required to call the following methods:
   68.39 //      SetDevice - Sets the LatencyTestDevice to be used for the tests.
   68.40 //      ProcessInputs - This should be called at the same place in the code where the game engine
   68.41 //                      reads the headset orientation from LibOVR (typically done by calling
   68.42 //                      'GetOrientation' on the SensorFusion object). Calling this at the right time
   68.43 //                      enables us to measure the same latency that occurs for headset orientation
   68.44 //                      changes.
   68.45 //      DisplayScreenColor -    The latency tester works by sensing the color of the pixels directly
   68.46 //                              beneath it. The color of these pixels can be set by drawing a small
   68.47 //                              quad at the end of the rendering stage. The quad should be small
   68.48 //                              such that it doesn't significantly impact the rendering of the scene,
   68.49 //                              but large enough to be 'seen' by the sensor. See the SDK
   68.50 //                              documentation for more information.
   68.51 //		GetResultsString -	Call this to get a string containing the most recent results.
   68.52 //							If the string has already been gotten then NULL will be returned.
   68.53 //							The string pointer will remain valid until the next time this 
   68.54 //							method is called.
   68.55 //
   68.56 
   68.57 class LatencyTest : public NewOverrideBase
   68.58 {
   68.59 public:
   68.60     LatencyTest(LatencyTestDevice* device = NULL);
   68.61     ~LatencyTest();
   68.62     
   68.63     // Set the Latency Tester device that we'll use to send commands to and receive
   68.64     // notification messages from.
   68.65     bool        SetDevice(LatencyTestDevice* device);
   68.66 
   68.67     // Returns true if this LatencyTestUtil has a Latency Tester device.
   68.68     bool        HasDevice() const
   68.69     { return Handler.IsHandlerInstalled(); }
   68.70 
   68.71     void        ProcessInputs();
   68.72     bool        DisplayScreenColor(Color& colorToDisplay);
   68.73 	const char*	GetResultsString();
   68.74 
   68.75     // Begin test. Equivalent to pressing the button on the latency tester.
   68.76     void BeginTest();
   68.77 
   68.78 private:
   68.79     LatencyTest* getThis()  { return this; }
   68.80 
   68.81     enum LatencyTestMessageType
   68.82     {
   68.83         LatencyTest_None,
   68.84         LatencyTest_Timer,
   68.85         LatencyTest_ProcessInputs,
   68.86     };
   68.87     
   68.88     UInt32 getRandomComponent(UInt32 range);
   68.89     void handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage = LatencyTest_None);
   68.90     void reset();
   68.91     void setTimer(UInt32 timeMilliS);
   68.92     void clearTimer();
   68.93 
   68.94     class LatencyTestHandler : public MessageHandler
   68.95     {
   68.96         LatencyTest*    pLatencyTestUtil;
   68.97     public:
   68.98         LatencyTestHandler(LatencyTest* latencyTester) : pLatencyTestUtil(latencyTester) { }
   68.99         ~LatencyTestHandler();
  68.100 
  68.101         virtual void OnMessage(const Message& msg);
  68.102     };
  68.103 
  68.104     bool areResultsComplete();
  68.105     void processResults();
  68.106     void updateForTimeouts();
  68.107 
  68.108     Ptr<LatencyTestDevice>      Device;
  68.109     LatencyTestHandler          Handler;
  68.110 
  68.111     enum TesterState
  68.112     {
  68.113         State_WaitingForButton,
  68.114         State_WaitingForSettlePreCalibrationColorBlack,
  68.115         State_WaitingForSettlePostCalibrationColorBlack,
  68.116         State_WaitingForSettlePreCalibrationColorWhite,
  68.117         State_WaitingForSettlePostCalibrationColorWhite,
  68.118         State_WaitingToTakeMeasurement,
  68.119         State_WaitingForTestStarted,
  68.120         State_WaitingForColorDetected,
  68.121         State_WaitingForSettlePostMeasurement
  68.122     };
  68.123     TesterState                 State;
  68.124 
  68.125     bool                        HaveOldTime;
  68.126     UInt32                      OldTime;
  68.127     UInt32                      ActiveTimerMilliS;
  68.128 
  68.129     Color                       RenderColor;
  68.130 
  68.131     struct MeasurementResult : public ListNode<MeasurementResult>, public NewOverrideBase
  68.132     {
  68.133         MeasurementResult()
  68.134          :  DeviceMeasuredElapsedMilliS(0),
  68.135             TimedOutWaitingForTestStarted(false),
  68.136             TimedOutWaitingForColorDetected(false),
  68.137             StartTestTicksMicroS(0),
  68.138             TestStartedTicksMicroS(0)
  68.139         {}
  68.140 
  68.141         Color                   TargetColor;
  68.142 
  68.143         UInt32                  DeviceMeasuredElapsedMilliS;
  68.144 
  68.145         bool                    TimedOutWaitingForTestStarted;
  68.146         bool                    TimedOutWaitingForColorDetected;
  68.147 
  68.148         UInt64                  StartTestTicksMicroS;
  68.149         UInt64                  TestStartedTicksMicroS;
  68.150     };
  68.151 
  68.152     List<MeasurementResult>     Results;
  68.153     void clearMeasurementResults();
  68.154 
  68.155     MeasurementResult*          getActiveResult();
  68.156 
  68.157     StringBuffer			    ResultsString;
  68.158 	String					    ReturnedResultString;
  68.159 };
  68.160 
  68.161 }} // namespace OVR::Util
  68.162 
  68.163 #endif // OVR_Util_LatencyTest_h
  68.164 \ No newline at end of file
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/libovr/Src/Util/Util_MagCalibration.cpp	Sat Sep 14 16:14:59 2013 +0300
    69.3 @@ -0,0 +1,1 @@
    69.4 +/************************************************************************************
    69.5 
    69.6 Filename    :   Util_MagCalibration.cpp
    69.7 Content     :   Procedures for calibrating the magnetometer
    69.8 Created     :   April 16, 2013
    69.9 Authors     :   Steve LaValle, Andrew Reisse
   69.10 
   69.11 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   69.12 
   69.13 Use of this software is subject to the terms of the Oculus license
   69.14 agreement provided at the time of installation or download, or which
   69.15 otherwise accompanies this software in either electronic or hard copy form.
   69.16 
   69.17 *************************************************************************************/
   69.18 
   69.19 #include "Util_MagCalibration.h"
   69.20 
   69.21 namespace OVR { namespace Util {
   69.22 
   69.23 void MagCalibration::BeginAutoCalibration(SensorFusion& sf)
   69.24 {
   69.25     Stat = Mag_AutoCalibrating;
   69.26     // This is a "hard" reset of the mag, so need to clear stored values
   69.27     sf.ClearMagCalibration();
   69.28     SampleCount = 0;
   69.29 
   69.30     // reset the statistics
   69.31     MinMagValues = Vector3f(10000.0f,10000.0f,10000.0f);
   69.32     MaxMagValues = Vector3f(-10000.0f,-10000.0f,-10000.0f);
   69.33 	MinQuatValues = Quatf(1.0f,1.0f,1.0f,1.0f);
   69.34 	MaxQuatValues = Quatf(0.0f,0.0f,0.0f,0.0f);
   69.35 }
   69.36 
   69.37 unsigned MagCalibration::UpdateAutoCalibration(SensorFusion& sf)
   69.38 {
   69.39     if (Stat != Mag_AutoCalibrating)
   69.40         return Stat;
   69.41 
   69.42     Quatf q = sf.GetOrientation();
   69.43     Vector3f m = sf.GetMagnetometer();
   69.44 
   69.45     InsertIfAcceptable(q, m);
   69.46 
   69.47     if ((SampleCount == 4) && (Stat == Mag_AutoCalibrating))
   69.48 	{
   69.49 		//LogText("Magnetometer Output Spread: %f %f %f\n",MagSpread.x,MagSpread.y,MagSpread.z);
   69.50 		//LogText("Quaternion Spread: %f %f %f %f\n",QuatSpread.x,QuatSpread.y,QuatSpread.z,QuatSpread.w);
   69.51         SetCalibration(sf);
   69.52 	}
   69.53 
   69.54     return Stat;
   69.55 
   69.56 }
   69.57 
   69.58 void MagCalibration::BeginManualCalibration(SensorFusion& sf)
   69.59 {
   69.60     Stat = Mag_ManuallyCalibrating;
   69.61     sf.ClearMagCalibration();
   69.62     SampleCount = 0;
   69.63 }
   69.64 
   69.65 bool MagCalibration::IsAcceptableSample(const Quatf& q, const Vector3f& m)
   69.66 {
   69.67     switch (SampleCount)
   69.68     {
   69.69         // Initial sample is always acceptable
   69.70     case 0:
   69.71         return true;
   69.72         break;
   69.73     case 1:
   69.74         return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&&
   69.75                ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq);
   69.76         break;
   69.77     case 2:
   69.78         return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&&
   69.79                (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&&
   69.80                ((m - MagSamples[0]).LengthSq() > MinMagDistanceSq)&&
   69.81                ((m - MagSamples[1]).LengthSq() > MinMagDistanceSq);
   69.82         break;
   69.83     case 3:
   69.84         return (q.DistanceSq(QuatSamples[0]) > MinQuatDistanceSq)&&
   69.85                (q.DistanceSq(QuatSamples[1]) > MinQuatDistanceSq)&&
   69.86                (q.DistanceSq(QuatSamples[2]) > MinQuatDistanceSq)&&
   69.87                ((PointToPlaneDistance(MagSamples[0],MagSamples[1],MagSamples[2],m) > MinMagDistance)||
   69.88                 (PointToPlaneDistance(MagSamples[1],MagSamples[2],m,MagSamples[0]) > MinMagDistance)||
   69.89                 (PointToPlaneDistance(MagSamples[2],m,MagSamples[0],MagSamples[1]) > MinMagDistance)||
   69.90                 (PointToPlaneDistance(m,MagSamples[0],MagSamples[1],MagSamples[2]) > MinMagDistance));
   69.91     }
   69.92 
   69.93     return false;
   69.94 }
   69.95 
   69.96 
   69.97 bool MagCalibration::InsertIfAcceptable(const Quatf& q, const Vector3f& m)
   69.98 {
   69.99 	// Update some statistics
  69.100 	if (m.x < MinMagValues.x)
  69.101 		MinMagValues.x = m.x;
  69.102 	if (m.y < MinMagValues.y)
  69.103 		MinMagValues.y = m.y;
  69.104 	if (m.z < MinMagValues.z)
  69.105 		MinMagValues.z = m.z;
  69.106 	if (m.x > MaxMagValues.x)
  69.107 		MaxMagValues.x = m.x;
  69.108 	if (m.y > MaxMagValues.y)
  69.109 		MaxMagValues.y = m.y;
  69.110 	if (m.z > MaxMagValues.z)
  69.111 		MaxMagValues.z = m.z;
  69.112 	if (q.x < MinQuatValues.x)
  69.113 		MinQuatValues.x = q.x;
  69.114 	if (q.y < MinQuatValues.y)
  69.115 		MinQuatValues.y = q.y;
  69.116 	if (q.z < MinQuatValues.z)
  69.117 		MinQuatValues.z = q.z;
  69.118 	if (q.w < MinQuatValues.w)
  69.119 		MinQuatValues.w = q.w;
  69.120 	if (q.x > MaxQuatValues.x)
  69.121 		MaxQuatValues.x = q.x;
  69.122 	if (q.y > MaxQuatValues.y)
  69.123 		MaxQuatValues.y = q.y;
  69.124 	if (q.z > MaxQuatValues.z)
  69.125 		MaxQuatValues.z = q.z;
  69.126 	if (q.w > MaxQuatValues.w)
  69.127 		MaxQuatValues.w = q.w;
  69.128 	MagSpread = MaxMagValues - MinMagValues;
  69.129 	QuatSpread = MaxQuatValues - MinQuatValues;
  69.130 
  69.131 	if (IsAcceptableSample(q, m))
  69.132     {
  69.133         MagSamples[SampleCount] = m;
  69.134         QuatSamples[SampleCount] = q;
  69.135         SampleCount++;
  69.136         return true;
  69.137     }
  69.138 
  69.139     return false;
  69.140 }
  69.141 
  69.142 Matrix4f MagCalibration::GetMagCalibration() const
  69.143 {
  69.144     Matrix4f calMat = Matrix4f();
  69.145     calMat.M[0][3] = -MagCenter.x;
  69.146     calMat.M[1][3] = -MagCenter.y;
  69.147     calMat.M[2][3] = -MagCenter.z;
  69.148     return calMat;
  69.149 }
  69.150 
  69.151 bool MagCalibration::SetCalibration(SensorFusion& sf)
  69.152 {
  69.153     if (SampleCount < 4)
  69.154         return false;
  69.155 
  69.156     MagCenter = CalculateSphereCenter(MagSamples[0],MagSamples[1],MagSamples[2],MagSamples[3]);
  69.157     Matrix4f calMat = GetMagCalibration();
  69.158     sf.SetMagCalibration(calMat);
  69.159     Stat = Mag_Calibrated;
  69.160     //LogText("MagCenter: %f %f %f\n",MagCenter.x,MagCenter.y,MagCenter.z);
  69.161 
  69.162     return true;
  69.163 }
  69.164 
  69.165 
  69.166 // Calculate the center of a sphere that passes through p1, p2, p3, p4
  69.167 Vector3f MagCalibration::CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2,
  69.168                                                const Vector3f& p3, const Vector3f& p4) 
  69.169 {
  69.170     Matrix4f A;
  69.171     int i;
  69.172     Vector3f p[4];
  69.173     p[0] = p1;
  69.174     p[1] = p2;
  69.175     p[2] = p3;
  69.176     p[3] = p4;
  69.177 
  69.178     for (i = 0; i < 4; i++) 
  69.179     {
  69.180         A.M[i][0] = p[i].x;
  69.181         A.M[i][1] = p[i].y;
  69.182         A.M[i][2] = p[i].z;
  69.183         A.M[i][3] = 1.0f;
  69.184     }
  69.185     float m11 = A.Determinant();
  69.186     OVR_ASSERT(m11 != 0.0f);
  69.187 
  69.188     for (i = 0; i < 4; i++) 
  69.189     {
  69.190         A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z;
  69.191         A.M[i][1] = p[i].y;
  69.192         A.M[i][2] = p[i].z;
  69.193         A.M[i][3] = 1.0f;
  69.194     }
  69.195     float m12 = A.Determinant();
  69.196 
  69.197     for (i = 0; i < 4; i++) 
  69.198     {
  69.199         A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z;
  69.200         A.M[i][1] = p[i].x;
  69.201         A.M[i][2] = p[i].z;
  69.202         A.M[i][3] = 1.0f;
  69.203     }
  69.204     float m13 = A.Determinant();
  69.205 
  69.206     for (i = 0; i < 4; i++) 
  69.207     {
  69.208         A.M[i][0] = p[i].x*p[i].x + p[i].y*p[i].y + p[i].z*p[i].z;
  69.209         A.M[i][1] = p[i].x;
  69.210         A.M[i][2] = p[i].y;
  69.211         A.M[i][3] = 1.0f;
  69.212     }
  69.213     float m14 = A.Determinant();
  69.214 
  69.215     float c = 0.5f / m11;
  69.216     return Vector3f(c*m12, -c*m13, c*m14);
  69.217 }
  69.218 
  69.219 // Distance from p4 to the nearest point on a plane through p1, p2, p3
  69.220 float MagCalibration::PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2,
  69.221                                            const Vector3f& p3, const Vector3f& p4) 
  69.222 {
  69.223     Vector3f v1 = p1 - p2;
  69.224     Vector3f v2 = p1 - p3;
  69.225     Vector3f planeNormal = v1.Cross(v2);
  69.226     planeNormal.Normalize();
  69.227     return (fabs((planeNormal * p4) - planeNormal * p1));
  69.228 }
  69.229 
  69.230 }}
  69.231 \ No newline at end of file
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/libovr/Src/Util/Util_MagCalibration.h	Sat Sep 14 16:14:59 2013 +0300
    70.3 @@ -0,0 +1,1 @@
    70.4 +/************************************************************************************
    70.5 
    70.6 PublicHeader:   OVR.h
    70.7 Filename    :   Util_MagCalibration.h
    70.8 Content     :   Procedures for calibrating the magnetometer
    70.9 Created     :   April 16, 2013
   70.10 Authors     :   Steve LaValle, Andrew Reisse
   70.11 
   70.12 Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   70.13 
   70.14 Use of this software is subject to the terms of the Oculus license
   70.15 agreement provided at the time of installation or download, or which
   70.16 otherwise accompanies this software in either electronic or hard copy form.
   70.17 
   70.18 *************************************************************************************/
   70.19 
   70.20 #ifndef OVR_Util_MagCalibration_h
   70.21 #define OVR_Util_MagCalibration_h
   70.22 
   70.23 #include "../OVR_SensorFusion.h"
   70.24 #include "../Kernel/OVR_String.h"
   70.25 #include "../Kernel/OVR_Log.h"
   70.26 
   70.27 namespace OVR { namespace Util {
   70.28 
   70.29 class MagCalibration
   70.30 {
   70.31 public:
   70.32     enum MagStatus
   70.33     {
   70.34         Mag_Uninitialized = 0,
   70.35         Mag_AutoCalibrating = 1,
   70.36         Mag_ManuallyCalibrating = 2,
   70.37         Mag_Calibrated  = 3
   70.38     };
   70.39 
   70.40     MagCalibration() :
   70.41         Stat(Mag_Uninitialized),
   70.42         MinMagDistance(0.2f), MinQuatDistance(0.5f),
   70.43         SampleCount(0)
   70.44     {
   70.45         MinMagDistanceSq = MinMagDistance * MinMagDistance;
   70.46         MinQuatDistanceSq = MinQuatDistance * MinQuatDistance;
   70.47         MinMagValues = Vector3f(10000.0f,10000.0f,10000.0f);
   70.48         MaxMagValues = Vector3f(-10000.0f,-10000.0f,-10000.0f);
   70.49 		MinQuatValues = Quatf(1.0f,1.0f,1.0f,1.0f);
   70.50 		MaxQuatValues = Quatf(0.0f,0.0f,0.0f,0.0f);
   70.51 		}
   70.52 
   70.53     // Methods that are useful for either auto or manual calibration
   70.54     bool     IsUnitialized() const       { return Stat == Mag_Uninitialized; }
   70.55     bool     IsCalibrated() const        { return Stat == Mag_Calibrated; }
   70.56     int      NumberOfSamples() const     { return SampleCount; }
   70.57     int      RequiredSampleCount() const { return 4; }
   70.58 	void     AbortCalibration()
   70.59 	{
   70.60         Stat = Mag_Uninitialized;
   70.61         SampleCount = 0;
   70.62 	}
   70.63 
   70.64     void     ClearCalibration(SensorFusion& sf) 
   70.65     {
   70.66         Stat = Mag_Uninitialized;
   70.67         SampleCount = 0;
   70.68         sf.ClearMagCalibration();
   70.69 	};
   70.70   
   70.71     // Methods for automatic magnetometer calibration
   70.72     void     BeginAutoCalibration(SensorFusion& sf);
   70.73     unsigned UpdateAutoCalibration(SensorFusion& sf);
   70.74     bool     IsAutoCalibrating() const { return Stat == Mag_AutoCalibrating; }
   70.75 
   70.76     // Methods for building a manual (user-guided) calibraton procedure
   70.77     void     BeginManualCalibration(SensorFusion& sf);
   70.78     bool     IsAcceptableSample(const Quatf& q, const Vector3f& m);
   70.79     bool     InsertIfAcceptable(const Quatf& q, const Vector3f& m);
   70.80     // Returns true if successful, requiring that SampleCount = 4
   70.81     bool     SetCalibration(SensorFusion& sf);
   70.82     bool     IsManuallyCalibrating() const { return Stat == Mag_ManuallyCalibrating; }
   70.83 
   70.84     // This is the minimum acceptable distance (Euclidean) between raw
   70.85     // magnetometer values to be acceptable for usage in calibration.
   70.86     void SetMinMagDistance(float dist) 
   70.87     { 
   70.88         MinMagDistance = dist; 
   70.89         MinMagDistanceSq = MinMagDistance * MinMagDistance;
   70.90     }
   70.91 
   70.92     // The minimum acceptable distance (4D Euclidean) between orientations
   70.93     // to be acceptable for calibration usage.
   70.94     void SetMinQuatDistance(float dist) 
   70.95     { 
   70.96         MinQuatDistance = dist; 
   70.97         MinQuatDistanceSq = MinQuatDistance * MinQuatDistance;
   70.98     }
   70.99 
  70.100     // A result of the calibration, which is the center of a sphere that 
  70.101     // roughly approximates the magnetometer data.
  70.102     Vector3f GetMagCenter() const { return MagCenter; }
  70.103     // Retrieves the full magnetometer calibration matrix
  70.104     Matrix4f GetMagCalibration() const;
  70.105     // Retrieves the range of each quaternion term during calibration
  70.106     Quatf GetCalibrationQuatSpread() const { return QuatSpread; }
  70.107     // Retrieves the range of each magnetometer term during calibration
  70.108     Vector3f GetCalibrationMagSpread() const { return MagSpread; }
  70.109 
  70.110 private:
  70.111     // Determine the unique sphere through 4 non-coplanar points
  70.112     Vector3f CalculateSphereCenter(const Vector3f& p1, const Vector3f& p2,
  70.113                                    const Vector3f& p3, const Vector3f& p4);
  70.114 
  70.115     // Distance from p4 to the nearest point on a plane through p1, p2, p3
  70.116     float PointToPlaneDistance(const Vector3f& p1, const Vector3f& p2,
  70.117                                const Vector3f& p3, const Vector3f& p4);
  70.118 
  70.119     Vector3f MagCenter;
  70.120     unsigned Stat;
  70.121     float    MinMagDistance;
  70.122     float    MinQuatDistance;
  70.123     float    MinMagDistanceSq;
  70.124     float    MinQuatDistanceSq;
  70.125 	// For gathering statistics during calibration
  70.126 	Vector3f    MinMagValues;
  70.127 	Vector3f    MaxMagValues;
  70.128 	Vector3f    MagSpread;
  70.129 	Quatf		MinQuatValues;
  70.130 	Quatf		MaxQuatValues;
  70.131 	Quatf       QuatSpread;
  70.132 
  70.133     unsigned SampleCount;
  70.134     Vector3f MagSamples[4];
  70.135     Quatf    QuatSamples[4];
  70.136 
  70.137 };
  70.138 
  70.139 }}
  70.140 
  70.141 #endif
  70.142 \ No newline at end of file
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/libovr/Src/Util/Util_Render_Stereo.cpp	Sat Sep 14 16:14:59 2013 +0300
    71.3 @@ -0,0 +1,1 @@
    71.4 +/************************************************************************************
    71.5 
    71.6 Filename    :   Util_Render_Stereo.cpp
    71.7 Content     :   Stereo rendering configuration implementation
    71.8 Created     :   October 22, 2012
    71.9 Authors     :   Michael Antonov, Andrew Reisse
   71.10 
   71.11 Copyright   :   Copyright 2012 Oculus, Inc. All Rights reserved.
   71.12 
   71.13 Use of this software is subject to the terms of the Oculus Inc license
   71.14 agreement provided at the time of installation or download, or which
   71.15 otherwise accompanies this software in either electronic or hard copy form.
   71.16 
   71.17 *************************************************************************************/
   71.18 
   71.19 #include "Util_Render_Stereo.h"
   71.20 
   71.21 namespace OVR { namespace Util { namespace Render {
   71.22 
   71.23 
   71.24 //-----------------------------------------------------------------------------------
   71.25 
   71.26 // DistortionFnInverse computes the inverse of the distortion function on an argument.
   71.27 float DistortionConfig::DistortionFnInverse(float r)
   71.28 {    
   71.29     OVR_ASSERT((r <= 10.0f));
   71.30 
   71.31     float s, d;
   71.32     float delta = r * 0.25f;
   71.33 
   71.34     s = r * 0.5f;
   71.35     d = fabs(r - DistortionFn(s));
   71.36 
   71.37     for (int i = 0; i < 20; i++)
   71.38     {
   71.39         float sUp   = s + delta;
   71.40         float sDown = s - delta;
   71.41         float dUp   = fabs(r - DistortionFn(sUp));
   71.42         float dDown = fabs(r - DistortionFn(sDown));
   71.43 
   71.44         if (dUp < d)
   71.45         {
   71.46             s = sUp;
   71.47             d = dUp;
   71.48         }
   71.49         else if (dDown < d)
   71.50         {
   71.51             s = sDown;
   71.52             d = dDown;
   71.53         }
   71.54         else
   71.55         {
   71.56             delta *= 0.5f;
   71.57         }
   71.58     }
   71.59 
   71.60     return s;
   71.61 }
   71.62 
   71.63 
   71.64 //-----------------------------------------------------------------------------------
   71.65 // **** StereoConfig Implementation
   71.66 
   71.67 StereoConfig::StereoConfig(StereoMode mode, const Viewport& vp)
   71.68     : Mode(mode),
   71.69       InterpupillaryDistance(0.064f), AspectMultiplier(1.0f),
   71.70       FullView(vp), DirtyFlag(true), IPDOverride(false),
   71.71       YFov(0), Aspect(vp.w / float(vp.h)), ProjectionCenterOffset(0),
   71.72       OrthoPixelOffset(0)
   71.73 {
   71.74     // And default distortion for it.
   71.75     Distortion.SetCoefficients(1.0f, 0.22f, 0.24f);
   71.76     Distortion.Scale = 1.0f; // Will be computed later.
   71.77 
   71.78     // Fit left of the image.
   71.79     DistortionFitX = -1.0f;
   71.80     DistortionFitY = 0.0f;
   71.81 
   71.82     // Initialize "fake" default HMD values for testing without HMD plugged in.
   71.83     // These default values match those returned by the HMD.
   71.84     HMD.HResolution            = 1280;
   71.85     HMD.VResolution            = 800;
   71.86     HMD.HScreenSize            = 0.14976f;
   71.87     HMD.VScreenSize            = HMD.HScreenSize / (1280.0f / 800.0f);
   71.88     HMD.InterpupillaryDistance = InterpupillaryDistance;
   71.89     HMD.LensSeparationDistance = 0.0635f;
   71.90     HMD.EyeToScreenDistance    = 0.041f;
   71.91     HMD.DistortionK[0]         = Distortion.K[0];
   71.92     HMD.DistortionK[1]         = Distortion.K[1];
   71.93     HMD.DistortionK[2]         = Distortion.K[2];
   71.94     HMD.DistortionK[3]         = 0;
   71.95 
   71.96     Set2DAreaFov(DegreeToRad(85.0f));
   71.97 }
   71.98 
   71.99 void StereoConfig::SetFullViewport(const Viewport& vp)
  71.100 {
  71.101     if (vp != FullView)
  71.102     { 
  71.103         FullView = vp;
  71.104         DirtyFlag = true;
  71.105     }
  71.106 }
  71.107 
  71.108 void StereoConfig::SetHMDInfo(const HMDInfo& hmd)
  71.109 {
  71.110     HMD = hmd;
  71.111     Distortion.K[0] = hmd.DistortionK[0];
  71.112     Distortion.K[1] = hmd.DistortionK[1];
  71.113     Distortion.K[2] = hmd.DistortionK[2];
  71.114     Distortion.K[3] = hmd.DistortionK[3];
  71.115 
  71.116     Distortion.SetChromaticAberration(hmd.ChromaAbCorrection[0], hmd.ChromaAbCorrection[1],
  71.117                                       hmd.ChromaAbCorrection[2], hmd.ChromaAbCorrection[3]);
  71.118 
  71.119     if (!IPDOverride)
  71.120         InterpupillaryDistance = HMD.InterpupillaryDistance;
  71.121 
  71.122     DirtyFlag = true;
  71.123 }
  71.124 
  71.125 void StereoConfig::SetDistortionFitPointVP(float x, float y)
  71.126 {
  71.127     DistortionFitX = x;
  71.128     DistortionFitY = y;
  71.129     DirtyFlag = true;
  71.130 }
  71.131 
  71.132 void StereoConfig::SetDistortionFitPointPixels(float x, float y)
  71.133 {
  71.134     DistortionFitX = (4 * x / float(FullView.w)) - 1.0f;
  71.135     DistortionFitY = (2 * y / float(FullView.h)) - 1.0f;
  71.136     DirtyFlag = true;
  71.137 }
  71.138 
  71.139 void StereoConfig::Set2DAreaFov(float fovRadians)
  71.140 {
  71.141     Area2DFov = fovRadians;
  71.142     DirtyFlag = true;
  71.143 }
  71.144 
  71.145 
  71.146 const StereoEyeParams& StereoConfig::GetEyeRenderParams(StereoEye eye)
  71.147 {
  71.148     static const UByte eyeParamIndices[3] = { 0, 0, 1 };
  71.149 
  71.150     updateIfDirty();
  71.151     OVR_ASSERT(eye < sizeof(eyeParamIndices));
  71.152     return EyeRenderParams[eyeParamIndices[eye]];
  71.153 }
  71.154 
  71.155 
  71.156 void StereoConfig::updateComputedState()
  71.157 {
  71.158     // Need to compute all of the following:
  71.159     //   - Aspect Ratio
  71.160     //   - FOV
  71.161     //   - Projection offsets for 3D
  71.162     //   - Distortion XCenterOffset
  71.163     //   - Update 2D
  71.164     //   - Initialize EyeRenderParams
  71.165 
  71.166     // Compute aspect ratio. Stereo mode cuts width in half.
  71.167     Aspect = float(FullView.w) / float(FullView.h);
  71.168     Aspect *= (Mode == Stereo_None) ? 1.0f : 0.5f;
  71.169     Aspect *= AspectMultiplier; 
  71.170 
  71.171     updateDistortionOffsetAndScale();
  71.172 
  71.173     // Compute Vertical FOV based on distance, distortion, etc.
  71.174     // Distance from vertical center to render vertical edge perceived through the lens.
  71.175     // This will be larger then normal screen size due to magnification & distortion.
  71.176     //
  71.177     // This percievedHalfRTDistance equation should hold as long as the render target
  71.178     // and display have the same aspect ratios. What we'd like to know is where the edge
  71.179     // of the render target will on the perceived screen surface. With NO LENS,
  71.180     // the answer would be:
  71.181     //
  71.182     //  halfRTDistance = (VScreenSize / 2) * aspect *
  71.183     //                   DistortionFn_Inverse( DistortionScale / aspect )
  71.184     //
  71.185     // To model the optical lens we eliminates DistortionFn_Inverse. Aspect ratios
  71.186     // cancel out, so we get:
  71.187     //
  71.188     //  halfRTDistance = (VScreenSize / 2) * DistortionScale
  71.189     //
  71.190     if (Mode == Stereo_None)
  71.191     {
  71.192         YFov = DegreeToRad(80.0f);
  71.193     }
  71.194     else
  71.195     {
  71.196         float percievedHalfRTDistance = (HMD.VScreenSize / 2) * Distortion.Scale;    
  71.197         YFov = 2.0f * atan(percievedHalfRTDistance/HMD.EyeToScreenDistance);
  71.198     }
  71.199     
  71.200     updateProjectionOffset();
  71.201     update2D();
  71.202     updateEyeParams();
  71.203 
  71.204     DirtyFlag = false;
  71.205 }
  71.206 
  71.207 void StereoConfig::updateDistortionOffsetAndScale()
  71.208 {
  71.209     // Distortion center shift is stored separately, since it isn't affected
  71.210     // by the eye distance.
  71.211     float lensOffset        = HMD.LensSeparationDistance * 0.5f;
  71.212     float lensShift         = HMD.HScreenSize * 0.25f - lensOffset;
  71.213     float lensViewportShift = 4.0f * lensShift / HMD.HScreenSize;
  71.214     Distortion.XCenterOffset= lensViewportShift;
  71.215 
  71.216     // Compute distortion scale from DistortionFitX & DistortionFitY.
  71.217     // Fit value of 0.0 means "no fit".
  71.218     if ((fabs(DistortionFitX) < 0.0001f) &&  (fabs(DistortionFitY) < 0.0001f))
  71.219     {
  71.220         Distortion.Scale = 1.0f;
  71.221     }
  71.222     else
  71.223     {
  71.224         // Convert fit value to distortion-centered coordinates before fit radius
  71.225         // calculation.
  71.226         float stereoAspect = 0.5f * float(FullView.w) / float(FullView.h);
  71.227         float dx           = DistortionFitX - Distortion.XCenterOffset;
  71.228         float dy           = DistortionFitY / stereoAspect;
  71.229         float fitRadius    = sqrt(dx * dx + dy * dy);
  71.230         Distortion.Scale   = Distortion.DistortionFn(fitRadius)/fitRadius;
  71.231     }
  71.232 }
  71.233 
  71.234 void StereoConfig::updateProjectionOffset()
  71.235 {
  71.236     // Post-projection viewport coordinates range from (-1.0, 1.0), with the
  71.237     // center of the left viewport falling at (1/4) of horizontal screen size.
  71.238     // We need to shift this projection center to match with the lens center;
  71.239     // note that we don't use the IPD here due to collimated light property of the lens.
  71.240     // We compute this shift in physical units (meters) to
  71.241     // correct for different screen sizes and then rescale to viewport coordinates.    
  71.242     float viewCenter         = HMD.HScreenSize * 0.25f;
  71.243     float eyeProjectionShift = viewCenter - HMD.LensSeparationDistance*0.5f;
  71.244     ProjectionCenterOffset   = 4.0f * eyeProjectionShift / HMD.HScreenSize;
  71.245 }
  71.246 
  71.247 void StereoConfig::update2D()
  71.248 {
  71.249     // Orthographic projection fakes a screen at a distance of 0.8m from the
  71.250     // eye, where hmd screen projection surface is at 0.05m distance.
  71.251     // This introduces an extra off-center pixel projection shift based on eye distance.
  71.252     // This offCenterShift is the pixel offset of the other camera's center
  71.253     // in your reference camera based on surface distance.    
  71.254     float metersToPixels          = (HMD.HResolution / HMD.HScreenSize);
  71.255     float lensDistanceScreenPixels= metersToPixels * HMD.LensSeparationDistance;
  71.256     float eyeDistanceScreenPixels = metersToPixels * InterpupillaryDistance;
  71.257     float offCenterShiftPixels    = (HMD.EyeToScreenDistance / 0.8f) * eyeDistanceScreenPixels;
  71.258     float leftPixelCenter         = (HMD.HResolution / 2) - lensDistanceScreenPixels * 0.5f;
  71.259     float rightPixelCenter        = lensDistanceScreenPixels * 0.5f;
  71.260     float pixelDifference         = leftPixelCenter - rightPixelCenter;
  71.261     
  71.262     // This computes the number of pixels that fit within specified 2D FOV (assuming
  71.263     // distortion scaling will be done).
  71.264     float percievedHalfScreenDistance = tan(Area2DFov * 0.5f) * HMD.EyeToScreenDistance;
  71.265     float vfovSize = 2.0f * percievedHalfScreenDistance / Distortion.Scale;
  71.266     FovPixels = HMD.VResolution * vfovSize / HMD.VScreenSize;
  71.267     
  71.268     // Create orthographic matrix.   
  71.269     Matrix4f& m      = OrthoCenter;
  71.270     m.SetIdentity();
  71.271     m.M[0][0] = FovPixels / (FullView.w * 0.5f);
  71.272     m.M[1][1] = -FovPixels / FullView.h;
  71.273     m.M[0][3] = 0;
  71.274     m.M[1][3] = 0;
  71.275     m.M[2][2] = 0;
  71.276 
  71.277     float orthoPixelOffset = (pixelDifference + offCenterShiftPixels/Distortion.Scale) * 0.5f;
  71.278     OrthoPixelOffset = orthoPixelOffset * 2.0f / FovPixels;
  71.279 }
  71.280 
  71.281 void StereoConfig::updateEyeParams()
  71.282 {
  71.283     // Projection matrix for the center eye, which the left/right matrices are based on.
  71.284     Matrix4f projCenter = Matrix4f::PerspectiveRH(YFov, Aspect, 0.01f, 2000.0f);
  71.285    
  71.286     switch(Mode)
  71.287     {
  71.288     case Stereo_None:
  71.289         {
  71.290             EyeRenderParams[0].Init(StereoEye_Center, FullView, 0, projCenter, OrthoCenter);
  71.291         }
  71.292         break;
  71.293 
  71.294     case Stereo_LeftRight_Multipass:
  71.295         {
  71.296             Matrix4f projLeft  = Matrix4f::Translation(ProjectionCenterOffset, 0, 0) * projCenter,
  71.297                      projRight = Matrix4f::Translation(-ProjectionCenterOffset, 0, 0) * projCenter;
  71.298 
  71.299             EyeRenderParams[0].Init(StereoEye_Left,
  71.300                 Viewport(FullView.x, FullView.y, FullView.w/2, FullView.h),
  71.301                          +InterpupillaryDistance * 0.5f,  // World view shift.                       
  71.302                          projLeft, OrthoCenter * Matrix4f::Translation(OrthoPixelOffset, 0, 0),
  71.303                          &Distortion);
  71.304             EyeRenderParams[1].Init(StereoEye_Right,
  71.305                 Viewport(FullView.x + FullView.w/2, FullView.y, FullView.w/2, FullView.h),
  71.306                          -InterpupillaryDistance * 0.5f,                         
  71.307                          projRight, OrthoCenter * Matrix4f::Translation(-OrthoPixelOffset, 0, 0),
  71.308                          &Distortion);
  71.309         }
  71.310         break;
  71.311     }
  71.312 
  71.313 }
  71.314 
  71.315 
  71.316 }}}  // OVR::Util::Render
  71.317 
  71.318 \ No newline at end of file
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/libovr/Src/Util/Util_Render_Stereo.h	Sat Sep 14 16:14:59 2013 +0300
    72.3 @@ -0,0 +1,1 @@
    72.4 +/************************************************************************************
    72.5 
    72.6 PublicHeader:   OVR.h
    72.7 Filename    :   Util_Render_Stereo.h
    72.8 Content     :   Sample stereo rendering configuration classes.
    72.9 Created     :   October 22, 2012
   72.10 Authors     :   Michael Antonov
   72.11 
   72.12 Copyright   :   Copyright 2012 Oculus, Inc. All Rights reserved.
   72.13 
   72.14 Use of this software is subject to the terms of the Oculus Inc license
   72.15 agreement provided at the time of installation or download, or which
   72.16 otherwise accompanies this software in either electronic or hard copy form.
   72.17 
   72.18 *************************************************************************************/
   72.19 
   72.20 #ifndef OVR_Util_Render_Stereo_h
   72.21 #define OVR_Util_Render_Stereo_h
   72.22 
   72.23 #include "../OVR_Device.h"
   72.24 
   72.25 namespace OVR { namespace Util { namespace Render {
   72.26 
   72.27 
   72.28 //-----------------------------------------------------------------------------------
   72.29 // ***** Stereo Enumerations
   72.30 
   72.31 // StereoMode describes rendering modes that can be used by StereoConfig.
   72.32 // These modes control whether stereo rendering is used or not (Stereo_None),
   72.33 // and how it is implemented.
   72.34 enum StereoMode
   72.35 {
   72.36     Stereo_None                 = 0,
   72.37     Stereo_LeftRight_Multipass  = 1
   72.38 };
   72.39 
   72.40 
   72.41 // StereoEye specifies which eye we are rendering for; it is used to
   72.42 // retrieve StereoEyeParams.
   72.43 enum StereoEye
   72.44 {
   72.45     StereoEye_Center,
   72.46     StereoEye_Left,
   72.47     StereoEye_Right    
   72.48 };
   72.49 
   72.50 
   72.51 //-----------------------------------------------------------------------------------
   72.52 // ***** Viewport
   72.53 
   72.54 // Viewport describes a rectangular area used for rendering, in pixels.
   72.55 struct Viewport
   72.56 {
   72.57     int x, y;
   72.58     int w, h;
   72.59 
   72.60     Viewport() {}
   72.61     Viewport(int x1, int y1, int w1, int h1) : x(x1), y(y1), w(w1), h(h1) { }
   72.62 
   72.63     bool operator == (const Viewport& vp) const
   72.64     { return (x == vp.x) && (y == vp.y) && (w == vp.w) && (h == vp.h); }
   72.65     bool operator != (const Viewport& vp) const
   72.66     { return !operator == (vp); }
   72.67 };
   72.68 
   72.69 
   72.70 //-----------------------------------------------------------------------------------
   72.71 // ***** DistortionConfig
   72.72 
   72.73 // DistortionConfig Provides controls for the distortion shader.
   72.74 //  - K[0] - K[3] are coefficients for the distortion function.
   72.75 //  - XCenterOffset is the offset of lens distortion center from the 
   72.76 //    center of one-eye screen half. [-1, 1] Range.
   72.77 //  - Scale is a factor of how much larger will the input image be,
   72.78 //    with a factor of 1.0f being no scaling. An inverse of this 
   72.79 //    value is applied to sampled UV coordinates (1/Scale).
   72.80 //  - ChromaticAberration is an array of parameters for controlling
   72.81 //    additional Red and Blue scaling in order to reduce chromatic aberration
   72.82 //    caused by the Rift lenses.
   72.83 class DistortionConfig
   72.84 {
   72.85 public:
   72.86     DistortionConfig(float k0 = 1.0f, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f)
   72.87         : XCenterOffset(0), YCenterOffset(0), Scale(1.0f)
   72.88     { 
   72.89         SetCoefficients(k0, k1, k2, k3);
   72.90         SetChromaticAberration();
   72.91     }
   72.92 
   72.93     void SetCoefficients(float k0, float k1 = 0.0f, float k2 = 0.0f, float k3 = 0.0f)
   72.94     { K[0] = k0; K[1] = k1;  K[2] = k2; K[3] = k3; }
   72.95 
   72.96     void SetChromaticAberration(float red1 = 1.0f, float red2 = 0.0f, float blue1 = 1.0f, float blue2 = 0.0f)
   72.97     { ChromaticAberration[0] = red1; ChromaticAberration[1] = red2; ChromaticAberration[2] = blue1; ChromaticAberration[3] = blue2; }
   72.98 
   72.99 
  72.100     // DistortionFn applies distortion equation to the argument. The returned
  72.101     // value should match distortion equation used in shader.
  72.102     float  DistortionFn(float r) const
  72.103     {        
  72.104         float rsq   = r * r;
  72.105         float scale = r * (K[0] + K[1] * rsq + K[2] * rsq * rsq + K[3] * rsq * rsq * rsq);
  72.106         return scale;
  72.107     }
  72.108 
  72.109     // DistortionFnInverse computes the inverse of the distortion function on an argument.
  72.110     float DistortionFnInverse(float r);
  72.111 
  72.112     float   K[4];
  72.113     float   XCenterOffset, YCenterOffset;
  72.114     float   Scale;
  72.115 
  72.116     float   ChromaticAberration[4]; // Additional per-channel scaling is applied after distortion:
  72.117                                     // Index [0] - Red channel constant coefficient.
  72.118                                     // Index [1] - Red channel r^2 coefficient.
  72.119                                     // Index [2] - Blue channel constant coefficient.
  72.120                                     // Index [3] - Blue channel r^2 coefficient.
  72.121 };
  72.122 
  72.123 
  72.124 //-----------------------------------------------------------------------------------
  72.125 // ***** StereoEyeParams
  72.126 
  72.127 // StereoEyeParams describes RenderDevice configuration needed to render
  72.128 // the scene for one eye. 
  72.129 class StereoEyeParams
  72.130 {
  72.131 public:
  72.132     StereoEye                Eye;
  72.133     Viewport                 VP;               // Viewport that we are rendering to        
  72.134     const DistortionConfig*  pDistortion;
  72.135 
  72.136     Matrix4f                 ViewAdjust;       // Translation to be applied to view matrix.
  72.137     Matrix4f                 Projection;       // Projection matrix used with this eye.
  72.138     Matrix4f                 OrthoProjection;  // Orthographic projection used with this eye.
  72.139 
  72.140     void Init(StereoEye eye, const Viewport &vp, float vofs,
  72.141               const Matrix4f& proj, const Matrix4f& orthoProj,
  72.142               const DistortionConfig* distortion = 0)
  72.143     {
  72.144         Eye                    = eye;
  72.145         VP                     = vp;
  72.146         ViewAdjust             = Matrix4f::Translation(Vector3f(vofs,0,0));
  72.147         Projection             = proj;
  72.148         OrthoProjection        = orthoProj;
  72.149         pDistortion            = distortion;        
  72.150     }
  72.151 };
  72.152 
  72.153 
  72.154 //-----------------------------------------------------------------------------------
  72.155 // *****  StereoConfig
  72.156 
  72.157 // StereoConfig maintains a scene stereo state and allow switching between different
  72.158 // stereo rendering modes. To support rendering, StereoConfig keeps track of HMD
  72.159 // variables such as screen size, eye-to-screen distance and distortion, and computes
  72.160 // extra data such as FOV and distortion center offsets based on it. Rendering
  72.161 // parameters are returned though StereoEyeParams for each eye.
  72.162 //
  72.163 // Beyond regular 3D projection, this class supports rendering a 2D orthographic
  72.164 // surface for UI and text. The 2D surface will be defined as fitting within a 2D
  72.165 // field of view (85 degrees by default) and used [-1,1] coordinate system with
  72.166 // square pixels. The (0,0) coordinate corresponds to eye center location
  72.167 // that is properly adjusted during rendering through SterepRenderParams::Adjust2D.
  72.168 // Genreally speaking, text outside [-1,1] coordinate range will not be readable.
  72.169 
  72.170 class StereoConfig
  72.171 {
  72.172 public:
  72.173 
  72.174     StereoConfig(StereoMode mode = Stereo_LeftRight_Multipass,
  72.175                  const Viewport& fullViewport = Viewport(0,0, 1280,800));
  72.176  
  72.177 
  72.178     // *** Modifiable State Access
  72.179 
  72.180     // Sets a stereo rendering mode and updates internal cached
  72.181     // state (matrices, per-eye view) based on it.
  72.182     void        SetStereoMode(StereoMode mode)  { Mode = mode; DirtyFlag = true; }
  72.183     StereoMode  GetStereoMode() const           { return Mode; }
  72.184 
  72.185     // Sets HMD parameters; also initializes distortion coefficients.
  72.186     void        SetHMDInfo(const HMDInfo& hmd);
  72.187     const HMDInfo& GetHMDInfo() const           { return HMD; }
  72.188 
  72.189     // Query physical eye-to-screen distance in meters, which combines screen-to-lens and
  72.190     // and lens-to-eye pupil distances. Modifying this value adjusts FOV.
  72.191     float       GetEyeToScreenDistance() const  { return HMD.EyeToScreenDistance; }
  72.192     void        SetEyeToScreenDistance(float esd) { HMD.EyeToScreenDistance = esd; DirtyFlag = true; }
  72.193 
  72.194     // Interpupillary distance used for stereo, in meters. Default is 0.064m (64 mm).
  72.195     void        SetIPD(float ipd)               { InterpupillaryDistance = ipd; IPDOverride = DirtyFlag = true; }
  72.196     float       GetIPD() const                  { return InterpupillaryDistance; }
  72.197 
  72.198     // Set full render target viewport; for HMD this includes both eyes. 
  72.199     void        SetFullViewport(const Viewport& vp);
  72.200     const Viewport& GetFullViewport() const     { return FullView; }
  72.201 
  72.202     // Aspect ratio defaults to ((w/h)*multiplier) computed per eye.
  72.203     // Aspect multiplier allows adjusting aspect ratio consistently for Stereo/NoStereo.
  72.204     void        SetAspectMultiplier(float m)    { AspectMultiplier = m; DirtyFlag = true; }
  72.205     float       GetAspectMultiplier() const     { return AspectMultiplier; }
  72.206 
  72.207     
  72.208     // For the distorted image to fill rendered viewport, input texture render target needs to be
  72.209     // scaled by DistortionScale before sampling. The scale factor is computed by fitting a point
  72.210     // on of specified radius from a distortion center, more easily specified as a coordinate.
  72.211     // SetDistortionFitPointVP sets the (x,y) coordinate of the point that scale will be "fit" to,
  72.212     // assuming [-1,1] coordinate range for full left-eye viewport. A fit point is a location
  72.213     // where source (pre-distortion) and target (post-distortion) image match each other.
  72.214     // For the right eye, the interpretation of 'u' will be inverted.  
  72.215     void       SetDistortionFitPointVP(float x, float y);
  72.216     // SetDistortionFitPointPixels sets the (x,y) coordinate of the point that scale will be "fit" to,
  72.217     // specified in pixeld for full left-eye texture.
  72.218     void       SetDistortionFitPointPixels(float x, float y);
  72.219 
  72.220     // Changes all distortion settings.
  72.221     // Note that setting HMDInfo also changes Distortion coefficients.
  72.222     void        SetDistortionConfig(const DistortionConfig& d) { Distortion = d; DirtyFlag = true; }
  72.223     
  72.224     // Modify distortion coefficients; useful for adjustment tweaking.
  72.225     void        SetDistortionK(int i, float k)  { Distortion.K[i] = k; DirtyFlag = true; }
  72.226     float       GetDistortionK(int i) const     { return Distortion.K[i]; }
  72.227 
  72.228     // Sets the fieldOfView that the 2D coordinate area stretches to.
  72.229     void        Set2DAreaFov(float fovRadians);
  72.230 
  72.231 
  72.232     // *** Computed State
  72.233 
  72.234     // Return current aspect ratio.
  72.235     float      GetAspect()                      { updateIfDirty(); return Aspect; }
  72.236     
  72.237     // Return computed vertical FOV in radians/degrees.
  72.238     float      GetYFOVRadians()                 { updateIfDirty(); return YFov; }
  72.239     float      GetYFOVDegrees()                 { return RadToDegree(GetYFOVRadians()); }
  72.240 
  72.241     // Query horizontal projection center offset as a distance away from the
  72.242     // one-eye [-1,1] unit viewport.
  72.243     // Positive return value should be used for left eye, negative for right eye. 
  72.244     float      GetProjectionCenterOffset()      { updateIfDirty(); return ProjectionCenterOffset; }
  72.245 
  72.246     // GetDistortionConfig isn't const because XCenterOffset bay need to be recomputed.  
  72.247     const DistortionConfig& GetDistortionConfig() { updateIfDirty(); return Distortion; }
  72.248 
  72.249     // Returns DistortionScale factor by which input texture size is increased to make
  72.250     // post-distortion result distortion fit the viewport.
  72.251     float      GetDistortionScale()             { updateIfDirty(); return Distortion.Scale; }
  72.252 
  72.253     // Returns the size of a pixel within 2D coordinate system.
  72.254     float      Get2DUnitPixel()                 { updateIfDirty();  return (2.0f / (FovPixels * Distortion.Scale)); }
  72.255 
  72.256     // Returns full set of Stereo rendering parameters for the specified eye.
  72.257     const StereoEyeParams& GetEyeRenderParams(StereoEye eye);
  72.258    
  72.259 private:    
  72.260 
  72.261     void updateIfDirty()   { if (DirtyFlag) updateComputedState(); }
  72.262     void updateComputedState();
  72.263 
  72.264     void updateDistortionOffsetAndScale();
  72.265     void updateProjectionOffset();
  72.266     void update2D();
  72.267     void updateEyeParams();
  72.268 
  72.269 
  72.270     // *** Modifiable State
  72.271 
  72.272     StereoMode         Mode;
  72.273     float              InterpupillaryDistance;
  72.274     float              AspectMultiplier;               // Multiplied into aspect ratio to change it.
  72.275     HMDInfo            HMD;
  72.276     DistortionConfig   Distortion;
  72.277     float              DistortionFitX, DistortionFitY; // In [-1,1] half-screen viewport units.
  72.278     Viewport           FullView;                       // Entire window viewport.
  72.279 
  72.280     float              Area2DFov;                      // FOV range mapping to [-1, 1] 2D area.
  72.281  
  72.282     // *** Computed State
  72.283  
  72.284     bool               DirtyFlag;   // Set when any if the modifiable state changed.
  72.285     bool               IPDOverride; // True after SetIPD was called.    
  72.286     float              YFov;        // Vertical FOV.
  72.287     float              Aspect;      // Aspect ratio: (w/h)*AspectMultiplier.
  72.288     float              ProjectionCenterOffset;
  72.289     StereoEyeParams    EyeRenderParams[2];
  72.290 
  72.291   
  72.292     // ** 2D Rendering
  72.293 
  72.294     // Number of 2D pixels in the FOV. This defines [-1,1] coordinate range for 2D.  
  72.295     float              FovPixels;
  72.296     Matrix4f           OrthoCenter;
  72.297     float              OrthoPixelOffset;
  72.298 };
  72.299 
  72.300 
  72.301 }}}  // OVR::Util::Render
  72.302 
  72.303 #endif
  72.304 \ No newline at end of file
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/libovr/Src/linux/OVR_Linux_DeviceManager.cpp	Sat Sep 14 16:14:59 2013 +0300
    73.3 @@ -0,0 +1,319 @@
    73.4 +/************************************************************************************
    73.5 +
    73.6 +Filename    :   OVR_Linux_DeviceManager.h
    73.7 +Content     :   Linux implementation of DeviceManager.
    73.8 +Created     :   
    73.9 +Authors     :   
   73.10 +
   73.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   73.12 +
   73.13 +Use of this software is subject to the terms of the Oculus license
   73.14 +agreement provided at the time of installation or download, or which
   73.15 +otherwise accompanies this software in either electronic or hard copy form.
   73.16 +
   73.17 +*************************************************************************************/
   73.18 +
   73.19 +#include "OVR_Linux_DeviceManager.h"
   73.20 +
   73.21 +// Sensor & HMD Factories
   73.22 +#include "OVR_LatencyTestImpl.h"
   73.23 +#include "OVR_SensorImpl.h"
   73.24 +#include "OVR_Linux_HIDDevice.h"
   73.25 +#include "OVR_Linux_HMDDevice.h"
   73.26 +
   73.27 +#include "Kernel/OVR_Timer.h"
   73.28 +#include "Kernel/OVR_Std.h"
   73.29 +#include "Kernel/OVR_Log.h"
   73.30 +
   73.31 +namespace OVR { namespace Linux {
   73.32 +
   73.33 +
   73.34 +//-------------------------------------------------------------------------------------
   73.35 +// **** Linux::DeviceManager
   73.36 +
   73.37 +DeviceManager::DeviceManager()
   73.38 +{
   73.39 +}
   73.40 +
   73.41 +DeviceManager::~DeviceManager()
   73.42 +{    
   73.43 +}
   73.44 +
   73.45 +bool DeviceManager::Initialize(DeviceBase*)
   73.46 +{
   73.47 +    if (!DeviceManagerImpl::Initialize(0))
   73.48 +        return false;
   73.49 +
   73.50 +    pThread = *new DeviceManagerThread();
   73.51 +    if (!pThread || !pThread->Start())
   73.52 +        return false;
   73.53 +
   73.54 +    // Wait for the thread to be fully up and running.
   73.55 +    pThread->StartupEvent.Wait();
   73.56 +
   73.57 +    // Do this now that we know the thread's run loop.
   73.58 +    HidDeviceManager = *HIDDeviceManager::CreateInternal(this);
   73.59 +         
   73.60 +    pCreateDesc->pDevice = this;
   73.61 +    LogText("OVR::DeviceManager - initialized.\n");
   73.62 +    return true;
   73.63 +}
   73.64 +
   73.65 +void DeviceManager::Shutdown()
   73.66 +{   
   73.67 +    LogText("OVR::DeviceManager - shutting down.\n");
   73.68 +
   73.69 +    // Set Manager shutdown marker variable; this prevents
   73.70 +    // any existing DeviceHandle objects from accessing device.
   73.71 +    pCreateDesc->pLock->pManager = 0;
   73.72 +
   73.73 +    // Push for thread shutdown *WITH NO WAIT*.
   73.74 +    // This will have the following effect:
   73.75 +    //  - Exit command will get enqueued, which will be executed later on the thread itself.
   73.76 +    //  - Beyond this point, this DeviceManager object may be deleted by our caller.
   73.77 +    //  - Other commands, such as CreateDevice, may execute before ExitCommand, but they will
   73.78 +    //    fail gracefully due to pLock->pManager == 0. Future commands can't be enqued
   73.79 +    //    after pManager is null.
   73.80 +    //  - Once ExitCommand executes, ThreadCommand::Run loop will exit and release the last
   73.81 +    //    reference to the thread object.
   73.82 +    pThread->PushExitCommand(false);
   73.83 +    pThread.Clear();
   73.84 +
   73.85 +    DeviceManagerImpl::Shutdown();
   73.86 +}
   73.87 +
   73.88 +ThreadCommandQueue* DeviceManager::GetThreadQueue()
   73.89 +{
   73.90 +    return pThread;
   73.91 +}
   73.92 +
   73.93 +ThreadId DeviceManager::GetThreadId() const
   73.94 +{
   73.95 +    return pThread->GetThreadId();
   73.96 +}
   73.97 +
   73.98 +bool DeviceManager::GetDeviceInfo(DeviceInfo* info) const
   73.99 +{
  73.100 +    if ((info->InfoClassType != Device_Manager) &&
  73.101 +        (info->InfoClassType != Device_None))
  73.102 +        return false;
  73.103 +    
  73.104 +    info->Type    = Device_Manager;
  73.105 +    info->Version = 0;
  73.106 +    OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength, "DeviceManager");
  73.107 +    OVR_strcpy(info->Manufacturer,DeviceInfo::MaxNameLength, "Oculus VR, Inc.");        
  73.108 +    return true;
  73.109 +}
  73.110 +
  73.111 +DeviceEnumerator<> DeviceManager::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
  73.112 +{
  73.113 +    // TBD: Can this be avoided in the future, once proper device notification is in place?
  73.114 +    pThread->PushCall((DeviceManagerImpl*)this,
  73.115 +                      &DeviceManager::EnumerateAllFactoryDevices, true);
  73.116 +
  73.117 +    return DeviceManagerImpl::EnumerateDevicesEx(args);
  73.118 +}
  73.119 +
  73.120 +
  73.121 +//-------------------------------------------------------------------------------------
  73.122 +// ***** DeviceManager Thread 
  73.123 +
  73.124 +DeviceManagerThread::DeviceManagerThread()
  73.125 +    : Thread(ThreadStackSize)
  73.126 +{
  73.127 +    int result = pipe(CommandFd);
  73.128 +    OVR_ASSERT(!result);
  73.129 +
  73.130 +    AddSelectFd(NULL, CommandFd[0]);
  73.131 +}
  73.132 +
  73.133 +DeviceManagerThread::~DeviceManagerThread()
  73.134 +{
  73.135 +    if (CommandFd[0])
  73.136 +    {
  73.137 +        RemoveSelectFd(NULL, CommandFd[0]);
  73.138 +        close(CommandFd[0]);
  73.139 +        close(CommandFd[1]);
  73.140 +    }
  73.141 +}
  73.142 +
  73.143 +bool DeviceManagerThread::AddSelectFd(Notifier* notify, int fd)
  73.144 +{
  73.145 +    struct pollfd pfd;
  73.146 +    pfd.fd = fd;
  73.147 +    pfd.events = POLLIN|POLLHUP|POLLERR;
  73.148 +    pfd.revents = 0;
  73.149 +
  73.150 +    FdNotifiers.PushBack(notify);
  73.151 +    PollFds.PushBack(pfd);
  73.152 +
  73.153 +    OVR_ASSERT(FdNotifiers.GetSize() == PollFds.GetSize());
  73.154 +    return true;
  73.155 +}
  73.156 +
  73.157 +bool DeviceManagerThread::RemoveSelectFd(Notifier* notify, int fd)
  73.158 +{
  73.159 +    // [0] is reserved for thread commands with notify of null, but we still
  73.160 +    // can use this function to remove it.
  73.161 +    for (UPInt i = 0; i < FdNotifiers.GetSize(); i++)
  73.162 +    {
  73.163 +        if ((FdNotifiers[i] == notify) && (PollFds[i].fd == fd))
  73.164 +        {
  73.165 +            FdNotifiers.RemoveAt(i);
  73.166 +            PollFds.RemoveAt(i);
  73.167 +            return true;
  73.168 +        }
  73.169 +    }
  73.170 +    return false;
  73.171 +}
  73.172 +
  73.173 +
  73.174 +
  73.175 +int DeviceManagerThread::Run()
  73.176 +{
  73.177 +    ThreadCommand::PopBuffer command;
  73.178 +
  73.179 +    SetThreadName("OVR::DeviceManagerThread");
  73.180 +    LogText("OVR::DeviceManagerThread - running (ThreadId=%p).\n", GetThreadId());
  73.181 +    
  73.182 +    // Signal to the parent thread that initialization has finished.
  73.183 +    StartupEvent.SetEvent();
  73.184 +
  73.185 +    while(!IsExiting())
  73.186 +    {
  73.187 +        // PopCommand will reset event on empty queue.
  73.188 +        if (PopCommand(&command))
  73.189 +        {
  73.190 +            command.Execute();
  73.191 +        }
  73.192 +        else
  73.193 +        {
  73.194 +            bool commands = 0;
  73.195 +            do
  73.196 +            {
  73.197 +                int waitMs = -1;
  73.198 +
  73.199 +                // If devices have time-dependent logic registered, get the longest wait
  73.200 +                // allowed based on current ticks.
  73.201 +                if (!TicksNotifiers.IsEmpty())
  73.202 +                {
  73.203 +                    UInt64 ticksMks = Timer::GetTicks();
  73.204 +                    int  waitAllowed;
  73.205 +
  73.206 +                    for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++)
  73.207 +                    {
  73.208 +                        waitAllowed = (int)(TicksNotifiers[j]->OnTicks(ticksMks) / Timer::MksPerMs);
  73.209 +                        if (waitAllowed < waitMs)
  73.210 +                            waitMs = waitAllowed;
  73.211 +                    }
  73.212 +                }
  73.213 +
  73.214 +                // wait until there is data available on one of the devices or the timeout expires
  73.215 +                int n = poll(&PollFds[0], PollFds.GetSize(), waitMs);
  73.216 +
  73.217 +                if (n > 0)
  73.218 +                {
  73.219 +                    // Iterate backwards through the list so the ordering will not be
  73.220 +                    // affected if the called object gets removed during the callback
  73.221 +                    // Also, the HID data streams are located toward the back of the list
  73.222 +                    // and servicing them first will allow a disconnect to be handled
  73.223 +                    // and cleaned directly at the device first instead of the general HID monitor
  73.224 +                    for (int i=PollFds.GetSize()-1; i>=0; i--)
  73.225 +                    {
  73.226 +                        if (PollFds[i].revents & POLLERR)
  73.227 +                        {
  73.228 +                            OVR_DEBUG_LOG(("poll: error on [%d]: %d", i, PollFds[i].fd));
  73.229 +                        }
  73.230 +                        else if (PollFds[i].revents & POLLIN)
  73.231 +                        {
  73.232 +                            if (FdNotifiers[i])
  73.233 +                                FdNotifiers[i]->OnEvent(i, PollFds[i].fd);
  73.234 +                            else if (i == 0) // command
  73.235 +                            {
  73.236 +                                char dummy[128];
  73.237 +                                read(PollFds[i].fd, dummy, 128);
  73.238 +                                commands = 1;
  73.239 +                            }
  73.240 +                        }
  73.241 +
  73.242 +                        if (PollFds[i].revents & POLLHUP)
  73.243 +                            PollFds[i].events = 0;
  73.244 +
  73.245 +                        if (PollFds[i].revents != 0)
  73.246 +                        {
  73.247 +                            n--;
  73.248 +                            if (n == 0)
  73.249 +                                break;
  73.250 +                        }
  73.251 +                    }
  73.252 +                }
  73.253 +            } while (PollFds.GetSize() > 0 && !commands);
  73.254 +        }
  73.255 +    }
  73.256 +
  73.257 +    LogText("OVR::DeviceManagerThread - exiting (ThreadId=%p).\n", GetThreadId());
  73.258 +    return 0;
  73.259 +}
  73.260 +
  73.261 +bool DeviceManagerThread::AddTicksNotifier(Notifier* notify)
  73.262 +{
  73.263 +     TicksNotifiers.PushBack(notify);
  73.264 +     return true;
  73.265 +}
  73.266 +
  73.267 +bool DeviceManagerThread::RemoveTicksNotifier(Notifier* notify)
  73.268 +{
  73.269 +    for (UPInt i = 0; i < TicksNotifiers.GetSize(); i++)
  73.270 +    {
  73.271 +        if (TicksNotifiers[i] == notify)
  73.272 +        {
  73.273 +            TicksNotifiers.RemoveAt(i);
  73.274 +            return true;
  73.275 +        }
  73.276 +    }
  73.277 +    return false;
  73.278 +}
  73.279 +
  73.280 +} // namespace Linux
  73.281 +
  73.282 +
  73.283 +//-------------------------------------------------------------------------------------
  73.284 +// ***** Creation
  73.285 +
  73.286 +
  73.287 +// Creates a new DeviceManager and initializes OVR.
  73.288 +DeviceManager* DeviceManager::Create()
  73.289 +{
  73.290 +    if (!System::IsInitialized())
  73.291 +    {
  73.292 +        // Use custom message, since Log is not yet installed.
  73.293 +        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
  73.294 +            LogMessage(Log_Debug, "DeviceManager::Create failed - OVR::System not initialized"); );
  73.295 +        return 0;
  73.296 +    }
  73.297 +
  73.298 +    Ptr<Linux::DeviceManager> manager = *new Linux::DeviceManager;
  73.299 +
  73.300 +    if (manager)
  73.301 +    {
  73.302 +        if (manager->Initialize(0))
  73.303 +        {            
  73.304 +            manager->AddFactory(&LatencyTestDeviceFactory::Instance);
  73.305 +            manager->AddFactory(&SensorDeviceFactory::Instance);
  73.306 +            manager->AddFactory(&Linux::HMDDeviceFactory::Instance);
  73.307 +
  73.308 +            manager->AddRef();
  73.309 +        }
  73.310 +        else
  73.311 +        {
  73.312 +            manager.Clear();
  73.313 +        }
  73.314 +
  73.315 +    }    
  73.316 +
  73.317 +    return manager.GetPtr();
  73.318 +}
  73.319 +
  73.320 +
  73.321 +} // namespace OVR
  73.322 +
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/libovr/Src/linux/OVR_Linux_DeviceManager.h	Sat Sep 14 16:14:59 2013 +0300
    74.3 @@ -0,0 +1,111 @@
    74.4 +/************************************************************************************
    74.5 +
    74.6 +Filename    :   OVR_Linux_DeviceManager.h
    74.7 +Content     :   Linux-specific DeviceManager header.
    74.8 +Created     :   
    74.9 +Authors     :   
   74.10 +
   74.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   74.12 +
   74.13 +Use of this software is subject to the terms of the Oculus license
   74.14 +agreement provided at the time of installation or download, or which
   74.15 +otherwise accompanies this software in either electronic or hard copy form.
   74.16 +
   74.17 +*************************************************************************************/
   74.18 +
   74.19 +#ifndef OVR_Linux_DeviceManager_h
   74.20 +#define OVR_Linux_DeviceManager_h
   74.21 +
   74.22 +#include "OVR_DeviceImpl.h"
   74.23 +
   74.24 +#include <unistd.h>
   74.25 +#include <sys/poll.h>
   74.26 +
   74.27 +
   74.28 +namespace OVR { namespace Linux {
   74.29 +
   74.30 +class DeviceManagerThread;
   74.31 +
   74.32 +//-------------------------------------------------------------------------------------
   74.33 +// ***** Linux DeviceManager
   74.34 +
   74.35 +class DeviceManager : public DeviceManagerImpl
   74.36 +{
   74.37 +public:
   74.38 +    DeviceManager();
   74.39 +    ~DeviceManager();
   74.40 +
   74.41 +    // Initialize/Shutdowncreate and shutdown manger thread.
   74.42 +    virtual bool Initialize(DeviceBase* parent);
   74.43 +    virtual void Shutdown();
   74.44 +
   74.45 +    virtual ThreadCommandQueue* GetThreadQueue();
   74.46 +    virtual ThreadId GetThreadId() const;
   74.47 +
   74.48 +    virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args);    
   74.49 +
   74.50 +    virtual bool  GetDeviceInfo(DeviceInfo* info) const;
   74.51 +
   74.52 +    Ptr<DeviceManagerThread> pThread;
   74.53 +};
   74.54 +
   74.55 +//-------------------------------------------------------------------------------------
   74.56 +// ***** Device Manager Background Thread
   74.57 +
   74.58 +class DeviceManagerThread : public Thread, public ThreadCommandQueue
   74.59 +{
   74.60 +    friend class DeviceManager;
   74.61 +    enum { ThreadStackSize = 64 * 1024 };
   74.62 +public:
   74.63 +    DeviceManagerThread();
   74.64 +    ~DeviceManagerThread();
   74.65 +
   74.66 +    virtual int Run();
   74.67 +
   74.68 +    // ThreadCommandQueue notifications for CommandEvent handling.
   74.69 +    virtual void OnPushNonEmpty_Locked() { write(CommandFd[1], this, 1); }
   74.70 +    virtual void OnPopEmpty_Locked()     { }
   74.71 +
   74.72 +    class Notifier
   74.73 +    {
   74.74 +    public:
   74.75 +        // Called when I/O is received
   74.76 +        virtual void OnEvent(int i, int fd) = 0;
   74.77 +
   74.78 +        // Called when timing ticks are updated.
   74.79 +        // Returns the largest number of microseconds this function can
   74.80 +        // wait till next call.
   74.81 +        virtual UInt64  OnTicks(UInt64 ticksMks)
   74.82 +        {
   74.83 +            OVR_UNUSED1(ticksMks);
   74.84 +            return Timer::MksPerSecond * 1000;
   74.85 +        }
   74.86 +    };
   74.87 +
   74.88 +    // Add I/O notifier
   74.89 +    bool AddSelectFd(Notifier* notify, int fd);
   74.90 +    bool RemoveSelectFd(Notifier* notify, int fd);
   74.91 +
   74.92 +    // Add notifier that will be called at regular intervals.
   74.93 +    bool AddTicksNotifier(Notifier* notify);
   74.94 +    bool RemoveTicksNotifier(Notifier* notify);
   74.95 +
   74.96 +private:
   74.97 +    
   74.98 +    bool threadInitialized() { return CommandFd[0] != 0; }
   74.99 +
  74.100 +    // pipe used to signal commands
  74.101 +    int CommandFd[2];
  74.102 +
  74.103 +    Array<struct pollfd>    PollFds;
  74.104 +    Array<Notifier*>        FdNotifiers;
  74.105 +
  74.106 +    Event                   StartupEvent;
  74.107 +
  74.108 +    // Ticks notifiers - used for time-dependent events such as keep-alive.
  74.109 +    Array<Notifier*>        TicksNotifiers;
  74.110 +};
  74.111 +
  74.112 +}} // namespace Linux::OVR
  74.113 +
  74.114 +#endif // OVR_Linux_DeviceManager_h
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/libovr/Src/linux/OVR_Linux_HIDDevice.cpp	Sat Sep 14 16:14:59 2013 +0300
    75.3 @@ -0,0 +1,799 @@
    75.4 +/************************************************************************************
    75.5 +Filename    :   OVR_Linux_HIDDevice.cpp
    75.6 +Content     :   Linux HID device implementation.
    75.7 +Created     :   February 26, 2013
    75.8 +Authors     :   Lee Cooper
    75.9 + 
   75.10 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   75.11 + 
   75.12 +Use of this software is subject to the terms of the Oculus license
   75.13 +agreement provided at the time of installation or download, or which
   75.14 +otherwise accompanies this software in either electronic or hard copy form.
   75.15 +
   75.16 +*************************************************************************************/
   75.17 +
   75.18 +#include "OVR_Linux_HIDDevice.h"
   75.19 +
   75.20 +#include <sys/ioctl.h>
   75.21 +#include <fcntl.h>
   75.22 +#include <errno.h>
   75.23 +#include <linux/hidraw.h>
   75.24 +#include "OVR_HIDDeviceImpl.h"
   75.25 +
   75.26 +namespace OVR { namespace Linux {
   75.27 +
   75.28 +static const UInt32 MAX_QUEUED_INPUT_REPORTS = 5;
   75.29 +    
   75.30 +//-------------------------------------------------------------------------------------
   75.31 +// **** Linux::DeviceManager
   75.32 +//-----------------------------------------------------------------------------
   75.33 +HIDDeviceManager::HIDDeviceManager(DeviceManager* manager) : DevManager(manager)
   75.34 +{
   75.35 +    UdevInstance = NULL;
   75.36 +    HIDMonitor = NULL;
   75.37 +    HIDMonHandle = -1;
   75.38 +}
   75.39 +
   75.40 +//-----------------------------------------------------------------------------
   75.41 +HIDDeviceManager::~HIDDeviceManager()
   75.42 +{
   75.43 +}
   75.44 +
   75.45 +//-----------------------------------------------------------------------------
   75.46 +bool HIDDeviceManager::initializeManager()
   75.47 +{
   75.48 +    if (HIDMonitor)
   75.49 +    {
   75.50 +        return true;
   75.51 +    }
   75.52 +
   75.53 +    // Create a udev_monitor handle to watch for device changes (hot-plug detection)
   75.54 +    HIDMonitor = udev_monitor_new_from_netlink(UdevInstance, "udev");
   75.55 +    if (HIDMonitor == NULL)
   75.56 +    {
   75.57 +        return false;
   75.58 +    }
   75.59 +
   75.60 +    udev_monitor_filter_add_match_subsystem_devtype(HIDMonitor, "hidraw", NULL);  // filter for hidraw only
   75.61 +	
   75.62 +    int err = udev_monitor_enable_receiving(HIDMonitor);
   75.63 +    if (err)
   75.64 +    {
   75.65 +        udev_monitor_unref(HIDMonitor);
   75.66 +        HIDMonitor = NULL;
   75.67 +        return false;
   75.68 +    }
   75.69 +	
   75.70 +    // Get the file descriptor (fd) for the monitor.  
   75.71 +    HIDMonHandle = udev_monitor_get_fd(HIDMonitor);
   75.72 +    if (HIDMonHandle < 0)
   75.73 +    {
   75.74 +        udev_monitor_unref(HIDMonitor);
   75.75 +        HIDMonitor = NULL;
   75.76 +        return false;
   75.77 +    }
   75.78 +
   75.79 +    // This file handle will be polled along-side with the device hid handles for changes
   75.80 +    // Add the handle to the polling list
   75.81 +    if (!DevManager->pThread->AddSelectFd(this, HIDMonHandle))
   75.82 +    {
   75.83 +        close(HIDMonHandle);
   75.84 +        HIDMonHandle = -1;
   75.85 +
   75.86 +        udev_monitor_unref(HIDMonitor);
   75.87 +        HIDMonitor = NULL;
   75.88 +        return false;
   75.89 +    }
   75.90 +
   75.91 +    return true;
   75.92 +}
   75.93 +
   75.94 +//-----------------------------------------------------------------------------
   75.95 +bool HIDDeviceManager::Initialize()
   75.96 +{
   75.97 +    // Get a udev library handle.  This handle must stay active during the
   75.98 +    // duration the lifetime of device monitoring handles
   75.99 +    UdevInstance = udev_new();
  75.100 +    if (!UdevInstance)
  75.101 +        return false;
  75.102 +
  75.103 +    return initializeManager();
  75.104 +}
  75.105 +
  75.106 +//-----------------------------------------------------------------------------
  75.107 +void HIDDeviceManager::Shutdown()
  75.108 +{
  75.109 +    OVR_ASSERT_LOG((UdevInstance), ("Should have called 'Initialize' before 'Shutdown'."));
  75.110 +
  75.111 +    if (HIDMonitor)
  75.112 +    {
  75.113 +        DevManager->pThread->RemoveSelectFd(this, HIDMonHandle);
  75.114 +        close(HIDMonHandle);
  75.115 +        HIDMonHandle = -1;
  75.116 +
  75.117 +        udev_monitor_unref(HIDMonitor);
  75.118 +        HIDMonitor = NULL;
  75.119 +    }
  75.120 +
  75.121 +    udev_unref(UdevInstance);  // release the library
  75.122 +    
  75.123 +    LogText("OVR::Linux::HIDDeviceManager - shutting down.\n");
  75.124 +}
  75.125 +
  75.126 +//-------------------------------------------------------------------------------
  75.127 +bool HIDDeviceManager::AddNotificationDevice(HIDDevice* device)
  75.128 +{
  75.129 +    NotificationDevices.PushBack(device);
  75.130 +    return true;
  75.131 +}
  75.132 +
  75.133 +//-------------------------------------------------------------------------------
  75.134 +bool HIDDeviceManager::RemoveNotificationDevice(HIDDevice* device)
  75.135 +{
  75.136 +    for (UPInt i = 0; i < NotificationDevices.GetSize(); i++)
  75.137 +    {
  75.138 +        if (NotificationDevices[i] == device)
  75.139 +        {
  75.140 +            NotificationDevices.RemoveAt(i);
  75.141 +            return true;
  75.142 +        }
  75.143 +    }
  75.144 +    return false;
  75.145 +}
  75.146 +
  75.147 +//-----------------------------------------------------------------------------
  75.148 +bool HIDDeviceManager::getIntProperty(udev_device* device,
  75.149 +                                      const char* propertyName,
  75.150 +                                      SInt32* pResult)
  75.151 +{
  75.152 +    const char* str = udev_device_get_sysattr_value(device, propertyName);
  75.153 +	if (str)
  75.154 +    {
  75.155 +        *pResult = strtol(str, NULL, 16);
  75.156 +        return true;
  75.157 +    }
  75.158 +    else
  75.159 +    {
  75.160 +        *pResult = 0;
  75.161 +        return true;
  75.162 +    }
  75.163 +}
  75.164 +
  75.165 +//-----------------------------------------------------------------------------
  75.166 +bool HIDDeviceManager::initVendorProductVersion(udev_device* device, HIDDeviceDesc* pDevDesc)
  75.167 +{
  75.168 +    SInt32 result;
  75.169 +    if (getIntProperty(device, "idVendor", &result))
  75.170 +        pDevDesc->VendorId = result;
  75.171 +    else
  75.172 +        return false;
  75.173 +
  75.174 +    if (getIntProperty(device, "idProduct", &result))
  75.175 +        pDevDesc->ProductId = result;
  75.176 +    else
  75.177 +        return false;
  75.178 +
  75.179 +    return true;
  75.180 +}
  75.181 +
  75.182 +//-----------------------------------------------------------------------------
  75.183 +bool HIDDeviceManager::getStringProperty(udev_device* device,
  75.184 +                                         const char* propertyName,
  75.185 +                                         OVR::String* pResult)
  75.186 +{
  75.187 +    // Get the attribute in UTF8
  75.188 +    const char* str = udev_device_get_sysattr_value(device, propertyName);
  75.189 +	if (str)
  75.190 +    {   // Copy the string into the return value
  75.191 +		*pResult = String(str);
  75.192 +        return true;
  75.193 +	}
  75.194 +    else
  75.195 +    {
  75.196 +        return false;
  75.197 +    }
  75.198 +}
  75.199 +
  75.200 +//-----------------------------------------------------------------------------
  75.201 +bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor)
  75.202 +{
  75.203 +    
  75.204 +    if (!initializeManager())
  75.205 +    {
  75.206 +        return false;
  75.207 +    }
  75.208 +
  75.209 +	// Get a list of hid devices
  75.210 +    udev_enumerate* devices = udev_enumerate_new(UdevInstance);
  75.211 +    udev_enumerate_add_match_subsystem(devices, "hidraw");
  75.212 +    udev_enumerate_scan_devices(devices);
  75.213 +
  75.214 +    udev_list_entry* entry = udev_enumerate_get_list_entry(devices);
  75.215 +
  75.216 +    // Search each device for the matching vid/pid
  75.217 +    while (entry != NULL)
  75.218 +    {
  75.219 +        // Get the device file name
  75.220 +        const char* sysfs_path = udev_list_entry_get_name(entry);
  75.221 +        udev_device* hid;  // The device's HID udev node.
  75.222 +        hid = udev_device_new_from_syspath(UdevInstance, sysfs_path);
  75.223 +        const char* dev_path = udev_device_get_devnode(hid);
  75.224 +
  75.225 +        // Get the USB device
  75.226 +        hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
  75.227 +        if (hid)
  75.228 +        {
  75.229 +            HIDDeviceDesc devDesc;
  75.230 +
  75.231 +            // Check the VID/PID for a match
  75.232 +            if (dev_path &&
  75.233 +                initVendorProductVersion(hid, &devDesc) &&
  75.234 +                enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId))
  75.235 +            {
  75.236 +                devDesc.Path = dev_path;
  75.237 +                getFullDesc(hid, &devDesc);
  75.238 +
  75.239 +                // Look for the device to check if it is already opened.
  75.240 +                Ptr<DeviceCreateDesc> existingDevice = DevManager->FindHIDDevice(devDesc);
  75.241 +                // if device exists and it is opened then most likely the device open()
  75.242 +                // will fail; therefore, we just set Enumerated to 'true' and continue.
  75.243 +                if (existingDevice && existingDevice->pDevice)
  75.244 +                {
  75.245 +                    existingDevice->Enumerated = true;
  75.246 +                }
  75.247 +                else
  75.248 +                {   // open the device temporarily for startup communication
  75.249 +                    int device_handle = open(dev_path, O_RDWR);
  75.250 +                    if (device_handle >= 0)
  75.251 +                    {
  75.252 +                        // Construct minimal device that the visitor callback can get feature reports from
  75.253 +                        Linux::HIDDevice device(this, device_handle);
  75.254 +                        enumVisitor->Visit(device, devDesc);
  75.255 +
  75.256 +                        close(device_handle);  // close the file handle
  75.257 +                    }
  75.258 +                }
  75.259 +            }
  75.260 +
  75.261 +            udev_device_unref(hid);
  75.262 +            entry = udev_list_entry_get_next(entry);
  75.263 +        }
  75.264 +    }
  75.265 +
  75.266 +	// Free the enumerator and udev objects
  75.267 +    udev_enumerate_unref(devices);
  75.268 +
  75.269 +    return true;
  75.270 +}
  75.271 +
  75.272 +//-----------------------------------------------------------------------------
  75.273 +OVR::HIDDevice* HIDDeviceManager::Open(const String& path)
  75.274 +{
  75.275 +    Ptr<Linux::HIDDevice> device = *new Linux::HIDDevice(this);
  75.276 +
  75.277 +    if (device->HIDInitialize(path))
  75.278 +    {
  75.279 +        device->AddRef();        
  75.280 +        return device;
  75.281 +    }
  75.282 +
  75.283 +    return NULL;
  75.284 +}
  75.285 +
  75.286 +//-----------------------------------------------------------------------------
  75.287 +bool HIDDeviceManager::getFullDesc(udev_device* device, HIDDeviceDesc* desc)
  75.288 +{
  75.289 +        
  75.290 +    if (!initVendorProductVersion(device, desc))
  75.291 +    {
  75.292 +        return false;
  75.293 +    }
  75.294 +        
  75.295 +    if (!getStringProperty(device, "serial", &(desc->SerialNumber)))
  75.296 +    {
  75.297 +        return false;
  75.298 +    }
  75.299 +    
  75.300 +    getStringProperty(device, "manufacturer", &(desc->Manufacturer));
  75.301 +    getStringProperty(device, "product", &(desc->Product));
  75.302 +        
  75.303 +    return true;
  75.304 +}
  75.305 +
  75.306 +//-----------------------------------------------------------------------------
  75.307 +bool HIDDeviceManager::GetDescriptorFromPath(const char* dev_path, HIDDeviceDesc* desc)
  75.308 +{
  75.309 +    if (!initializeManager())
  75.310 +    {
  75.311 +        return false;
  75.312 +    }
  75.313 +
  75.314 +    // Search for the udev device from the given pathname so we can
  75.315 +    // have a handle to query device properties
  75.316 +
  75.317 +    udev_enumerate* devices = udev_enumerate_new(UdevInstance);
  75.318 +    udev_enumerate_add_match_subsystem(devices, "hidraw");
  75.319 +    udev_enumerate_scan_devices(devices);
  75.320 +
  75.321 +    udev_list_entry* entry = udev_enumerate_get_list_entry(devices);
  75.322 +
  75.323 +    bool success = false;
  75.324 +    // Search for the device with the matching path
  75.325 +    while (entry != NULL)
  75.326 +    {
  75.327 +        // Get the device file name
  75.328 +        const char* sysfs_path = udev_list_entry_get_name(entry);
  75.329 +        udev_device* hid;  // The device's HID udev node.
  75.330 +        hid = udev_device_new_from_syspath(UdevInstance, sysfs_path);
  75.331 +        const char* path = udev_device_get_devnode(hid);
  75.332 +
  75.333 +        if (OVR_strcmp(dev_path, path) == 0)
  75.334 +        {   // Found the device so lets collect the device descriptor
  75.335 +
  75.336 +            // Get the USB device
  75.337 +            hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
  75.338 +            if (hid)
  75.339 +            {
  75.340 +                desc->Path = dev_path;
  75.341 +                success = getFullDesc(hid, desc);
  75.342 +            }
  75.343 +
  75.344 +        }
  75.345 +
  75.346 +        udev_device_unref(hid);
  75.347 +        entry = udev_list_entry_get_next(entry);
  75.348 +    }
  75.349 +
  75.350 +    // Free the enumerator
  75.351 +    udev_enumerate_unref(devices);
  75.352 +
  75.353 +    return success;
  75.354 +}
  75.355 +
  75.356 +//-----------------------------------------------------------------------------
  75.357 +void HIDDeviceManager::OnEvent(int i, int fd)
  75.358 +{
  75.359 +    // There is a device status change
  75.360 +    udev_device* hid = udev_monitor_receive_device(HIDMonitor);
  75.361 +    if (hid)
  75.362 +    {
  75.363 +        const char* dev_path = udev_device_get_devnode(hid);
  75.364 +        const char* action = udev_device_get_action(hid);
  75.365 +
  75.366 +        HIDDeviceDesc device_info;
  75.367 +        device_info.Path = dev_path;
  75.368 +
  75.369 +        MessageType notify_type;
  75.370 +        if (OVR_strcmp(action, "add") == 0)
  75.371 +        {
  75.372 +            notify_type = Message_DeviceAdded;
  75.373 +
  75.374 +            // Retrieve the device info.  This can only be done on a connected
  75.375 +            // device and is invalid for a disconnected device
  75.376 +
  75.377 +            // Get the USB device
  75.378 +            hid = udev_device_get_parent_with_subsystem_devtype(hid, "usb", "usb_device");
  75.379 +            if (!hid)
  75.380 +            {
  75.381 +                return;
  75.382 +            }
  75.383 +
  75.384 +            getFullDesc(hid, &device_info);
  75.385 +        }
  75.386 +        else if (OVR_strcmp(action, "remove") == 0)
  75.387 +        {
  75.388 +            notify_type = Message_DeviceRemoved;
  75.389 +        }
  75.390 +        else
  75.391 +        {
  75.392 +            return;
  75.393 +        }
  75.394 +
  75.395 +        bool error = false;
  75.396 +        bool deviceFound = false;
  75.397 +        for (UPInt i = 0; i < NotificationDevices.GetSize(); i++)
  75.398 +        {
  75.399 +            if (NotificationDevices[i] &&
  75.400 +                NotificationDevices[i]->OnDeviceNotification(notify_type, &device_info, &error))
  75.401 +            {
  75.402 +                // The notification was for an existing device
  75.403 +                deviceFound = true;
  75.404 +                break;
  75.405 +            }
  75.406 +        }
  75.407 +
  75.408 +        if (notify_type == Message_DeviceAdded && !deviceFound)
  75.409 +        {
  75.410 +            DevManager->DetectHIDDevice(device_info);
  75.411 +        }
  75.412 +
  75.413 +        udev_device_unref(hid);
  75.414 +    }
  75.415 +}
  75.416 +
  75.417 +//=============================================================================
  75.418 +//                           Linux::HIDDevice
  75.419 +//=============================================================================
  75.420 +HIDDevice::HIDDevice(HIDDeviceManager* manager)
  75.421 + :  HIDManager(manager), InMinimalMode(false)
  75.422 +{
  75.423 +    DeviceHandle = -1;
  75.424 +}
  75.425 +    
  75.426 +//-----------------------------------------------------------------------------
  75.427 +// This is a minimal constructor used during enumeration for us to pass
  75.428 +// a HIDDevice to the visit function (so that it can query feature reports).
  75.429 +HIDDevice::HIDDevice(HIDDeviceManager* manager, int device_handle)
  75.430 +:   HIDManager(manager), DeviceHandle(device_handle), InMinimalMode(true)
  75.431 +{
  75.432 +}
  75.433 +
  75.434 +//-----------------------------------------------------------------------------
  75.435 +HIDDevice::~HIDDevice()
  75.436 +{
  75.437 +    if (!InMinimalMode)
  75.438 +    {
  75.439 +        HIDShutdown();
  75.440 +    }
  75.441 +}
  75.442 +
  75.443 +//-----------------------------------------------------------------------------
  75.444 +bool HIDDevice::HIDInitialize(const String& path)
  75.445 +{
  75.446 +    const char* hid_path = path.ToCStr();
  75.447 +    if (!openDevice(hid_path))
  75.448 +    {
  75.449 +        LogText("OVR::Linux::HIDDevice - Failed to open HIDDevice: %s", hid_path);
  75.450 +        return false;
  75.451 +    }
  75.452 +    
  75.453 +    HIDManager->DevManager->pThread->AddTicksNotifier(this);
  75.454 +    HIDManager->AddNotificationDevice(this);
  75.455 +
  75.456 +    LogText("OVR::Linux::HIDDevice - Opened '%s'\n"
  75.457 +            "                    Manufacturer:'%s'  Product:'%s'  Serial#:'%s'\n",
  75.458 +            DevDesc.Path.ToCStr(),
  75.459 +            DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(),
  75.460 +            DevDesc.SerialNumber.ToCStr());
  75.461 +    
  75.462 +    return true;
  75.463 +}
  75.464 +
  75.465 +//-----------------------------------------------------------------------------
  75.466 +bool HIDDevice::initInfo()
  75.467 +{
  75.468 +    // Device must have been successfully opened.
  75.469 +    OVR_ASSERT(DeviceHandle >= 0);
  75.470 +
  75.471 +    int desc_size = 0;
  75.472 +    hidraw_report_descriptor rpt_desc;
  75.473 +    memset(&rpt_desc, 0, sizeof(rpt_desc));
  75.474 +
  75.475 +    // get report descriptor size
  75.476 +    int r = ioctl(DeviceHandle, HIDIOCGRDESCSIZE, &desc_size);
  75.477 +    if (r < 0)
  75.478 +    {
  75.479 +        OVR_ASSERT_LOG(false, ("Failed to get report descriptor size."));
  75.480 +        return false;
  75.481 +    }
  75.482 +
  75.483 +    // Get the report descriptor
  75.484 +    rpt_desc.size = desc_size;
  75.485 +    r = ioctl(DeviceHandle, HIDIOCGRDESC, &rpt_desc);
  75.486 +    if (r < 0)
  75.487 +    {
  75.488 +        OVR_ASSERT_LOG(false, ("Failed to get report descriptor."));
  75.489 +        return false;
  75.490 +    }
  75.491 +    
  75.492 +    /*
  75.493 +    // Get report lengths.
  75.494 +    SInt32 bufferLength;
  75.495 +    bool getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxInputReportSizeKey), &bufferLength);
  75.496 +    OVR_ASSERT(getResult);
  75.497 +    InputReportBufferLength = (UInt16) bufferLength;
  75.498 +
  75.499 +    getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxOutputReportSizeKey), &bufferLength);
  75.500 +    OVR_ASSERT(getResult);
  75.501 +    OutputReportBufferLength = (UInt16) bufferLength;
  75.502 +
  75.503 +    getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxFeatureReportSizeKey), &bufferLength);
  75.504 +    OVR_ASSERT(getResult);
  75.505 +    FeatureReportBufferLength = (UInt16) bufferLength;
  75.506 +    
  75.507 +    
  75.508 +    if (ReadBufferSize < InputReportBufferLength)
  75.509 +    {
  75.510 +        OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
  75.511 +        return false;
  75.512 +    }
  75.513 +    
  75.514 +    // Get device desc.
  75.515 +    if (!HIDManager->getFullDesc(Device, &DevDesc))
  75.516 +    {
  75.517 +        OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device."));
  75.518 +        return false;
  75.519 +    }
  75.520 +    
  75.521 +    return true;
  75.522 +    */
  75.523 +
  75.524 +    // Get report lengths.
  75.525 +// TODO: hard-coded for now.  Need to interpret these values from the report descriptor
  75.526 +    InputReportBufferLength = 62;
  75.527 +    OutputReportBufferLength = 0;
  75.528 +    FeatureReportBufferLength = 69;
  75.529 +    
  75.530 +    if (ReadBufferSize < InputReportBufferLength)
  75.531 +    {
  75.532 +        OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
  75.533 +        return false;
  75.534 +    }
  75.535 +      
  75.536 +    return true;
  75.537 +}
  75.538 +
  75.539 +//-----------------------------------------------------------------------------
  75.540 +bool HIDDevice::openDevice(const char* device_path)
  75.541 +{
  75.542 +    // First fill out the device descriptor
  75.543 +    if (!HIDManager->GetDescriptorFromPath(device_path, &DevDesc))
  75.544 +    {
  75.545 +        return false;
  75.546 +    }
  75.547 +
  75.548 +    // Now open the device
  75.549 +    DeviceHandle = open(device_path, O_RDWR);
  75.550 +    if (DeviceHandle < 0)
  75.551 +    {
  75.552 +        OVR_DEBUG_LOG(("Failed 'CreateHIDFile' while opening device, error = 0x%X.", errno));
  75.553 +        DeviceHandle = -1;
  75.554 +        return false;
  75.555 +    }
  75.556 +
  75.557 +    // fill out some values from the feature report descriptor
  75.558 +    if (!initInfo())
  75.559 +    {
  75.560 +        OVR_ASSERT_LOG(false, ("Failed to get HIDDevice info."));
  75.561 +
  75.562 +        close(DeviceHandle);
  75.563 +        DeviceHandle = -1;
  75.564 +        return false;
  75.565 +    }
  75.566 +
  75.567 +    // Add the device to the polling list
  75.568 +    if (!HIDManager->DevManager->pThread->AddSelectFd(this, DeviceHandle))
  75.569 +    {
  75.570 +        OVR_ASSERT_LOG(false, ("Failed to initialize polling for HIDDevice."));
  75.571 +
  75.572 +        close(DeviceHandle);
  75.573 +        DeviceHandle = -1;
  75.574 +        return false;
  75.575 +    }
  75.576 +    
  75.577 +    return true;
  75.578 +}
  75.579 +    
  75.580 +//-----------------------------------------------------------------------------
  75.581 +void HIDDevice::HIDShutdown()
  75.582 +{
  75.583 +
  75.584 +    HIDManager->DevManager->pThread->RemoveTicksNotifier(this);
  75.585 +    HIDManager->RemoveNotificationDevice(this);
  75.586 +    
  75.587 +    if (DeviceHandle >= 0) // Device may already have been closed if unplugged.
  75.588 +    {
  75.589 +        closeDevice(false);
  75.590 +    }
  75.591 +    
  75.592 +    LogText("OVR::Linux::HIDDevice - HIDShutdown '%s'\n", DevDesc.Path.ToCStr());
  75.593 +}
  75.594 +
  75.595 +//-----------------------------------------------------------------------------
  75.596 +void HIDDevice::closeDevice(bool wasUnplugged)
  75.597 +{
  75.598 +    OVR_ASSERT(DeviceHandle >= 0);
  75.599 +    
  75.600 +
  75.601 +    HIDManager->DevManager->pThread->RemoveSelectFd(this, DeviceHandle);
  75.602 +
  75.603 +    close(DeviceHandle);  // close the file handle
  75.604 +    DeviceHandle = -1;
  75.605 +        
  75.606 +    LogText("OVR::Linux::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr());
  75.607 +}
  75.608 +
  75.609 +//-----------------------------------------------------------------------------
  75.610 +void HIDDevice::closeDeviceOnIOError()
  75.611 +{
  75.612 +    LogText("OVR::Linux::HIDDevice - Lost connection to '%s'\n", DevDesc.Path.ToCStr());
  75.613 +    closeDevice(false);
  75.614 +}
  75.615 +
  75.616 +//-----------------------------------------------------------------------------
  75.617 +bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length)
  75.618 +{
  75.619 +    
  75.620 +    if (DeviceHandle < 0)
  75.621 +        return false;
  75.622 +    
  75.623 +    UByte reportID = data[0];
  75.624 +
  75.625 +    if (reportID == 0)
  75.626 +    {
  75.627 +        // Not using reports so remove from data packet.
  75.628 +        data++;
  75.629 +        length--;
  75.630 +    }
  75.631 +
  75.632 +    int r = ioctl(DeviceHandle, HIDIOCSFEATURE(length), data);
  75.633 +	return (r >= 0);
  75.634 +}
  75.635 +
  75.636 +//-----------------------------------------------------------------------------
  75.637 +bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length)
  75.638 +{
  75.639 +    if (DeviceHandle < 0)
  75.640 +        return false;
  75.641 +
  75.642 +	int r = ioctl(DeviceHandle, HIDIOCGFEATURE(length), data);
  75.643 +    return (r >= 0);
  75.644 +}
  75.645 +
  75.646 +//-----------------------------------------------------------------------------
  75.647 +UInt64 HIDDevice::OnTicks(UInt64 ticksMks)
  75.648 +{
  75.649 +    if (Handler)
  75.650 +    {
  75.651 +        return Handler->OnTicks(ticksMks);
  75.652 +    }
  75.653 +    
  75.654 +    return DeviceManagerThread::Notifier::OnTicks(ticksMks);
  75.655 +}
  75.656 +
  75.657 +//-----------------------------------------------------------------------------
  75.658 +void HIDDevice::OnEvent(int i, int fd)
  75.659 +{
  75.660 +    // We have data to read from the device
  75.661 +    int bytes = read(fd, ReadBuffer, ReadBufferSize);
  75.662 +    if (bytes >= 0)
  75.663 +    {
  75.664 +// TODO: I need to handle partial messages and package reconstruction
  75.665 +        if (Handler)
  75.666 +        {
  75.667 +            Handler->OnInputReport(ReadBuffer, bytes);
  75.668 +        }
  75.669 +    }
  75.670 +    else
  75.671 +    {   // Close the device on read error.
  75.672 +        closeDeviceOnIOError();
  75.673 +    }
  75.674 +}
  75.675 +
  75.676 +//-----------------------------------------------------------------------------
  75.677 +bool HIDDevice::OnDeviceNotification(MessageType messageType,
  75.678 +                                     HIDDeviceDesc* device_info,
  75.679 +                                     bool* error)
  75.680 +{
  75.681 +    const char* device_path = device_info->Path.ToCStr();
  75.682 +
  75.683 +    if (messageType == Message_DeviceAdded && DeviceHandle < 0)
  75.684 +    {
  75.685 +        // Is this the correct device?
  75.686 +        if (!(device_info->VendorId == DevDesc.VendorId
  75.687 +            && device_info->ProductId == DevDesc.ProductId
  75.688 +            && device_info->SerialNumber == DevDesc.SerialNumber))
  75.689 +        {
  75.690 +            return false;
  75.691 +        }
  75.692 +
  75.693 +        // A closed device has been re-added. Try to reopen.
  75.694 +        if (!openDevice(device_path))
  75.695 +        {
  75.696 +            LogError("OVR::Linux::HIDDevice - Failed to reopen a device '%s' that was re-added.\n", 
  75.697 +                     device_path);
  75.698 +            *error = true;
  75.699 +            return true;
  75.700 +        }
  75.701 +
  75.702 +        LogText("OVR::Linux::HIDDevice - Reopened device '%s'\n", device_path);
  75.703 +
  75.704 +        if (Handler)
  75.705 +        {
  75.706 +            Handler->OnDeviceMessage(HIDHandler::HIDDeviceMessage_DeviceAdded);
  75.707 +        }
  75.708 +    }
  75.709 +    else if (messageType == Message_DeviceRemoved)
  75.710 +    {
  75.711 +        // Is this the correct device?
  75.712 +        // For disconnected device, the device description will be invalid so
  75.713 +        // checking the path is the only way to match them
  75.714 +        if (DevDesc.Path.CompareNoCase(device_path) != 0)
  75.715 +        {
  75.716 +            return false;
  75.717 +        }
  75.718 +
  75.719 +        if (DeviceHandle >= 0)
  75.720 +        {
  75.721 +            closeDevice(true);
  75.722 +        }
  75.723 +
  75.724 +        if (Handler)
  75.725 +        {
  75.726 +            Handler->OnDeviceMessage(HIDHandler::HIDDeviceMessage_DeviceRemoved);
  75.727 +        }
  75.728 +    }
  75.729 +    else
  75.730 +    {
  75.731 +        OVR_ASSERT(0);
  75.732 +    }
  75.733 +
  75.734 +    *error = false;
  75.735 +    return true;
  75.736 +}
  75.737 +
  75.738 +//-----------------------------------------------------------------------------
  75.739 +HIDDeviceManager* HIDDeviceManager::CreateInternal(Linux::DeviceManager* devManager)
  75.740 +{
  75.741 +        
  75.742 +    if (!System::IsInitialized())
  75.743 +    {
  75.744 +        // Use custom message, since Log is not yet installed.
  75.745 +        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
  75.746 +                            LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
  75.747 +        return 0;
  75.748 +    }
  75.749 +
  75.750 +    Ptr<Linux::HIDDeviceManager> manager = *new Linux::HIDDeviceManager(devManager);
  75.751 +
  75.752 +    if (manager)
  75.753 +    {
  75.754 +        if (manager->Initialize())
  75.755 +        {
  75.756 +            manager->AddRef();
  75.757 +        }
  75.758 +        else
  75.759 +        {
  75.760 +            manager.Clear();
  75.761 +        }
  75.762 +    }
  75.763 +
  75.764 +    return manager.GetPtr();
  75.765 +}
  75.766 +    
  75.767 +} // namespace Linux
  75.768 +
  75.769 +//-------------------------------------------------------------------------------------
  75.770 +// ***** Creation
  75.771 +
  75.772 +// Creates a new HIDDeviceManager and initializes OVR.
  75.773 +HIDDeviceManager* HIDDeviceManager::Create()
  75.774 +{
  75.775 +    OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet."));
  75.776 +    
  75.777 +    if (!System::IsInitialized())
  75.778 +    {
  75.779 +        // Use custom message, since Log is not yet installed.
  75.780 +        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
  75.781 +            LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
  75.782 +        return 0;
  75.783 +    }
  75.784 +
  75.785 +    Ptr<Linux::HIDDeviceManager> manager = *new Linux::HIDDeviceManager(NULL);
  75.786 +
  75.787 +    if (manager)
  75.788 +    {
  75.789 +        if (manager->Initialize())
  75.790 +        {
  75.791 +            manager->AddRef();
  75.792 +        }
  75.793 +        else
  75.794 +        {
  75.795 +            manager.Clear();
  75.796 +        }
  75.797 +    }
  75.798 +
  75.799 +    return manager.GetPtr();
  75.800 +}
  75.801 +
  75.802 +} // namespace OVR
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/libovr/Src/linux/OVR_Linux_HIDDevice.h	Sat Sep 14 16:14:59 2013 +0300
    76.3 @@ -0,0 +1,124 @@
    76.4 +/************************************************************************************
    76.5 +Filename    :   OVR_Linux_HIDDevice.h
    76.6 +Content     :   Linux HID device implementation.
    76.7 +Created     :   June 13, 2013
    76.8 +Authors     :   Brant Lewis
    76.9 +
   76.10 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   76.11 +
   76.12 +Use of this software is subject to the terms of the Oculus license
   76.13 +agreement provided at the time of installation or download, or which
   76.14 +otherwise accompanies this software in either electronic or hard copy form.
   76.15 +
   76.16 +*************************************************************************************/
   76.17 +
   76.18 +#ifndef OVR_LINUX_HIDDevice_h
   76.19 +#define OVR_LINUX_HIDDevice_h
   76.20 +
   76.21 +#include "OVR_HIDDevice.h"
   76.22 +#include "OVR_Linux_DeviceManager.h"
   76.23 +#include <libudev.h>
   76.24 +
   76.25 +namespace OVR { namespace Linux {
   76.26 +
   76.27 +class HIDDeviceManager;
   76.28 +
   76.29 +//-------------------------------------------------------------------------------------
   76.30 +// ***** Linux HIDDevice
   76.31 +
   76.32 +class HIDDevice : public OVR::HIDDevice, public DeviceManagerThread::Notifier
   76.33 +{
   76.34 +private:
   76.35 +    friend class HIDDeviceManager;
   76.36 +
   76.37 +public:
   76.38 +    HIDDevice(HIDDeviceManager* manager);
   76.39 +
   76.40 +    // This is a minimal constructor used during enumeration for us to pass
   76.41 +    // a HIDDevice to the visit function (so that it can query feature reports).
   76.42 +    HIDDevice(HIDDeviceManager* manager, int device_handle);
   76.43 +    
   76.44 +    virtual ~HIDDevice();
   76.45 +
   76.46 +    bool HIDInitialize(const String& path);
   76.47 +    void HIDShutdown();
   76.48 +    
   76.49 +    virtual bool SetFeatureReport(UByte* data, UInt32 length);
   76.50 +	virtual bool GetFeatureReport(UByte* data, UInt32 length);
   76.51 +
   76.52 +    // DeviceManagerThread::Notifier
   76.53 +    void OnEvent(int i, int fd);
   76.54 +    UInt64 OnTicks(UInt64 ticksMks);
   76.55 +
   76.56 +    bool OnDeviceNotification(MessageType messageType,
   76.57 +                              HIDDeviceDesc* device_info,
   76.58 +                              bool* error);
   76.59 +
   76.60 +private:
   76.61 +    bool initInfo();
   76.62 +    bool openDevice(const char* dev_path);
   76.63 +    void closeDevice(bool wasUnplugged);
   76.64 +    void closeDeviceOnIOError();
   76.65 +    bool setupDevicePluggedInNotification();
   76.66 +
   76.67 +    bool                    InMinimalMode;
   76.68 +    HIDDeviceManager*       HIDManager;
   76.69 +    int                     DeviceHandle;     // file handle to the device
   76.70 +    HIDDeviceDesc           DevDesc;
   76.71 +    
   76.72 +    enum { ReadBufferSize = 96 };
   76.73 +    UByte                   ReadBuffer[ReadBufferSize];
   76.74 +
   76.75 +    UInt16                  InputReportBufferLength;
   76.76 +    UInt16                  OutputReportBufferLength;
   76.77 +    UInt16                  FeatureReportBufferLength;
   76.78 +};
   76.79 +
   76.80 +
   76.81 +//-------------------------------------------------------------------------------------
   76.82 +// ***** Linux HIDDeviceManager
   76.83 +
   76.84 +class HIDDeviceManager : public OVR::HIDDeviceManager, public DeviceManagerThread::Notifier
   76.85 +{
   76.86 +	friend class HIDDevice;
   76.87 +
   76.88 +public:
   76.89 +    HIDDeviceManager(Linux::DeviceManager* Manager);
   76.90 +    virtual ~HIDDeviceManager();
   76.91 +
   76.92 +    virtual bool Initialize();
   76.93 +    virtual void Shutdown();
   76.94 +
   76.95 +    virtual bool Enumerate(HIDEnumerateVisitor* enumVisitor);
   76.96 +    virtual OVR::HIDDevice* Open(const String& path);
   76.97 +
   76.98 +    static HIDDeviceManager* CreateInternal(DeviceManager* manager);
   76.99 +
  76.100 +    void OnEvent(int i, int fd);
  76.101 +    
  76.102 +private:
  76.103 +    bool initializeManager();
  76.104 +    bool initVendorProductVersion(udev_device* device, HIDDeviceDesc* pDevDesc);
  76.105 +    bool getPath(udev_device* device, String* pPath);
  76.106 +    bool getIntProperty(udev_device* device, const char* key, int32_t* pResult);
  76.107 +    bool getStringProperty(udev_device* device,
  76.108 +                           const char* propertyName,
  76.109 +                           OVR::String* pResult);
  76.110 +    bool getFullDesc(udev_device* device, HIDDeviceDesc* desc);
  76.111 +    bool GetDescriptorFromPath(const char* dev_path, HIDDeviceDesc* desc);
  76.112 +    
  76.113 +    bool AddNotificationDevice(HIDDevice* device);
  76.114 +    bool RemoveNotificationDevice(HIDDevice* device);
  76.115 +    
  76.116 +    DeviceManager*           DevManager;
  76.117 +
  76.118 +    udev*                    UdevInstance;     // a handle to the udev library instance
  76.119 +    udev_monitor*            HIDMonitor;
  76.120 +    int                      HIDMonHandle;     // the udev_monitor file handle
  76.121 +
  76.122 +    Array<HIDDevice*>        NotificationDevices;
  76.123 +};
  76.124 +
  76.125 +}} // namespace OVR::Linux
  76.126 +
  76.127 +#endif // OVR_Linux_HIDDevice_h
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/libovr/Src/linux/OVR_Linux_HMDDevice.cpp	Sat Sep 14 16:14:59 2013 +0300
    77.3 @@ -0,0 +1,392 @@
    77.4 +/************************************************************************************
    77.5 +
    77.6 +Filename    :   OVR_Linux_HMDDevice.h
    77.7 +Content     :   Linux HMDDevice implementation
    77.8 +Created     :   June 17, 2013
    77.9 +Authors     :   Brant Lewis
   77.10 +
   77.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   77.12 +
   77.13 +Use of this software is subject to the terms of the Oculus license
   77.14 +agreement provided at the time of installation or download, or which
   77.15 +otherwise accompanies this software in either electronic or hard copy form.
   77.16 +
   77.17 +*************************************************************************************/
   77.18 +
   77.19 +#include "OVR_Linux_HMDDevice.h"
   77.20 +
   77.21 +#include "OVR_Linux_DeviceManager.h"
   77.22 +
   77.23 +#include "OVR_Profile.h"
   77.24 +
   77.25 +#include <X11/Xlib.h>
   77.26 +#include <X11/extensions/Xinerama.h>
   77.27 +
   77.28 +namespace OVR { namespace Linux {
   77.29 +
   77.30 +//-------------------------------------------------------------------------------------
   77.31 +
   77.32 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory, const String& displayDeviceName, long dispId)
   77.33 +        : DeviceCreateDesc(factory, Device_HMD),
   77.34 +          DisplayDeviceName(displayDeviceName),
   77.35 +          DesktopX(0), DesktopY(0), Contents(0),
   77.36 +          HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0),
   77.37 +          DisplayId(dispId)
   77.38 +{
   77.39 +    DeviceId = DisplayDeviceName;
   77.40 +}
   77.41 +
   77.42 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other)
   77.43 +        : DeviceCreateDesc(other.pFactory, Device_HMD),
   77.44 +          DeviceId(other.DeviceId), DisplayDeviceName(other.DisplayDeviceName),
   77.45 +          DesktopX(other.DesktopX), DesktopY(other.DesktopY), Contents(other.Contents),
   77.46 +          HResolution(other.HResolution), VResolution(other.VResolution),
   77.47 +          HScreenSize(other.HScreenSize), VScreenSize(other.VScreenSize),
   77.48 +          DisplayId(other.DisplayId)
   77.49 +{
   77.50 +}
   77.51 +
   77.52 +HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCreateDesc& other,
   77.53 +                                                                  DeviceCreateDesc** pcandidate) const
   77.54 +{
   77.55 +    if ((other.Type != Device_HMD) || (other.pFactory != pFactory))
   77.56 +        return Match_None;
   77.57 +
   77.58 +    // There are several reasons we can come in here:
   77.59 +    //   a) Matching this HMD Monitor created desc to OTHER HMD Monitor desc
   77.60 +    //          - Require exact device DeviceId/DeviceName match
   77.61 +    //   b) Matching SensorDisplayInfo created desc to OTHER HMD Monitor desc
   77.62 +    //          - This DeviceId is empty; becomes candidate
   77.63 +    //   c) Matching this HMD Monitor created desc to SensorDisplayInfo desc
   77.64 +    //          - This other.DeviceId is empty; becomes candidate
   77.65 +
   77.66 +    const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
   77.67 +
   77.68 +    if ((DeviceId == s2.DeviceId) &&
   77.69 +        (DisplayId == s2.DisplayId))
   77.70 +    {
   77.71 +        // Non-null DeviceId may match while size is different if screen size was overwritten
   77.72 +        // by SensorDisplayInfo in prior iteration.
   77.73 +        if (!DeviceId.IsEmpty() ||
   77.74 +             ((HScreenSize == s2.HScreenSize) &&
   77.75 +              (VScreenSize == s2.VScreenSize)) )
   77.76 +        {            
   77.77 +            *pcandidate = 0;
   77.78 +            return Match_Found;
   77.79 +        }
   77.80 +    }
   77.81 +
   77.82 +
   77.83 +    // DisplayInfo takes precedence, although we try to match it first.
   77.84 +    if ((HResolution == s2.HResolution) &&
   77.85 +        (VResolution == s2.VResolution) &&
   77.86 +        (HScreenSize == s2.HScreenSize) &&
   77.87 +        (VScreenSize == s2.VScreenSize))
   77.88 +    {
   77.89 +        if (DeviceId.IsEmpty() && !s2.DeviceId.IsEmpty())
   77.90 +        {
   77.91 +            *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
   77.92 +            return Match_Candidate;
   77.93 +        }
   77.94 +
   77.95 +        *pcandidate = 0;
   77.96 +        return Match_Found;
   77.97 +    }
   77.98 +    
   77.99 +    // SensorDisplayInfo may override resolution settings, so store as candidate.
  77.100 +    if (s2.DeviceId.IsEmpty())
  77.101 +    {        
  77.102 +        *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
  77.103 +        return Match_Candidate;
  77.104 +    }
  77.105 +    // OTHER HMD Monitor desc may initialize DeviceName/Id
  77.106 +    else if (DeviceId.IsEmpty())
  77.107 +    {
  77.108 +        *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
  77.109 +        return Match_Candidate;
  77.110 +    }
  77.111 +    
  77.112 +    return Match_None;
  77.113 +}
  77.114 +
  77.115 +
  77.116 +bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, 
  77.117 +                                                 bool* newDeviceFlag)
  77.118 +{
  77.119 +    // This candidate was the the "best fit" to apply sensor DisplayInfo to.
  77.120 +    OVR_ASSERT(other.Type == Device_HMD);
  77.121 +    
  77.122 +    const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
  77.123 +
  77.124 +    // Force screen size on resolution from SensorDisplayInfo.
  77.125 +    // We do this because USB detection is more reliable as compared to HDMI EDID,
  77.126 +    // which may be corrupted by splitter reporting wrong monitor 
  77.127 +    if (s2.DeviceId.IsEmpty())
  77.128 +    {
  77.129 +        HScreenSize = s2.HScreenSize;
  77.130 +        VScreenSize = s2.VScreenSize;
  77.131 +        Contents |= Contents_Screen;
  77.132 +
  77.133 +        if (s2.Contents & HMDDeviceCreateDesc::Contents_Distortion)
  77.134 +        {
  77.135 +            memcpy(DistortionK, s2.DistortionK, sizeof(float)*4);
  77.136 +            Contents |= Contents_Distortion;
  77.137 +        }
  77.138 +        DeviceId          = s2.DeviceId;
  77.139 +        DisplayId         = s2.DisplayId;
  77.140 +        DisplayDeviceName = s2.DisplayDeviceName;
  77.141 +        if (newDeviceFlag) *newDeviceFlag = true;
  77.142 +    }
  77.143 +    else if (DeviceId.IsEmpty())
  77.144 +    {
  77.145 +        DeviceId          = s2.DeviceId;
  77.146 +        DisplayId         = s2.DisplayId;
  77.147 +        DisplayDeviceName = s2.DisplayDeviceName;
  77.148 +
  77.149 +		// ScreenSize and Resolution are NOT assigned here, since they may have
  77.150 +		// come from a sensor DisplayInfo (which has precedence over HDMI).
  77.151 +
  77.152 +        if (newDeviceFlag) *newDeviceFlag = true;
  77.153 +    }
  77.154 +    else
  77.155 +    {
  77.156 +        if (newDeviceFlag) *newDeviceFlag = false;
  77.157 +    }
  77.158 +
  77.159 +    return true;
  77.160 +}
  77.161 +
  77.162 +bool HMDDeviceCreateDesc::MatchDevice(const String& path)
  77.163 +{
  77.164 +    return DeviceId.CompareNoCase(path) == 0;
  77.165 +}
  77.166 +
  77.167 +//-------------------------------------------------------------------------------------
  77.168 +// ***** HMDDeviceFactory
  77.169 +
  77.170 +HMDDeviceFactory HMDDeviceFactory::Instance;
  77.171 +
  77.172 +void HMDDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
  77.173 +{
  77.174 +    // For now we'll assume the Rift DK1 is attached in extended monitor mode. Ultimately we need to
  77.175 +    // use XFree86 to enumerate X11 screens in case the Rift is attached as a separate screen. We also
  77.176 +    // need to be able to read the EDID manufacturer product code to be able to differentiate between
  77.177 +    // Rift models.
  77.178 +
  77.179 +    bool foundHMD = false;
  77.180 +
  77.181 +    Display* display = XOpenDisplay(NULL);
  77.182 +    if (display && XineramaIsActive(display))
  77.183 +    {
  77.184 +        int numberOfScreens;
  77.185 +        XineramaScreenInfo* screens = XineramaQueryScreens(display, &numberOfScreens);
  77.186 +
  77.187 +        for (int i = 0; i < numberOfScreens; i++)
  77.188 +        {
  77.189 +            XineramaScreenInfo screenInfo = screens[i];
  77.190 +
  77.191 +            if (screenInfo.width == 1280 && screenInfo.height == 800)
  77.192 +            {
  77.193 +                String deviceName = "OVR0001";
  77.194 +
  77.195 +                HMDDeviceCreateDesc hmdCreateDesc(this, deviceName, i);
  77.196 +                hmdCreateDesc.SetScreenParameters(screenInfo.x_org, screenInfo.y_org, 1280, 800, 0.14976f, 0.0936f);
  77.197 +
  77.198 +                OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %s - %d\n",
  77.199 +                                    deviceName.ToCStr(), i));
  77.200 +
  77.201 +                // Notify caller about detected device. This will call EnumerateAddDevice
  77.202 +                // if the this is the first time device was detected.
  77.203 +                visitor.Visit(hmdCreateDesc);
  77.204 +                foundHMD = true;
  77.205 +                break;
  77.206 +            }
  77.207 +        }
  77.208 +
  77.209 +        XFree(screens);
  77.210 +    }
  77.211 +
  77.212 +
  77.213 +    // Real HMD device is not found; however, we still may have a 'fake' HMD
  77.214 +    // device created via SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo.
  77.215 +    // Need to find it and set 'Enumerated' to true to avoid Removal notification.
  77.216 +    if (!foundHMD)
  77.217 +    {
  77.218 +        Ptr<DeviceCreateDesc> hmdDevDesc = getManager()->FindDevice("", Device_HMD);
  77.219 +        if (hmdDevDesc)
  77.220 +            hmdDevDesc->Enumerated = true;
  77.221 +    }
  77.222 +}
  77.223 +
  77.224 +DeviceBase* HMDDeviceCreateDesc::NewDeviceInstance()
  77.225 +{
  77.226 +    return new HMDDevice(this);
  77.227 +}
  77.228 +
  77.229 +bool HMDDeviceCreateDesc::Is7Inch() const
  77.230 +{
  77.231 +    return (strstr(DeviceId.ToCStr(), "OVR0001") != 0) || (Contents & Contents_7Inch);
  77.232 +}
  77.233 +
  77.234 +Profile* HMDDeviceCreateDesc::GetProfileAddRef() const
  77.235 +{
  77.236 +    // Create device may override profile name, so get it from there is possible.
  77.237 +    ProfileManager* profileManager = GetManagerImpl()->GetProfileManager();
  77.238 +    ProfileType     profileType    = GetProfileType();
  77.239 +    const char *    profileName    = pDevice ?
  77.240 +                        ((HMDDevice*)pDevice)->GetProfileName() :
  77.241 +                        profileManager->GetDefaultProfileName(profileType);
  77.242 +    
  77.243 +    return profileName ? 
  77.244 +        profileManager->LoadProfile(profileType, profileName) :
  77.245 +        profileManager->GetDeviceDefaultProfile(profileType);
  77.246 +}
  77.247 +
  77.248 +
  77.249 +bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
  77.250 +{
  77.251 +    if ((info->InfoClassType != Device_HMD) &&
  77.252 +        (info->InfoClassType != Device_None))
  77.253 +        return false;
  77.254 +
  77.255 +    bool is7Inch = Is7Inch();
  77.256 +
  77.257 +    OVR_strcpy(info->ProductName,  DeviceInfo::MaxNameLength,
  77.258 +               is7Inch ? "Oculus Rift DK1" :
  77.259 +			   ((HResolution >= 1920) ? "Oculus Rift DK HD" : "Oculus Rift DK1-Prototype") );
  77.260 +    OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, "Oculus VR");
  77.261 +    info->Type    = Device_HMD;
  77.262 +    info->Version = 0;
  77.263 +
  77.264 +    // Display detection.
  77.265 +    if (info->InfoClassType == Device_HMD)
  77.266 +    {
  77.267 +        HMDInfo* hmdInfo = static_cast<HMDInfo*>(info);
  77.268 +
  77.269 +        hmdInfo->DesktopX               = DesktopX;
  77.270 +        hmdInfo->DesktopY               = DesktopY;
  77.271 +        hmdInfo->HResolution            = HResolution;
  77.272 +        hmdInfo->VResolution            = VResolution;
  77.273 +        hmdInfo->HScreenSize            = HScreenSize;
  77.274 +        hmdInfo->VScreenSize            = VScreenSize;
  77.275 +        hmdInfo->VScreenCenter          = VScreenSize * 0.5f;
  77.276 +        hmdInfo->InterpupillaryDistance = 0.064f;  // Default IPD; should be configurable.
  77.277 +        hmdInfo->LensSeparationDistance = 0.0635f;
  77.278 +
  77.279 +        // Obtain IPD from profile.
  77.280 +        Ptr<Profile> profile = *GetProfileAddRef();
  77.281 +
  77.282 +        if (profile)
  77.283 +        {
  77.284 +            hmdInfo->InterpupillaryDistance = profile->GetIPD();
  77.285 +            // TBD: Switch on EyeCup type.
  77.286 +        }
  77.287 +
  77.288 +        if (Contents & Contents_Distortion)
  77.289 +        {
  77.290 +            memcpy(hmdInfo->DistortionK, DistortionK, sizeof(float)*4);
  77.291 +        }
  77.292 +        else
  77.293 +        {						
  77.294 +			if (is7Inch)
  77.295 +            {
  77.296 +                // 7" screen.
  77.297 +                hmdInfo->DistortionK[0]      = 1.0f;
  77.298 +                hmdInfo->DistortionK[1]      = 0.22f;
  77.299 +                hmdInfo->DistortionK[2]      = 0.24f;
  77.300 +                hmdInfo->EyeToScreenDistance = 0.041f;
  77.301 +            }
  77.302 +            else
  77.303 +            {
  77.304 +                hmdInfo->DistortionK[0]      = 1.0f;
  77.305 +                hmdInfo->DistortionK[1]      = 0.18f;
  77.306 +                hmdInfo->DistortionK[2]      = 0.115f;
  77.307 +
  77.308 +				if (HResolution == 1920)
  77.309 +					hmdInfo->EyeToScreenDistance = 0.040f;
  77.310 +				else
  77.311 +					hmdInfo->EyeToScreenDistance = 0.0387f;
  77.312 +            }
  77.313 +
  77.314 +			hmdInfo->ChromaAbCorrection[0] = 0.996f;
  77.315 +			hmdInfo->ChromaAbCorrection[1] = -0.004f;
  77.316 +			hmdInfo->ChromaAbCorrection[2] = 1.014f;
  77.317 +			hmdInfo->ChromaAbCorrection[3] = 0.0f;
  77.318 +        }
  77.319 +
  77.320 +        OVR_strcpy(hmdInfo->DisplayDeviceName, sizeof(hmdInfo->DisplayDeviceName),
  77.321 +                   DisplayDeviceName.ToCStr());
  77.322 +        hmdInfo->DisplayId = DisplayId;
  77.323 +    }
  77.324 +
  77.325 +    return true;
  77.326 +}
  77.327 +
  77.328 +//-------------------------------------------------------------------------------------
  77.329 +// ***** HMDDevice
  77.330 +
  77.331 +HMDDevice::HMDDevice(HMDDeviceCreateDesc* createDesc)
  77.332 +    : OVR::DeviceImpl<OVR::HMDDevice>(createDesc, 0)
  77.333 +{
  77.334 +}
  77.335 +HMDDevice::~HMDDevice()
  77.336 +{
  77.337 +}
  77.338 +
  77.339 +bool HMDDevice::Initialize(DeviceBase* parent)
  77.340 +{
  77.341 +    pParent = parent;
  77.342 +
  77.343 +    // Initialize user profile to default for device.
  77.344 +    ProfileManager* profileManager = GetManager()->GetProfileManager();    
  77.345 +    ProfileName = profileManager->GetDefaultProfileName(getDesc()->GetProfileType());
  77.346 +
  77.347 +    return true;
  77.348 +}
  77.349 +void HMDDevice::Shutdown()
  77.350 +{
  77.351 +    ProfileName.Clear();
  77.352 +    pCachedProfile.Clear();
  77.353 +    pParent.Clear();
  77.354 +}
  77.355 +
  77.356 +Profile* HMDDevice::GetProfile() const
  77.357 +{    
  77.358 +    if (!pCachedProfile)
  77.359 +        pCachedProfile = *getDesc()->GetProfileAddRef();
  77.360 +    return pCachedProfile.GetPtr();
  77.361 +}
  77.362 +
  77.363 +const char* HMDDevice::GetProfileName() const
  77.364 +{
  77.365 +    return ProfileName.ToCStr();
  77.366 +}
  77.367 +
  77.368 +bool HMDDevice::SetProfileName(const char* name)
  77.369 +{
  77.370 +    pCachedProfile.Clear();
  77.371 +    if (!name)
  77.372 +    {
  77.373 +        ProfileName.Clear();
  77.374 +        return 0;
  77.375 +    }
  77.376 +    if (GetManager()->GetProfileManager()->HasProfile(getDesc()->GetProfileType(), name))
  77.377 +    {
  77.378 +        ProfileName = name;
  77.379 +        return true;
  77.380 +    }
  77.381 +    return false;
  77.382 +}
  77.383 +
  77.384 +OVR::SensorDevice* HMDDevice::GetSensor()
  77.385 +{
  77.386 +    // Just return first sensor found since we have no way to match it yet.
  77.387 +    OVR::SensorDevice* sensor = GetManager()->EnumerateDevices<SensorDevice>().CreateDevice();
  77.388 +    if (sensor)
  77.389 +        sensor->SetCoordinateFrame(SensorDevice::Coord_HMD);
  77.390 +    return sensor;
  77.391 +}
  77.392 +
  77.393 +}} // namespace OVR::Linux
  77.394 +
  77.395 +
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/libovr/Src/linux/OVR_Linux_HMDDevice.h	Sat Sep 14 16:14:59 2013 +0300
    78.3 @@ -0,0 +1,156 @@
    78.4 +/************************************************************************************
    78.5 +
    78.6 +Filename    :   OVR_Linux_HMDDevice.h
    78.7 +Content     :   Linux HMDDevice implementation
    78.8 +Created     :   June 17, 2013
    78.9 +Authors     :   Brant Lewis
   78.10 +
   78.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   78.12 +
   78.13 +Use of this software is subject to the terms of the Oculus license
   78.14 +agreement provided at the time of installation or download, or which
   78.15 +otherwise accompanies this software in either electronic or hard copy form.
   78.16 +
   78.17 +*************************************************************************************/
   78.18 +
   78.19 +#ifndef OVR_Linux_HMDDevice_h
   78.20 +#define OVR_Linux_HMDDevice_h
   78.21 +
   78.22 +#include "OVR_Linux_DeviceManager.h"
   78.23 +#include "OVR_Profile.h"
   78.24 +
   78.25 +namespace OVR { namespace Linux {
   78.26 +
   78.27 +class HMDDevice;
   78.28 +
   78.29 +//-------------------------------------------------------------------------------------
   78.30 +
   78.31 +// HMDDeviceFactory enumerates attached Oculus HMD devices.
   78.32 +//
   78.33 +// This is currently done by matching monitor device strings.
   78.34 +
   78.35 +class HMDDeviceFactory : public DeviceFactory
   78.36 +{
   78.37 +public:
   78.38 +    static HMDDeviceFactory Instance;
   78.39 +
   78.40 +    // Enumerates devices, creating and destroying relevant objects in manager.
   78.41 +    virtual void EnumerateDevices(EnumerateVisitor& visitor);
   78.42 +
   78.43 +protected:
   78.44 +    DeviceManager* getManager() const { return (DeviceManager*) pManager; }
   78.45 +};
   78.46 +
   78.47 +
   78.48 +class HMDDeviceCreateDesc : public DeviceCreateDesc
   78.49 +{
   78.50 +    friend class HMDDevice;
   78.51 +
   78.52 +protected:
   78.53 +    enum
   78.54 +    {
   78.55 +        Contents_Screen     = 1,
   78.56 +        Contents_Distortion = 2,
   78.57 +        Contents_7Inch      = 4,
   78.58 +    };
   78.59 +    String      DeviceId;
   78.60 +    String      DisplayDeviceName;
   78.61 +    int         DesktopX, DesktopY;
   78.62 +    unsigned    Contents;
   78.63 +    unsigned    HResolution, VResolution;
   78.64 +    float       HScreenSize, VScreenSize;
   78.65 +    long        DisplayId;
   78.66 +    float       DistortionK[4];
   78.67 +
   78.68 +public:
   78.69 +    HMDDeviceCreateDesc(DeviceFactory* factory, const String& displayDeviceName, long dispId);
   78.70 +    HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other);
   78.71 +
   78.72 +    virtual DeviceCreateDesc* Clone() const
   78.73 +    {
   78.74 +        return new HMDDeviceCreateDesc(*this);
   78.75 +    }
   78.76 +
   78.77 +    virtual DeviceBase* NewDeviceInstance();
   78.78 +
   78.79 +    virtual MatchResult MatchDevice(const DeviceCreateDesc& other,
   78.80 +                                    DeviceCreateDesc**) const;
   78.81 +
   78.82 +    // Matches device by path.
   78.83 +    virtual bool MatchDevice(const String& path);
   78.84 +
   78.85 +    virtual bool UpdateMatchedCandidate(const DeviceCreateDesc&, bool* newDeviceFlag = NULL);
   78.86 +
   78.87 +    virtual bool GetDeviceInfo(DeviceInfo* info) const;
   78.88 +
   78.89 +    // Requests the currently used default profile. This profile affects the
   78.90 +    // settings reported by HMDInfo. 
   78.91 +    Profile* GetProfileAddRef() const;
   78.92 +
   78.93 +    ProfileType GetProfileType() const
   78.94 +    {
   78.95 +        return (HResolution >= 1920) ? Profile_RiftDKHD : Profile_RiftDK1;
   78.96 +    }
   78.97 +
   78.98 +
   78.99 +    void  SetScreenParameters(int x, int y, unsigned hres, unsigned vres, float hsize, float vsize)
  78.100 +    {
  78.101 +        DesktopX = x;
  78.102 +        DesktopY = y;
  78.103 +        HResolution = hres;
  78.104 +        VResolution = vres;
  78.105 +        HScreenSize = hsize;
  78.106 +        VScreenSize = vsize;
  78.107 +        Contents |= Contents_Screen;
  78.108 +    }
  78.109 +    void SetDistortion(const float* dks)
  78.110 +    {
  78.111 +        for (int i = 0; i < 4; i++)
  78.112 +            DistortionK[i] = dks[i];
  78.113 +        Contents |= Contents_Distortion;
  78.114 +    }
  78.115 +
  78.116 +    void Set7Inch() { Contents |= Contents_7Inch; }
  78.117 +
  78.118 +    bool Is7Inch() const;
  78.119 +};
  78.120 +
  78.121 +
  78.122 +//-------------------------------------------------------------------------------------
  78.123 +
  78.124 +// HMDDevice represents an Oculus HMD device unit. An instance of this class
  78.125 +// is typically created from the DeviceManager.
  78.126 +//  After HMD device is created, we its sensor data can be obtained by 
  78.127 +//  first creating a Sensor object and then wrappig it in SensorFusion.
  78.128 +
  78.129 +class HMDDevice : public DeviceImpl<OVR::HMDDevice>
  78.130 +{
  78.131 +public:
  78.132 +    HMDDevice(HMDDeviceCreateDesc* createDesc);
  78.133 +    ~HMDDevice();    
  78.134 +
  78.135 +    virtual bool Initialize(DeviceBase* parent);
  78.136 +    virtual void Shutdown();
  78.137 +
  78.138 +    // Requests the currently used default profile. This profile affects the
  78.139 +    // settings reported by HMDInfo. 
  78.140 +    virtual Profile*    GetProfile() const;
  78.141 +    virtual const char* GetProfileName() const;
  78.142 +    virtual bool        SetProfileName(const char* name);
  78.143 +
  78.144 +    // Query associated sensor.
  78.145 +    virtual OVR::SensorDevice* GetSensor();  
  78.146 +
  78.147 +protected:
  78.148 +    HMDDeviceCreateDesc* getDesc() const { return (HMDDeviceCreateDesc*)pCreateDesc.GetPtr(); }
  78.149 +
  78.150 +    // User name for the profile used with this device.
  78.151 +    String               ProfileName;
  78.152 +    mutable Ptr<Profile> pCachedProfile;
  78.153 +};
  78.154 +
  78.155 +
  78.156 +}} // namespace OVR::Linux
  78.157 +
  78.158 +#endif // OVR_Linux_HMDDevice_h
  78.159 +
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/libovr/Src/linux/OVR_Linux_SensorDevice.cpp	Sat Sep 14 16:14:59 2013 +0300
    79.3 @@ -0,0 +1,48 @@
    79.4 +/************************************************************************************
    79.5 +
    79.6 +Filename    :   OVR_Linux_SensorDevice.cpp
    79.7 +Content     :   Linux SensorDevice implementation
    79.8 +Created     :   June 13, 2013
    79.9 +Authors     :   Brant Lewis
   79.10 +
   79.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   79.12 +
   79.13 +Use of this software is subject to the terms of the Oculus license
   79.14 +agreement provided at the time of installation or download, or which
   79.15 +otherwise accompanies this software in either electronic or hard copy form.
   79.16 +
   79.17 +*************************************************************************************/
   79.18 +
   79.19 +//#include "OVR_OSX_HMDDevice.h"
   79.20 +#include "OVR_SensorImpl.h"
   79.21 +#include "OVR_DeviceImpl.h"
   79.22 +
   79.23 +namespace OVR { namespace OSX {
   79.24 +
   79.25 +} // namespace OSX
   79.26 +
   79.27 +//-------------------------------------------------------------------------------------
   79.28 +void SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(   const SensorDisplayInfoImpl& displayInfo, 
   79.29 +                                                            DeviceFactory::EnumerateVisitor& visitor)
   79.30 +{
   79.31 +/*
   79.32 +    Linux::HMDDeviceCreateDesc hmdCreateDesc(&Linux::HMDDeviceFactory::Instance, 1, 1, "", 0);
   79.33 +    
   79.34 +    hmdCreateDesc.SetScreenParameters(  0, 0,
   79.35 +                                        displayInfo.HResolution, displayInfo.VResolution,
   79.36 +                                        displayInfo.HScreenSize, displayInfo.VScreenSize);
   79.37 +
   79.38 +    if ((displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) == SensorDisplayInfoImpl::Base_Distortion)
   79.39 +        hmdCreateDesc.SetDistortion(displayInfo.DistortionK);
   79.40 +    if (displayInfo.HScreenSize > 0.14f)
   79.41 +        hmdCreateDesc.Set7Inch();
   79.42 +
   79.43 +    visitor.Visit(hmdCreateDesc);
   79.44 +    */
   79.45 +
   79.46 +
   79.47 +}
   79.48 +
   79.49 +} // namespace OVR
   79.50 +
   79.51 +
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/libovr/Src/linux/OVR_ThreadsPthread.cpp	Sat Sep 14 16:14:59 2013 +0300
    80.3 @@ -0,0 +1,1 @@
    80.4 +
    80.5 #include "OVR_Threads.h"
    80.6 #include "OVR_Hash.h"
    80.7 
    80.8 #ifdef OVR_ENABLE_THREADS
    80.9 
   80.10 #include "OVR_Timer.h"
   80.11 #include "OVR_Log.h"
   80.12 
   80.13 #include <pthread.h>
   80.14 #include <time.h>
   80.15 
   80.16 #ifdef OVR_OS_PS3
   80.17 #include <sys/sys_time.h>
   80.18 #include <sys/timer.h>
   80.19 #include <sys/synchronization.h>
   80.20 #define sleep(x) sys_timer_sleep(x)
   80.21 #define usleep(x) sys_timer_usleep(x)
   80.22 using std::timespec;
   80.23 #else
   80.24 #include <unistd.h>
   80.25 #include <sys/time.h>
   80.26 #include <errno.h>
   80.27 #endif
   80.28 
   80.29 namespace OVR {
   80.30 
   80.31 // ***** Mutex implementation
   80.32 
   80.33 
   80.34 // *** Internal Mutex implementation structure
   80.35 
   80.36 class MutexImpl : public NewOverrideBase
   80.37 {
   80.38     // System mutex or semaphore
   80.39     pthread_mutex_t   SMutex;
   80.40     bool          Recursive;
   80.41     unsigned      LockCount;
   80.42     pthread_t     LockedBy;
   80.43 
   80.44     friend class WaitConditionImpl;
   80.45 
   80.46 public:
   80.47     // Constructor/destructor
   80.48     MutexImpl(Mutex* pmutex, bool recursive = 1);
   80.49     ~MutexImpl();
   80.50 
   80.51     // Locking functions
   80.52     void                DoLock();
   80.53     bool                TryLock();
   80.54     void                Unlock(Mutex* pmutex);
   80.55     // Returns 1 if the mutes is currently locked
   80.56     bool                IsLockedByAnotherThread(Mutex* pmutex);        
   80.57     bool                IsSignaled() const;
   80.58 };
   80.59 
   80.60 pthread_mutexattr_t Lock::RecursiveAttr;
   80.61 bool Lock::RecursiveAttrInit = 0;
   80.62 
   80.63 // *** Constructor/destructor
   80.64 MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
   80.65 {   
   80.66     Recursive           = recursive;
   80.67     LockCount           = 0;
   80.68 
   80.69     if (Recursive)
   80.70     {
   80.71         if (!Lock::RecursiveAttrInit)
   80.72         {
   80.73             pthread_mutexattr_init(&Lock::RecursiveAttr);
   80.74             pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
   80.75             Lock::RecursiveAttrInit = 1;
   80.76         }
   80.77 
   80.78         pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
   80.79     }
   80.80     else
   80.81         pthread_mutex_init(&SMutex, 0);
   80.82 }
   80.83 
   80.84 MutexImpl::~MutexImpl()
   80.85 {
   80.86     pthread_mutex_destroy(&SMutex);
   80.87 }
   80.88 
   80.89 
   80.90 // Lock and try lock
   80.91 void MutexImpl::DoLock()
   80.92 {
   80.93     while (pthread_mutex_lock(&SMutex));
   80.94     LockCount++;
   80.95     LockedBy = pthread_self();
   80.96 }
   80.97 
   80.98 bool MutexImpl::TryLock()
   80.99 {
  80.100     if (!pthread_mutex_trylock(&SMutex))
  80.101     {
  80.102         LockCount++;
  80.103         LockedBy = pthread_self();
  80.104         return 1;
  80.105     }
  80.106     
  80.107     return 0;
  80.108 }
  80.109 
  80.110 void MutexImpl::Unlock(Mutex* pmutex)
  80.111 {
  80.112     OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
  80.113 
  80.114     unsigned lockCount;
  80.115     LockCount--;
  80.116     lockCount = LockCount;
  80.117 
  80.118     pthread_mutex_unlock(&SMutex);
  80.119 }
  80.120 
  80.121 bool    MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
  80.122 {
  80.123     // There could be multiple interpretations of IsLocked with respect to current thread
  80.124     if (LockCount == 0)
  80.125         return 0;
  80.126     if (pthread_self() != LockedBy)
  80.127         return 1;
  80.128     return 0;
  80.129 }
  80.130 
  80.131 bool    MutexImpl::IsSignaled() const
  80.132 {
  80.133     // An mutex is signaled if it is not locked ANYWHERE
  80.134     // Note that this is different from IsLockedByAnotherThread function,
  80.135     // that takes current thread into account
  80.136     return LockCount == 0;
  80.137 }
  80.138 
  80.139 
  80.140 // *** Actual Mutex class implementation
  80.141 
  80.142 Mutex::Mutex(bool recursive)
  80.143 {
  80.144     // NOTE: RefCount mode already thread-safe for all waitables.
  80.145     pImpl = new MutexImpl(this, recursive);
  80.146 }
  80.147 
  80.148 Mutex::~Mutex()
  80.149 {
  80.150     delete pImpl;
  80.151 }
  80.152 
  80.153 // Lock and try lock
  80.154 void Mutex::DoLock()
  80.155 {
  80.156     pImpl->DoLock();
  80.157 }
  80.158 bool Mutex::TryLock()
  80.159 {
  80.160     return pImpl->TryLock();
  80.161 }
  80.162 void Mutex::Unlock()
  80.163 {
  80.164     pImpl->Unlock(this);
  80.165 }
  80.166 bool    Mutex::IsLockedByAnotherThread()
  80.167 {
  80.168     return pImpl->IsLockedByAnotherThread(this);
  80.169 }
  80.170 
  80.171 
  80.172 
  80.173 //-----------------------------------------------------------------------------------
  80.174 // ***** Event
  80.175 
  80.176 bool Event::Wait(unsigned delay)
  80.177 {
  80.178     Mutex::Locker lock(&StateMutex);
  80.179 
  80.180     // Do the correct amount of waiting
  80.181     if (delay == OVR_WAIT_INFINITE)
  80.182     {
  80.183         while(!State)
  80.184             StateWaitCondition.Wait(&StateMutex);
  80.185     }
  80.186     else if (delay)
  80.187     {
  80.188         if (!State)
  80.189             StateWaitCondition.Wait(&StateMutex, delay);
  80.190     }
  80.191 
  80.192     bool state = State;
  80.193     // Take care of temporary 'pulsing' of a state
  80.194     if (Temporary)
  80.195     {
  80.196         Temporary   = false;
  80.197         State       = false;
  80.198     }
  80.199     return state;
  80.200 }
  80.201 
  80.202 void Event::updateState(bool newState, bool newTemp, bool mustNotify)
  80.203 {
  80.204     Mutex::Locker lock(&StateMutex);
  80.205     State       = newState;
  80.206     Temporary   = newTemp;
  80.207     if (mustNotify)
  80.208         StateWaitCondition.NotifyAll();    
  80.209 }
  80.210 
  80.211 
  80.212 
  80.213 // ***** Wait Condition Implementation
  80.214 
  80.215 // Internal implementation class
  80.216 class WaitConditionImpl : public NewOverrideBase
  80.217 {
  80.218     pthread_mutex_t     SMutex;
  80.219     pthread_cond_t      Condv;
  80.220 
  80.221 public:
  80.222 
  80.223     // Constructor/destructor
  80.224     WaitConditionImpl();
  80.225     ~WaitConditionImpl();
  80.226 
  80.227     // Release mutex and wait for condition. The mutex is re-aqured after the wait.
  80.228     bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
  80.229 
  80.230     // Notify a condition, releasing at one object waiting
  80.231     void    Notify();
  80.232     // Notify a condition, releasing all objects waiting
  80.233     void    NotifyAll();
  80.234 };
  80.235 
  80.236 
  80.237 WaitConditionImpl::WaitConditionImpl()
  80.238 {
  80.239     pthread_mutex_init(&SMutex, 0);
  80.240     pthread_cond_init(&Condv, 0);
  80.241 }
  80.242 
  80.243 WaitConditionImpl::~WaitConditionImpl()
  80.244 {
  80.245     pthread_mutex_destroy(&SMutex);
  80.246     pthread_cond_destroy(&Condv);
  80.247 }    
  80.248 
  80.249 bool    WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
  80.250 {
  80.251     bool            result = 1;
  80.252     unsigned            lockCount = pmutex->pImpl->LockCount;
  80.253 
  80.254     // Mutex must have been locked
  80.255     if (lockCount == 0)
  80.256         return 0;
  80.257 
  80.258     pthread_mutex_lock(&SMutex);
  80.259 
  80.260     // Finally, release a mutex or semaphore
  80.261     if (pmutex->pImpl->Recursive)
  80.262     {
  80.263         // Release the recursive mutex N times
  80.264         pmutex->pImpl->LockCount = 0;
  80.265         for(unsigned i=0; i<lockCount; i++)
  80.266             pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  80.267     }
  80.268     else
  80.269     {
  80.270         pmutex->pImpl->LockCount = 0;
  80.271         pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  80.272     }
  80.273 
  80.274     // Note that there is a gap here between mutex.Unlock() and Wait().
  80.275     // The other mutex protects this gap.
  80.276 
  80.277     if (delay == OVR_WAIT_INFINITE)
  80.278         pthread_cond_wait(&Condv,&SMutex);
  80.279     else
  80.280     {
  80.281         timespec ts;
  80.282 #ifdef OVR_OS_PS3
  80.283         sys_time_sec_t s;
  80.284         sys_time_nsec_t ns;
  80.285         sys_time_get_current_time(&s, &ns);
  80.286 
  80.287         ts.tv_sec = s + (delay / 1000);
  80.288         ts.tv_nsec = ns + (delay % 1000) * 1000000;
  80.289 
  80.290 #else
  80.291         struct timeval tv;
  80.292         gettimeofday(&tv, 0);
  80.293 
  80.294         ts.tv_sec = tv.tv_sec + (delay / 1000);
  80.295         ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
  80.296 #endif
  80.297         if (ts.tv_nsec > 999999999)
  80.298         {
  80.299             ts.tv_sec++;
  80.300             ts.tv_nsec -= 1000000000;
  80.301         }
  80.302         int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
  80.303         OVR_ASSERT(r == 0 || r == ETIMEDOUT);
  80.304         if (r)
  80.305             result = 0;
  80.306     }
  80.307 
  80.308     pthread_mutex_unlock(&SMutex);
  80.309 
  80.310     // Re-aquire the mutex
  80.311     for(unsigned i=0; i<lockCount; i++)
  80.312         pmutex->DoLock(); 
  80.313 
  80.314     // Return the result
  80.315     return result;
  80.316 }
  80.317 
  80.318 // Notify a condition, releasing the least object in a queue
  80.319 void    WaitConditionImpl::Notify()
  80.320 {
  80.321     pthread_mutex_lock(&SMutex);
  80.322     pthread_cond_signal(&Condv);
  80.323     pthread_mutex_unlock(&SMutex);
  80.324 }
  80.325 
  80.326 // Notify a condition, releasing all objects waiting
  80.327 void    WaitConditionImpl::NotifyAll()
  80.328 {
  80.329     pthread_mutex_lock(&SMutex);
  80.330     pthread_cond_broadcast(&Condv);
  80.331     pthread_mutex_unlock(&SMutex);
  80.332 }
  80.333 
  80.334 
  80.335 
  80.336 // *** Actual implementation of WaitCondition
  80.337 
  80.338 WaitCondition::WaitCondition()
  80.339 {
  80.340     pImpl = new WaitConditionImpl;
  80.341 }
  80.342 WaitCondition::~WaitCondition()
  80.343 {
  80.344     delete pImpl;
  80.345 }
  80.346     
  80.347 bool    WaitCondition::Wait(Mutex *pmutex, unsigned delay)
  80.348 {
  80.349     return pImpl->Wait(pmutex, delay);
  80.350 }
  80.351 // Notification
  80.352 void    WaitCondition::Notify()
  80.353 {
  80.354     pImpl->Notify();
  80.355 }
  80.356 void    WaitCondition::NotifyAll()
  80.357 {
  80.358     pImpl->NotifyAll();
  80.359 }
  80.360 
  80.361 
  80.362 // ***** Current thread
  80.363 
  80.364 // Per-thread variable
  80.365 /*
  80.366 static __thread Thread* pCurrentThread = 0;
  80.367 
  80.368 // Static function to return a pointer to the current thread
  80.369 void    Thread::InitCurrentThread(Thread *pthread)
  80.370 {
  80.371     pCurrentThread = pthread;
  80.372 }
  80.373 
  80.374 // Static function to return a pointer to the current thread
  80.375 Thread*    Thread::GetThread()
  80.376 {
  80.377     return pCurrentThread;
  80.378 }
  80.379 */
  80.380 
  80.381 
  80.382 // *** Thread constructors.
  80.383 
  80.384 Thread::Thread(UPInt stackSize, int processor)
  80.385 {
  80.386     // NOTE: RefCount mode already thread-safe for all Waitable objects.
  80.387     CreateParams params;
  80.388     params.stackSize = stackSize;
  80.389     params.processor = processor;
  80.390     Init(params);
  80.391 }
  80.392 
  80.393 Thread::Thread(Thread::ThreadFn threadFunction, void*  userHandle, UPInt stackSize,
  80.394                  int processor, Thread::ThreadState initialState)
  80.395 {
  80.396     CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
  80.397     Init(params);
  80.398 }
  80.399 
  80.400 Thread::Thread(const CreateParams& params)
  80.401 {
  80.402     Init(params);
  80.403 }
  80.404 
  80.405 void Thread::Init(const CreateParams& params)
  80.406 {
  80.407     // Clear the variables    
  80.408     ThreadFlags     = 0;
  80.409     ThreadHandle    = 0;
  80.410     ExitCode        = 0;
  80.411     SuspendCount    = 0;
  80.412     StackSize       = params.stackSize;
  80.413     Processor       = params.processor;
  80.414     Priority        = params.priority;
  80.415 
  80.416     // Clear Function pointers
  80.417     ThreadFunction  = params.threadFunction;
  80.418     UserHandle      = params.userHandle;
  80.419     if (params.initialState != NotRunning)
  80.420         Start(params.initialState);
  80.421 }
  80.422 
  80.423 Thread::~Thread()
  80.424 {
  80.425     // Thread should not running while object is being destroyed,
  80.426     // this would indicate ref-counting issue.
  80.427     //OVR_ASSERT(IsRunning() == 0);
  80.428 
  80.429     // Clean up thread.    
  80.430     ThreadHandle = 0;
  80.431 }
  80.432 
  80.433 
  80.434 
  80.435 // *** Overridable User functions.
  80.436 
  80.437 // Default Run implementation
  80.438 int    Thread::Run()
  80.439 {
  80.440     // Call pointer to function, if available.    
  80.441     return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
  80.442 }
  80.443 void    Thread::OnExit()
  80.444 {   
  80.445 }
  80.446 
  80.447 
  80.448 // Finishes the thread and releases internal reference to it.
  80.449 void    Thread::FinishAndRelease()
  80.450 {
  80.451     // Note: thread must be US.
  80.452     ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
  80.453     ThreadFlags |= OVR_THREAD_FINISHED;
  80.454 
  80.455     // Release our reference; this is equivalent to 'delete this'
  80.456     // from the point of view of our thread.
  80.457     Release();
  80.458 }
  80.459 
  80.460 
  80.461 
  80.462 // *** ThreadList - used to track all created threads
  80.463 
  80.464 class ThreadList : public NewOverrideBase
  80.465 {
  80.466     //------------------------------------------------------------------------
  80.467     struct ThreadHashOp
  80.468     {
  80.469         size_t operator()(const Thread* ptr)
  80.470         {
  80.471             return (((size_t)ptr) >> 6) ^ (size_t)ptr;
  80.472         }
  80.473     };
  80.474 
  80.475     HashSet<Thread*, ThreadHashOp>        ThreadSet;
  80.476     Mutex                                 ThreadMutex;
  80.477     WaitCondition                         ThreadsEmpty;
  80.478     // Track the root thread that created us.
  80.479     pthread_t                             RootThreadId;
  80.480 
  80.481     static ThreadList* volatile pRunningThreads;
  80.482 
  80.483     void addThread(Thread *pthread)
  80.484     {
  80.485         Mutex::Locker lock(&ThreadMutex);
  80.486         ThreadSet.Add(pthread);
  80.487     }
  80.488 
  80.489     void removeThread(Thread *pthread)
  80.490     {
  80.491         Mutex::Locker lock(&ThreadMutex);
  80.492         ThreadSet.Remove(pthread);
  80.493         if (ThreadSet.GetSize() == 0)
  80.494             ThreadsEmpty.Notify();
  80.495     }
  80.496 
  80.497     void finishAllThreads()
  80.498     {
  80.499         // Only original root thread can call this.
  80.500         OVR_ASSERT(pthread_self() == RootThreadId);
  80.501 
  80.502         Mutex::Locker lock(&ThreadMutex);
  80.503         while (ThreadSet.GetSize() != 0)
  80.504             ThreadsEmpty.Wait(&ThreadMutex);
  80.505     }
  80.506 
  80.507 public:
  80.508 
  80.509     ThreadList()
  80.510     {
  80.511         RootThreadId = pthread_self();
  80.512     }
  80.513     ~ThreadList() { }
  80.514 
  80.515 
  80.516     static void AddRunningThread(Thread *pthread)
  80.517     {
  80.518         // Non-atomic creation ok since only the root thread
  80.519         if (!pRunningThreads)
  80.520         {
  80.521             pRunningThreads = new ThreadList;
  80.522             OVR_ASSERT(pRunningThreads);
  80.523         }
  80.524         pRunningThreads->addThread(pthread);
  80.525     }
  80.526 
  80.527     // NOTE: 'pthread' might be a dead pointer when this is
  80.528     // called so it should not be accessed; it is only used
  80.529     // for removal.
  80.530     static void RemoveRunningThread(Thread *pthread)
  80.531     {
  80.532         OVR_ASSERT(pRunningThreads);        
  80.533         pRunningThreads->removeThread(pthread);
  80.534     }
  80.535 
  80.536     static void FinishAllThreads()
  80.537     {
  80.538         // This is ok because only root thread can wait for other thread finish.
  80.539         if (pRunningThreads)
  80.540         {           
  80.541             pRunningThreads->finishAllThreads();
  80.542             delete pRunningThreads;
  80.543             pRunningThreads = 0;
  80.544         }        
  80.545     }
  80.546 };
  80.547 
  80.548 // By default, we have no thread list.
  80.549 ThreadList* volatile ThreadList::pRunningThreads = 0;
  80.550 
  80.551 
  80.552 // FinishAllThreads - exposed publicly in Thread.
  80.553 void Thread::FinishAllThreads()
  80.554 {
  80.555     ThreadList::FinishAllThreads();
  80.556 }
  80.557 
  80.558 // *** Run override
  80.559 
  80.560 int    Thread::PRun()
  80.561 {
  80.562     // Suspend us on start, if requested
  80.563     if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
  80.564     {
  80.565         Suspend();
  80.566         ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
  80.567     }
  80.568 
  80.569     // Call the virtual run function
  80.570     ExitCode = Run();    
  80.571     return ExitCode;
  80.572 }
  80.573 
  80.574 
  80.575 
  80.576 
  80.577 // *** User overridables
  80.578 
  80.579 bool    Thread::GetExitFlag() const
  80.580 {
  80.581     return (ThreadFlags & OVR_THREAD_EXIT) != 0;
  80.582 }       
  80.583 
  80.584 void    Thread::SetExitFlag(bool exitFlag)
  80.585 {
  80.586     // The below is atomic since ThreadFlags is AtomicInt.
  80.587     if (exitFlag)
  80.588         ThreadFlags |= OVR_THREAD_EXIT;
  80.589     else
  80.590         ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
  80.591 }
  80.592 
  80.593 
  80.594 // Determines whether the thread was running and is now finished
  80.595 bool    Thread::IsFinished() const
  80.596 {
  80.597     return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
  80.598 }
  80.599 // Determines whether the thread is suspended
  80.600 bool    Thread::IsSuspended() const
  80.601 {   
  80.602     return SuspendCount > 0;
  80.603 }
  80.604 // Returns current thread state
  80.605 Thread::ThreadState Thread::GetThreadState() const
  80.606 {
  80.607     if (IsSuspended())
  80.608         return Suspended;    
  80.609     if (ThreadFlags & OVR_THREAD_STARTED)
  80.610         return Running;    
  80.611     return NotRunning;
  80.612 }
  80.613 /*
  80.614 static const char* mapsched_policy(int policy)
  80.615 {
  80.616     switch(policy)
  80.617     {
  80.618     case SCHED_OTHER:
  80.619         return "SCHED_OTHER";
  80.620     case SCHED_RR:
  80.621         return "SCHED_RR";
  80.622     case SCHED_FIFO:
  80.623         return "SCHED_FIFO";
  80.624 
  80.625     }
  80.626     return "UNKNOWN";
  80.627 }
  80.628     int policy;
  80.629     sched_param sparam;
  80.630     pthread_getschedparam(pthread_self(), &policy, &sparam);
  80.631     int max_prior = sched_get_priority_max(policy);
  80.632     int min_prior = sched_get_priority_min(policy);
  80.633     printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior);
  80.634 #include <stdio.h>
  80.635 */
  80.636 // ***** Thread management
  80.637 
  80.638 // The actual first function called on thread start
  80.639 void* Thread_PthreadStartFn(void* phandle)
  80.640 {
  80.641     Thread* pthread = (Thread*)phandle;
  80.642     int     result = pthread->PRun();
  80.643     // Signal the thread as done and release it atomically.
  80.644     pthread->FinishAndRelease();
  80.645     // At this point Thread object might be dead; however we can still pass
  80.646     // it to RemoveRunningThread since it is only used as a key there.   
  80.647     ThreadList::RemoveRunningThread(pthread);
  80.648     return (void*) result;
  80.649 }
  80.650 
  80.651 int Thread::InitAttr = 0;
  80.652 pthread_attr_t Thread::Attr; 
  80.653 
  80.654 /* static */
  80.655 int Thread::GetOSPriority(ThreadPriority p)
  80.656 //static inline int MapToSystemPrority(Thread::ThreadPriority p)
  80.657 {
  80.658 #ifdef OVR_OS_PS3 
  80.659     switch(p)
  80.660     {
  80.661     case Thread::CriticalPriority:     return 0;
  80.662     case Thread::HighestPriority:      return 300;
  80.663     case Thread::AboveNormalPriority:  return 600;
  80.664     case Thread::NormalPriority:       return 1000;
  80.665     case Thread::BelowNormalPriority:  return 1500;
  80.666     case Thread::LowestPriority:       return 2500;
  80.667     case Thread::IdlePriority:         return 3071;
  80.668     }                                  return 1000;
  80.669 #else
  80.670     OVR_UNUSED(p);
  80.671     return -1;
  80.672 #endif
  80.673 }
  80.674 
  80.675 bool    Thread::Start(ThreadState initialState)
  80.676 {
  80.677     if (initialState == NotRunning)
  80.678         return 0;
  80.679     if (GetThreadState() != NotRunning)
  80.680     {
  80.681         OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
  80.682         return 0;
  80.683     }
  80.684 
  80.685     if (!InitAttr)
  80.686     {
  80.687         pthread_attr_init(&Attr);
  80.688         pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
  80.689         pthread_attr_setstacksize(&Attr, 128 * 1024);
  80.690         sched_param sparam;
  80.691         sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
  80.692         pthread_attr_setschedparam(&Attr, &sparam);
  80.693         InitAttr = 1;
  80.694     }
  80.695 
  80.696     ExitCode        = 0;
  80.697     SuspendCount    = 0;
  80.698     ThreadFlags     = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
  80.699 
  80.700     // AddRef to us until the thread is finished
  80.701     AddRef();
  80.702     ThreadList::AddRunningThread(this);
  80.703 
  80.704     int result;
  80.705     if (StackSize != 128 * 1024 || Priority != NormalPriority)
  80.706     {
  80.707         pthread_attr_t attr;
  80.708 
  80.709         pthread_attr_init(&attr);
  80.710         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  80.711         pthread_attr_setstacksize(&attr, StackSize);
  80.712         sched_param sparam;
  80.713         sparam.sched_priority = Thread::GetOSPriority(Priority);
  80.714         pthread_attr_setschedparam(&attr, &sparam);
  80.715         result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
  80.716         pthread_attr_destroy(&attr);
  80.717     }
  80.718     else
  80.719         result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
  80.720 
  80.721     if (result)
  80.722     {
  80.723         ThreadFlags = 0;
  80.724         Release();
  80.725         ThreadList::RemoveRunningThread(this);
  80.726         return 0;
  80.727     }
  80.728     return 1;
  80.729 }
  80.730 
  80.731 
  80.732 // Suspend the thread until resumed
  80.733 bool    Thread::Suspend()
  80.734 {
  80.735     OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
  80.736     return 0;
  80.737 }
  80.738 
  80.739 // Resumes currently suspended thread
  80.740 bool    Thread::Resume()
  80.741 {
  80.742     return 0;
  80.743 }
  80.744 
  80.745 
  80.746 // Quits with an exit code  
  80.747 void    Thread::Exit(int exitCode)
  80.748 {
  80.749     // Can only exist the current thread
  80.750    // if (GetThread() != this)
  80.751    //     return;
  80.752 
  80.753     // Call the virtual OnExit function
  80.754     OnExit();   
  80.755 
  80.756     // Signal this thread object as done and release it's references.
  80.757     FinishAndRelease();
  80.758     ThreadList::RemoveRunningThread(this);
  80.759 
  80.760     pthread_exit((void *) exitCode);
  80.761 }
  80.762 
  80.763 ThreadId GetCurrentThreadId()
  80.764 {
  80.765     return (void*)pthread_self();
  80.766 }
  80.767 
  80.768 // *** Sleep functions
  80.769 
  80.770 /* static */
  80.771 bool    Thread::Sleep(unsigned secs)
  80.772 {
  80.773     sleep(secs);
  80.774     return 1;
  80.775 }
  80.776 /* static */
  80.777 bool    Thread::MSleep(unsigned msecs)
  80.778 {
  80.779     usleep(msecs*1000);
  80.780     return 1;
  80.781 }
  80.782 
  80.783 /* static */
  80.784 int     Thread::GetCPUCount()
  80.785 {
  80.786     return 1;
  80.787 }
  80.788 
  80.789 
  80.790 #ifdef OVR_OS_PS3
  80.791 
  80.792 sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE };
  80.793 
  80.794 #endif
  80.795 
  80.796 }
  80.797 
  80.798 #endif  // OVR_ENABLE_THREADS
  80.799 \ No newline at end of file
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/libovr/Src/osx/OVR_OSX_DeviceManager.cpp	Sat Sep 14 16:14:59 2013 +0300
    81.3 @@ -0,0 +1,349 @@
    81.4 +/************************************************************************************
    81.5 +
    81.6 +Filename    :   OVR_OSX_DeviceManager.cpp
    81.7 +Content     :   OSX specific DeviceManager implementation.
    81.8 +Created     :   March 14, 2013
    81.9 +Authors     :   Lee Cooper
   81.10 +
   81.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   81.12 +
   81.13 +Use of this software is subject to the terms of the Oculus license
   81.14 +agreement provided at the time of installation or download, or which
   81.15 +otherwise accompanies this software in either electronic or hard copy form.
   81.16 +
   81.17 +*************************************************************************************/
   81.18 +
   81.19 +#include "OVR_OSX_DeviceManager.h"
   81.20 +
   81.21 +// Sensor & HMD Factories
   81.22 +#include "OVR_LatencyTestImpl.h"
   81.23 +#include "OVR_SensorImpl.h"
   81.24 +#include "OVR_OSX_HMDDevice.h"
   81.25 +#include "OVR_OSX_HIDDevice.h"
   81.26 +
   81.27 +#include "Kernel/OVR_Timer.h"
   81.28 +#include "Kernel/OVR_Std.h"
   81.29 +#include "Kernel/OVR_Log.h"
   81.30 +
   81.31 +#include <IOKit/hid/IOHIDManager.h>
   81.32 +#include <IOKit/hid/IOHIDKeys.h>
   81.33 +
   81.34 +
   81.35 +namespace OVR { namespace OSX {
   81.36 +
   81.37 +//-------------------------------------------------------------------------------------
   81.38 +// **** OSX::DeviceManager
   81.39 +
   81.40 +DeviceManager::DeviceManager()
   81.41 +{
   81.42 +}
   81.43 +
   81.44 +DeviceManager::~DeviceManager()
   81.45 +{
   81.46 +    OVR_DEBUG_LOG(("OSX::DeviceManager::~DeviceManager was called"));
   81.47 +}
   81.48 +
   81.49 +bool DeviceManager::Initialize(DeviceBase*)
   81.50 +{
   81.51 +    if (!DeviceManagerImpl::Initialize(0))
   81.52 +        return false;
   81.53 +    
   81.54 +    // Start the background thread.
   81.55 +    pThread = *new DeviceManagerThread();
   81.56 +    if (!pThread || !pThread->Start())
   81.57 +        return false;
   81.58 +
   81.59 +    // Wait for the thread to be fully up and running.
   81.60 +    pThread->StartupEvent.Wait();
   81.61 +
   81.62 +    // Do this now that we know the thread's run loop.
   81.63 +    HidDeviceManager = *HIDDeviceManager::CreateInternal(this);
   81.64 +
   81.65 +    CGDisplayRegisterReconfigurationCallback(displayReconfigurationCallBack, this);
   81.66 +         
   81.67 +    pCreateDesc->pDevice = this;
   81.68 +    LogText("OVR::DeviceManager - initialized.\n");
   81.69 +
   81.70 +    return true;
   81.71 +}
   81.72 +
   81.73 +void DeviceManager::Shutdown()
   81.74 +{
   81.75 +    LogText("OVR::DeviceManager - shutting down.\n");
   81.76 +
   81.77 +    CGDisplayRemoveReconfigurationCallback(displayReconfigurationCallBack, this);
   81.78 +    
   81.79 +    // Set Manager shutdown marker variable; this prevents
   81.80 +    // any existing DeviceHandle objects from accessing device.
   81.81 +    pCreateDesc->pLock->pManager = 0;
   81.82 +
   81.83 +    // Push for thread shutdown *WITH NO WAIT*.
   81.84 +    // This will have the following effect:
   81.85 +    //  - Exit command will get enqueued, which will be executed later on the thread itself.
   81.86 +    //  - Beyond this point, this DeviceManager object may be deleted by our caller.
   81.87 +    //  - Other commands, such as CreateDevice, may execute before ExitCommand, but they will
   81.88 +    //    fail gracefully due to pLock->pManager == 0. Future commands can't be enqued
   81.89 +    //    after pManager is null.
   81.90 +    //  - Once ExitCommand executes, ThreadCommand::Run loop will exit and release the last
   81.91 +    //    reference to the thread object.
   81.92 +    pThread->Shutdown();
   81.93 +    pThread.Clear();
   81.94 +
   81.95 +    DeviceManagerImpl::Shutdown();
   81.96 +}
   81.97 +
   81.98 +ThreadCommandQueue* DeviceManager::GetThreadQueue()
   81.99 +{
  81.100 +    return pThread;
  81.101 +}
  81.102 +
  81.103 +ThreadId DeviceManager::GetThreadId() const
  81.104 +{
  81.105 +    return pThread->GetThreadId();
  81.106 +}
  81.107 +
  81.108 +bool DeviceManager::GetDeviceInfo(DeviceInfo* info) const
  81.109 +{
  81.110 +    if ((info->InfoClassType != Device_Manager) &&
  81.111 +        (info->InfoClassType != Device_None))
  81.112 +        return false;
  81.113 +    
  81.114 +    info->Type    = Device_Manager;
  81.115 +    info->Version = 0;
  81.116 +    OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength, "DeviceManager");
  81.117 +    OVR_strcpy(info->Manufacturer,DeviceInfo::MaxNameLength, "Oculus VR, Inc.");        
  81.118 +    return true;
  81.119 +}
  81.120 +
  81.121 +DeviceEnumerator<> DeviceManager::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
  81.122 +{
  81.123 +    // TBD: Can this be avoided in the future, once proper device notification is in place?
  81.124 +    pThread->PushCall((DeviceManagerImpl*)this,
  81.125 +                      &DeviceManager::EnumerateAllFactoryDevices, true);
  81.126 +
  81.127 +    return DeviceManagerImpl::EnumerateDevicesEx(args);
  81.128 +}
  81.129 +
  81.130 +void DeviceManager::displayReconfigurationCallBack (CGDirectDisplayID display,
  81.131 +                                                    CGDisplayChangeSummaryFlags flags,
  81.132 +                                                    void *userInfo)
  81.133 +{
  81.134 +    DeviceManager* manager = reinterpret_cast<DeviceManager*>(userInfo);
  81.135 +    OVR_UNUSED(manager);
  81.136 +    
  81.137 +    if (flags & kCGDisplayAddFlag)
  81.138 +    {
  81.139 +        LogText("Display Added, id = %d\n", int(display));
  81.140 +        manager->EnumerateDevices<HMDDevice>();
  81.141 +    }
  81.142 +    else if (flags & kCGDisplayRemoveFlag)
  81.143 +    {
  81.144 +        LogText("Display Removed, id = %d\n", int(display));
  81.145 +        manager->EnumerateDevices<HMDDevice>();
  81.146 +    }
  81.147 +}
  81.148 +
  81.149 +//-------------------------------------------------------------------------------------
  81.150 +// ***** DeviceManager Thread 
  81.151 +
  81.152 +DeviceManagerThread::DeviceManagerThread()
  81.153 +    : Thread(ThreadStackSize)
  81.154 +{    
  81.155 +}
  81.156 +
  81.157 +DeviceManagerThread::~DeviceManagerThread()
  81.158 +{
  81.159 +}
  81.160 +
  81.161 +int DeviceManagerThread::Run()
  81.162 +{
  81.163 +
  81.164 +    SetThreadName("OVR::DeviceManagerThread");
  81.165 +    LogText("OVR::DeviceManagerThread - running (ThreadId=0x%p).\n", GetThreadId());
  81.166 +
  81.167 +    // Store out the run loop ref.
  81.168 +    RunLoop = CFRunLoopGetCurrent();
  81.169 +
  81.170 +    // Create a 'source' to enable us to signal the run loop to process the command queue.
  81.171 +    CFRunLoopSourceContext sourceContext;
  81.172 +    memset(&sourceContext, 0, sizeof(sourceContext));
  81.173 +    sourceContext.version = 0;
  81.174 +    sourceContext.info = this;
  81.175 +    sourceContext.perform = &staticCommandQueueSourceCallback;
  81.176 +
  81.177 +    CommandQueueSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0 , &sourceContext);
  81.178 +
  81.179 +    CFRunLoopAddSource(RunLoop, CommandQueueSource, kCFRunLoopDefaultMode);
  81.180 +
  81.181 +
  81.182 +    // Signal to the parent thread that initialization has finished.
  81.183 +    StartupEvent.SetEvent();
  81.184 +
  81.185 +
  81.186 +    ThreadCommand::PopBuffer command;
  81.187 +   
  81.188 +    while(!IsExiting())
  81.189 +    {
  81.190 +        // PopCommand will reset event on empty queue.
  81.191 +        if (PopCommand(&command))
  81.192 +        {
  81.193 +            command.Execute();
  81.194 +        }
  81.195 +        else
  81.196 +        {
  81.197 +            SInt32 exitReason = 0;
  81.198 +            do {
  81.199 +
  81.200 +                UInt32 waitMs = INT_MAX;
  81.201 +
  81.202 +                // If devices have time-dependent logic registered, get the longest wait
  81.203 +                // allowed based on current ticks.
  81.204 +                if (!TicksNotifiers.IsEmpty())
  81.205 +                {
  81.206 +                    UInt64 ticksMks = Timer::GetTicks();
  81.207 +                    UInt32  waitAllowed;
  81.208 +
  81.209 +                    for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++)
  81.210 +                    {
  81.211 +                        waitAllowed = (UInt32)(TicksNotifiers[j]->OnTicks(ticksMks) / Timer::MksPerMs);
  81.212 +                        if (waitAllowed < waitMs)
  81.213 +                            waitMs = waitAllowed;
  81.214 +                    }
  81.215 +                }
  81.216 +                
  81.217 +                // Enter blocking run loop. We may continue until we timeout in which
  81.218 +                // case it's time to service the ticks. Or if commands arrive in the command
  81.219 +                // queue then the source callback will call 'CFRunLoopStop' causing this
  81.220 +                // to return.
  81.221 +                CFTimeInterval blockInterval = 0.001 * (double) waitMs;
  81.222 +                exitReason = CFRunLoopRunInMode(kCFRunLoopDefaultMode, blockInterval, false);
  81.223 +
  81.224 +                if (exitReason == kCFRunLoopRunFinished)
  81.225 +                {
  81.226 +                    // Maybe this will occur during shutdown?
  81.227 +                    break;
  81.228 +                }
  81.229 +                else if (exitReason == kCFRunLoopRunStopped )
  81.230 +                {
  81.231 +                    // Commands need processing or we're being shutdown.
  81.232 +                    break;
  81.233 +                }
  81.234 +                else if (exitReason == kCFRunLoopRunTimedOut)
  81.235 +                {
  81.236 +                    // Timed out so that we can service our ticks callbacks.
  81.237 +                    continue;
  81.238 +                }
  81.239 +                else if (exitReason == kCFRunLoopRunHandledSource)
  81.240 +                {
  81.241 +                    // Should never occur since the last param when we call
  81.242 +                    // 'CFRunLoopRunInMode' is false.
  81.243 +                    OVR_ASSERT(false);
  81.244 +                    break;
  81.245 +                }
  81.246 +                else
  81.247 +                {
  81.248 +                    OVR_ASSERT_LOG(false, ("CFRunLoopRunInMode returned unexpected code"));
  81.249 +                    break;
  81.250 +                }
  81.251 +            }
  81.252 +            while(true);                    
  81.253 +        }
  81.254 +    }
  81.255 +
  81.256 +                                   
  81.257 +    CFRunLoopRemoveSource(RunLoop, CommandQueueSource, kCFRunLoopDefaultMode);
  81.258 +    CFRelease(CommandQueueSource);
  81.259 +    
  81.260 +    LogText("OVR::DeviceManagerThread - exiting (ThreadId=0x%p).\n", GetThreadId());
  81.261 +
  81.262 +    return 0;
  81.263 +}
  81.264 +    
  81.265 +void DeviceManagerThread::staticCommandQueueSourceCallback(void* pContext)
  81.266 +{
  81.267 +    DeviceManagerThread* pThread = (DeviceManagerThread*) pContext;
  81.268 +    pThread->commandQueueSourceCallback();
  81.269 +}
  81.270 +    
  81.271 +void DeviceManagerThread::commandQueueSourceCallback()
  81.272 +{    
  81.273 +    CFRunLoopStop(RunLoop);
  81.274 +}
  81.275 +
  81.276 +bool DeviceManagerThread::AddTicksNotifier(Notifier* notify)
  81.277 +{
  81.278 +     TicksNotifiers.PushBack(notify);
  81.279 +     return true;
  81.280 +}
  81.281 +
  81.282 +bool DeviceManagerThread::RemoveTicksNotifier(Notifier* notify)
  81.283 +{
  81.284 +    for (UPInt i = 0; i < TicksNotifiers.GetSize(); i++)
  81.285 +    {
  81.286 +        if (TicksNotifiers[i] == notify)
  81.287 +        {
  81.288 +            TicksNotifiers.RemoveAt(i);
  81.289 +            return true;
  81.290 +        }
  81.291 +    }
  81.292 +    return false;
  81.293 +}
  81.294 +
  81.295 +void DeviceManagerThread::Shutdown()
  81.296 +{
  81.297 +    // Push for thread shutdown *WITH NO WAIT*.
  81.298 +    // This will have the following effect:
  81.299 +    //  - Exit command will get enqueued, which will be executed later on the thread itself.
  81.300 +    //  - Beyond this point, this DeviceManager object may be deleted by our caller.
  81.301 +    //  - Other commands, such as CreateDevice, may execute before ExitCommand, but they will
  81.302 +    //    fail gracefully due to pLock->pManager == 0. Future commands can't be enqued
  81.303 +    //    after pManager is null.
  81.304 +    //  - Once ExitCommand executes, ThreadCommand::Run loop will exit and release the last
  81.305 +    //    reference to the thread object.
  81.306 +    PushExitCommand(false);
  81.307 +
  81.308 +    // make sure CFRunLoopRunInMode is woken up
  81.309 +    CFRunLoopSourceSignal(CommandQueueSource);
  81.310 +    CFRunLoopWakeUp(RunLoop);
  81.311 +}
  81.312 +    
  81.313 +} // namespace OSX
  81.314 +
  81.315 +
  81.316 +//-------------------------------------------------------------------------------------
  81.317 +// ***** Creation
  81.318 +
  81.319 +// Creates a new DeviceManager and initializes OVR.
  81.320 +DeviceManager* DeviceManager::Create()
  81.321 +{
  81.322 +
  81.323 +    if (!System::IsInitialized())
  81.324 +    {
  81.325 +        // Use custom message, since Log is not yet installed.
  81.326 +        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
  81.327 +            LogMessage(Log_Debug, "DeviceManager::Create failed - OVR::System not initialized"); );
  81.328 +        return 0;
  81.329 +    }
  81.330 +
  81.331 +    Ptr<OSX::DeviceManager> manager = *new OSX::DeviceManager;
  81.332 +
  81.333 +    if (manager)
  81.334 +    {
  81.335 +        if (manager->Initialize(0))
  81.336 +        {
  81.337 +            manager->AddFactory(&LatencyTestDeviceFactory::Instance);
  81.338 +            manager->AddFactory(&SensorDeviceFactory::Instance);
  81.339 +            manager->AddFactory(&OSX::HMDDeviceFactory::Instance);
  81.340 +
  81.341 +            manager->AddRef();
  81.342 +        }
  81.343 +        else
  81.344 +        {
  81.345 +            manager.Clear();
  81.346 +        }
  81.347 +    }    
  81.348 +
  81.349 +    return manager.GetPtr();
  81.350 +}
  81.351 +
  81.352 +} // namespace OVR
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/libovr/Src/osx/OVR_OSX_DeviceManager.h	Sat Sep 14 16:14:59 2013 +0300
    82.3 @@ -0,0 +1,119 @@
    82.4 +/************************************************************************************
    82.5 +
    82.6 +Filename    :   OVR_OSX_DeviceManager.h
    82.7 +Content     :   OSX specific DeviceManager header.
    82.8 +Created     :   March 14, 2013
    82.9 +Authors     :   Lee Cooper
   82.10 +
   82.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   82.12 +
   82.13 +Use of this software is subject to the terms of the Oculus license
   82.14 +agreement provided at the time of installation or download, or which
   82.15 +otherwise accompanies this software in either electronic or hard copy form.
   82.16 +
   82.17 +*************************************************************************************/
   82.18 +
   82.19 +#ifndef OVR_OSX_DeviceManager_h
   82.20 +#define OVR_OSX_DeviceManager_h
   82.21 +
   82.22 +#include "OVR_DeviceImpl.h"
   82.23 +
   82.24 +#include "Kernel/OVR_Timer.h"
   82.25 +
   82.26 +#include <IOKit/hid/IOHIDManager.h>
   82.27 +#include <CoreGraphics/CGDirectDisplay.h>
   82.28 +#include <CoreGraphics/CGDisplayConfiguration.h>
   82.29 +
   82.30 +
   82.31 +namespace OVR { namespace OSX {
   82.32 +
   82.33 +class DeviceManagerThread;
   82.34 +
   82.35 +//-------------------------------------------------------------------------------------
   82.36 +// ***** OSX DeviceManager
   82.37 +
   82.38 +class DeviceManager : public DeviceManagerImpl
   82.39 +{
   82.40 +public:
   82.41 +    DeviceManager();
   82.42 +    ~DeviceManager();
   82.43 +
   82.44 +    // Initialize/Shutdown manager thread.
   82.45 +    virtual bool Initialize(DeviceBase* parent);
   82.46 +    virtual void Shutdown();
   82.47 +
   82.48 +    virtual ThreadCommandQueue* GetThreadQueue();
   82.49 +    virtual ThreadId GetThreadId() const;
   82.50 +    
   82.51 +    virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args);
   82.52 +
   82.53 +    virtual bool  GetDeviceInfo(DeviceInfo* info) const;
   82.54 +
   82.55 +protected:
   82.56 +    static void displayReconfigurationCallBack (CGDirectDisplayID display,
   82.57 +                                                CGDisplayChangeSummaryFlags flags,
   82.58 +                                                void *userInfo);
   82.59 +  
   82.60 +public: // data
   82.61 +    Ptr<DeviceManagerThread> pThread;
   82.62 +};
   82.63 +
   82.64 +//-------------------------------------------------------------------------------------
   82.65 +// ***** Device Manager Background Thread
   82.66 +
   82.67 +class DeviceManagerThread : public Thread, public ThreadCommandQueue
   82.68 +{
   82.69 +    friend class DeviceManager;
   82.70 +    enum { ThreadStackSize = 32 * 1024 };
   82.71 +public:
   82.72 +    DeviceManagerThread();
   82.73 +    ~DeviceManagerThread();
   82.74 +
   82.75 +    virtual int Run();
   82.76 +
   82.77 +    // ThreadCommandQueue notifications for CommandEvent handling.
   82.78 +    virtual void OnPushNonEmpty_Locked()
   82.79 +    {
   82.80 +        CFRunLoopSourceSignal(CommandQueueSource);
   82.81 +        CFRunLoopWakeUp(RunLoop);
   82.82 +    }
   82.83 +    
   82.84 +    virtual void OnPopEmpty_Locked()     {}
   82.85 +
   82.86 +
   82.87 +    // Notifier used for different updates (EVENT or regular timing or messages).
   82.88 +    class Notifier  
   82.89 +    {
   82.90 +    public:
   82.91 +
   82.92 +        // Called when timing ticks are updated. // Returns the largest number of microseconds
   82.93 +        // this function can wait till next call.
   82.94 +        virtual UInt64  OnTicks(UInt64 ticksMks)
   82.95 +        { OVR_UNUSED1(ticksMks);  return Timer::MksPerSecond * 1000; }
   82.96 +    };
   82.97 + 
   82.98 +    // Add notifier that will be called at regular intervals. 
   82.99 +    bool AddTicksNotifier(Notifier* notify);
  82.100 +    bool RemoveTicksNotifier(Notifier* notify);
  82.101 +
  82.102 +    CFRunLoopRef        GetRunLoop()
  82.103 +    { return RunLoop; }
  82.104 +    
  82.105 +    void                Shutdown();
  82.106 +private:
  82.107 +    CFRunLoopRef        RunLoop;
  82.108 +
  82.109 +    CFRunLoopSourceRef  CommandQueueSource;
  82.110 +    
  82.111 +    static void staticCommandQueueSourceCallback(void* pContext);
  82.112 +    void commandQueueSourceCallback();
  82.113 +
  82.114 +    Event               StartupEvent;
  82.115 +    
  82.116 +    // Ticks notifiers. Used for time-dependent events such as keep-alive.
  82.117 +    Array<Notifier*>    TicksNotifiers;
  82.118 +};
  82.119 +
  82.120 +}} // namespace OSX::OVR
  82.121 +
  82.122 +#endif // OVR_OSX_DeviceManager_h
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/libovr/Src/osx/OVR_OSX_HIDDevice.cpp	Sat Sep 14 16:14:59 2013 +0300
    83.3 @@ -0,0 +1,899 @@
    83.4 +/************************************************************************************
    83.5 +Filename    :   OVR_OSX_HIDDevice.cpp
    83.6 +Content     :   OSX HID device implementation.
    83.7 +Created     :   February 26, 2013
    83.8 +Authors     :   Lee Cooper
    83.9 + 
   83.10 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   83.11 + 
   83.12 +Use of this software is subject to the terms of the Oculus license
   83.13 +agreement provided at the time of installation or download, or which
   83.14 +otherwise accompanies this software in either electronic or hard copy form.
   83.15 +
   83.16 +*************************************************************************************/
   83.17 +
   83.18 +#include "OVR_OSX_HIDDevice.h"
   83.19 +
   83.20 +#include <IOKit/usb/IOUSBLib.h>
   83.21 +
   83.22 +namespace OVR { namespace OSX {
   83.23 +
   83.24 +static const UInt32 MAX_QUEUED_INPUT_REPORTS = 5;
   83.25 +    
   83.26 +//-------------------------------------------------------------------------------------
   83.27 +// **** OSX::DeviceManager
   83.28 +
   83.29 +HIDDeviceManager::HIDDeviceManager(DeviceManager* manager)
   83.30 + :  DevManager(manager)
   83.31 +{
   83.32 +    HIDManager = NULL;
   83.33 +}
   83.34 +
   83.35 +HIDDeviceManager::~HIDDeviceManager()
   83.36 +{
   83.37 +}
   83.38 +
   83.39 +CFRunLoopRef HIDDeviceManager::getRunLoop()
   83.40 +{
   83.41 +    if (DevManager != NULL)
   83.42 +    {
   83.43 +        return DevManager->pThread->GetRunLoop();
   83.44 +    }
   83.45 +
   83.46 +    return CFRunLoopGetCurrent();
   83.47 +}
   83.48 +
   83.49 +bool HIDDeviceManager::initializeManager()
   83.50 +{
   83.51 +    if (HIDManager != NULL)
   83.52 +    {
   83.53 +        return true;
   83.54 +    }
   83.55 +    
   83.56 +	HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
   83.57 +    
   83.58 +    if (!HIDManager)
   83.59 +    {
   83.60 +        return false;
   83.61 +    }
   83.62 +    
   83.63 +    // Create a Matching Dictionary
   83.64 +    CFMutableDictionaryRef matchDict =
   83.65 +        CFDictionaryCreateMutable(kCFAllocatorDefault,
   83.66 +                                  2,
   83.67 +                                  &kCFTypeDictionaryKeyCallBacks,
   83.68 +                                  &kCFTypeDictionaryValueCallBacks);
   83.69 +    
   83.70 +    // Specify a device manufacturer in the Matching Dictionary
   83.71 +    UInt32 vendorId = Oculus_VendorId;
   83.72 +    CFNumberRef vendorIdRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &vendorId);
   83.73 +    CFDictionarySetValue(matchDict,
   83.74 +                         CFSTR(kIOHIDVendorIDKey),
   83.75 +                         vendorIdRef);
   83.76 +    // Register the Matching Dictionary to the HID Manager
   83.77 +    IOHIDManagerSetDeviceMatching(HIDManager, matchDict);
   83.78 +    CFRelease(vendorIdRef);
   83.79 +    CFRelease(matchDict);
   83.80 +    
   83.81 +    // Register a callback for USB device detection with the HID Manager
   83.82 +    IOHIDManagerRegisterDeviceMatchingCallback(HIDManager, &staticDeviceMatchingCallback, this);
   83.83 +    
   83.84 +    IOHIDManagerScheduleWithRunLoop(HIDManager, getRunLoop(), kCFRunLoopDefaultMode);
   83.85 +
   83.86 +    return true;
   83.87 +}
   83.88 +    
   83.89 +bool HIDDeviceManager::Initialize()
   83.90 +{
   83.91 +    return initializeManager();
   83.92 +}
   83.93 +
   83.94 +void HIDDeviceManager::Shutdown()
   83.95 +{
   83.96 +    OVR_ASSERT_LOG(HIDManager, ("Should have called 'Initialize' before 'Shutdown'."));
   83.97 +    CFRelease(HIDManager);
   83.98 +    
   83.99 +    LogText("OVR::OSX::HIDDeviceManager - shutting down.\n");
  83.100 +}
  83.101 +    
  83.102 +bool HIDDeviceManager::getIntProperty(IOHIDDeviceRef device, CFStringRef propertyName, SInt32* pResult)
  83.103 +{
  83.104 +    
  83.105 +    CFTypeRef ref = IOHIDDeviceGetProperty(device, propertyName);
  83.106 +
  83.107 +    if (!ref)
  83.108 +    {
  83.109 +        return false;
  83.110 +    }
  83.111 +    
  83.112 +    if (CFGetTypeID(ref) != CFNumberGetTypeID())
  83.113 +    {
  83.114 +        return false;
  83.115 +    }
  83.116 +    
  83.117 +    CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, pResult);
  83.118 +
  83.119 +    return true;
  83.120 +}
  83.121 +    
  83.122 +bool HIDDeviceManager::initVendorProductVersion(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
  83.123 +{
  83.124 +    
  83.125 +    if (!getVendorId(device, &(pDevDesc->VendorId)))
  83.126 +    {
  83.127 +        return false;
  83.128 +    }
  83.129 +    
  83.130 +    if (!getProductId(device, &(pDevDesc->ProductId)))
  83.131 +    {
  83.132 +        return false;
  83.133 +    }
  83.134 +    
  83.135 +    return true;
  83.136 +}
  83.137 +
  83.138 +bool HIDDeviceManager::initUsage(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
  83.139 +{
  83.140 +    
  83.141 +    SInt32 result;
  83.142 +    
  83.143 +    if (!getIntProperty(device, CFSTR(kIOHIDPrimaryUsagePageKey), &result))
  83.144 +    {
  83.145 +        return false;
  83.146 +    }
  83.147 +    
  83.148 +    pDevDesc->UsagePage = result;
  83.149 +
  83.150 +    
  83.151 +    if (!getIntProperty(device, CFSTR(kIOHIDPrimaryUsageKey), &result))
  83.152 +    {
  83.153 +        return false;
  83.154 +    }
  83.155 +    
  83.156 +    pDevDesc->Usage = result;
  83.157 +    
  83.158 +    return true;
  83.159 +}
  83.160 +
  83.161 +bool HIDDeviceManager::initSerialNumber(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
  83.162 +{
  83.163 +    return getSerialNumberString(device, &(pDevDesc->SerialNumber));
  83.164 +}
  83.165 +    
  83.166 +bool HIDDeviceManager::initStrings(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc)
  83.167 +{
  83.168 +
  83.169 +    // Regardless of whether they fail we'll try and get the remaining.
  83.170 +    getStringProperty(device, CFSTR(kIOHIDManufacturerKey), &(pDevDesc->Manufacturer));
  83.171 +    getStringProperty(device, CFSTR(kIOHIDProductKey), &(pDevDesc->Product));
  83.172 +    
  83.173 +    return true;
  83.174 +}
  83.175 +
  83.176 +bool HIDDeviceManager::getStringProperty(IOHIDDeviceRef device,
  83.177 +                                         CFStringRef propertyName,
  83.178 +                                         String* pResult)
  83.179 +{
  83.180 +    
  83.181 +    CFStringRef str = (CFStringRef) IOHIDDeviceGetProperty(device, propertyName);
  83.182 +    
  83.183 +    if (!str)
  83.184 +    {
  83.185 +        return false;
  83.186 +    }
  83.187 +
  83.188 +    CFIndex length = CFStringGetLength(str);
  83.189 +    CFRange range = CFRangeMake(0, length);
  83.190 +    
  83.191 +    // Test the conversion first to get required buffer size.
  83.192 +    CFIndex bufferLength;
  83.193 +    CFIndex numberOfChars = CFStringGetBytes(str,
  83.194 +                                             range,
  83.195 +                                             kCFStringEncodingUTF8,
  83.196 +                                             (char) '?',
  83.197 +                                             FALSE,
  83.198 +                                             NULL,
  83.199 +                                             0,
  83.200 +                                             &bufferLength);
  83.201 +    
  83.202 +    if (numberOfChars == 0)
  83.203 +    {
  83.204 +        return false;
  83.205 +    }
  83.206 +    
  83.207 +    // Now allocate buffer.
  83.208 +    char* buffer = new char[bufferLength+1];
  83.209 +    
  83.210 +    numberOfChars = CFStringGetBytes(str,
  83.211 +                                     range,
  83.212 +                                     kCFStringEncodingUTF8,
  83.213 +                                     (char) '?',
  83.214 +                                     FALSE,
  83.215 +                                     (UInt8*) buffer,
  83.216 +                                     bufferLength,
  83.217 +                                     NULL);
  83.218 +    OVR_ASSERT_LOG(numberOfChars != 0, ("CFStringGetBytes failed."));
  83.219 +
  83.220 +    buffer[bufferLength] = '\0';
  83.221 +    *pResult = String(buffer);
  83.222 +    
  83.223 +    return true;
  83.224 +}
  83.225 +    
  83.226 +bool HIDDeviceManager::getVendorId(IOHIDDeviceRef device, UInt16* pResult)
  83.227 +{
  83.228 +    SInt32 result;
  83.229 +    
  83.230 +    if (!getIntProperty(device, CFSTR(kIOHIDVendorIDKey), &result))
  83.231 +    {
  83.232 +        return false;
  83.233 +    }
  83.234 +    
  83.235 +    *pResult = result;
  83.236 +
  83.237 +    return true;
  83.238 +}
  83.239 +    
  83.240 +bool HIDDeviceManager::getProductId(IOHIDDeviceRef device, UInt16* pResult)
  83.241 +{
  83.242 +    SInt32 result;
  83.243 +    
  83.244 +    if (!getIntProperty(device, CFSTR(kIOHIDProductIDKey), &result))
  83.245 +    {
  83.246 +        return false;
  83.247 +    }
  83.248 +    
  83.249 +    *pResult = result;
  83.250 +    
  83.251 +    return true;
  83.252 +}
  83.253 + 
  83.254 +bool HIDDeviceManager::getLocationId(IOHIDDeviceRef device, SInt32* pResult)
  83.255 +{
  83.256 +    SInt32 result;
  83.257 +    
  83.258 +    if (!getIntProperty(device, CFSTR(kIOHIDLocationIDKey), &result))
  83.259 +    {
  83.260 +        return false;
  83.261 +    }
  83.262 +        
  83.263 +    *pResult = result;
  83.264 +        
  83.265 +    return true;
  83.266 +}
  83.267 +    
  83.268 +bool HIDDeviceManager::getSerialNumberString(IOHIDDeviceRef device, String* pResult)
  83.269 +{
  83.270 + 
  83.271 +    if (!getStringProperty(device, CFSTR(kIOHIDSerialNumberKey), pResult))
  83.272 +    {
  83.273 +        return false;
  83.274 +    }
  83.275 +
  83.276 +    return true;
  83.277 +}
  83.278 +    
  83.279 +bool HIDDeviceManager::getPath(IOHIDDeviceRef device, String* pPath)
  83.280 +{
  83.281 +
  83.282 +    String transport;
  83.283 +    if (!getStringProperty(device, CFSTR(kIOHIDTransportKey), &transport))
  83.284 +    {
  83.285 +        return false;
  83.286 +    }
  83.287 +    
  83.288 +    UInt16 vendorId;
  83.289 +    if (!getVendorId(device, &vendorId))
  83.290 +    {
  83.291 +        return false;
  83.292 +    }
  83.293 +
  83.294 +    UInt16 productId;
  83.295 +    if (!getProductId(device, &productId))
  83.296 +    {
  83.297 +        return false;
  83.298 +    }
  83.299 +    
  83.300 +    String serialNumber;
  83.301 +	if (!getSerialNumberString(device, &serialNumber))
  83.302 +    {
  83.303 +        return false;
  83.304 +    }
  83.305 +    
  83.306 +
  83.307 +    StringBuffer buffer;
  83.308 +    buffer.AppendFormat("%s:vid=%04hx:pid=%04hx:ser=%s",
  83.309 +                            transport.ToCStr(),
  83.310 +                            vendorId,
  83.311 +                            productId,
  83.312 +                            serialNumber.ToCStr());
  83.313 +    
  83.314 +    *pPath = String(buffer);
  83.315 +    
  83.316 +    return true;
  83.317 +}
  83.318 +
  83.319 +bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor)
  83.320 +{
  83.321 +    if (!initializeManager())
  83.322 +    {
  83.323 +        return false;
  83.324 +    }
  83.325 +    
  83.326 +
  83.327 +	CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager);
  83.328 +    if (!deviceSet)
  83.329 +        return false;
  83.330 +    
  83.331 +	CFIndex deviceCount = CFSetGetCount(deviceSet);
  83.332 +    
  83.333 +    // Allocate a block of memory and read the set into it.
  83.334 +    IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount);
  83.335 +    CFSetGetValues(deviceSet, (const void **) devices);
  83.336 +    
  83.337 +
  83.338 +    // Iterate over devices.
  83.339 +    for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
  83.340 +    {
  83.341 +        IOHIDDeviceRef hidDev = devices[deviceIndex];
  83.342 +        
  83.343 +        if (!hidDev)
  83.344 +        {
  83.345 +            continue;
  83.346 +        }
  83.347 +        
  83.348 +        HIDDeviceDesc devDesc;
  83.349 +                
  83.350 +        if (getPath(hidDev, &(devDesc.Path)) &&
  83.351 +            initVendorProductVersion(hidDev, &devDesc) &&
  83.352 +            enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId) &&
  83.353 +            initUsage(hidDev, &devDesc))
  83.354 +        {
  83.355 +            initStrings(hidDev, &devDesc);
  83.356 +            initSerialNumber(hidDev, &devDesc);
  83.357 +
  83.358 +            // Look for the device to check if it is already opened.
  83.359 +            Ptr<DeviceCreateDesc> existingDevice = DevManager->FindHIDDevice(devDesc);
  83.360 +            // if device exists and it is opened then most likely the CreateHIDFile
  83.361 +            // will fail; therefore, we just set Enumerated to 'true' and continue.
  83.362 +            if (existingDevice && existingDevice->pDevice)
  83.363 +            {
  83.364 +                existingDevice->Enumerated = true;
  83.365 +                continue;
  83.366 +            }
  83.367 +            
  83.368 +            // Construct minimal device that the visitor callback can get feature reports from.
  83.369 +            OSX::HIDDevice device(this, hidDev);
  83.370 +            
  83.371 +            enumVisitor->Visit(device, devDesc);
  83.372 +        }
  83.373 +    }
  83.374 +    
  83.375 +    OVR_FREE(devices);
  83.376 +    CFRelease(deviceSet);
  83.377 +    
  83.378 +    return true;
  83.379 +}
  83.380 +
  83.381 +OVR::HIDDevice* HIDDeviceManager::Open(const String& path)
  83.382 +{
  83.383 +
  83.384 +    Ptr<OSX::HIDDevice> device = *new OSX::HIDDevice(this);
  83.385 +
  83.386 +    if (!device->HIDInitialize(path))
  83.387 +    {
  83.388 +        return NULL;
  83.389 +    }
  83.390 +
  83.391 +    device->AddRef();
  83.392 +    
  83.393 +    return device;
  83.394 +}
  83.395 +    
  83.396 +bool HIDDeviceManager::getFullDesc(IOHIDDeviceRef device, HIDDeviceDesc* desc)
  83.397 +{
  83.398 +        
  83.399 +    if (!initVendorProductVersion(device, desc))
  83.400 +    {
  83.401 +        return false;
  83.402 +    }
  83.403 +        
  83.404 +    if (!initUsage(device, desc))
  83.405 +    {
  83.406 +        return false;
  83.407 +    }
  83.408 +    
  83.409 +    if (!initSerialNumber(device, desc))
  83.410 +    {
  83.411 +        return false;
  83.412 +    }
  83.413 +    
  83.414 +    initStrings(device, desc);
  83.415 +        
  83.416 +    return true;
  83.417 +}
  83.418 +
  83.419 +// New USB device specified in the matching dictionary has been added (callback function)
  83.420 +void HIDDeviceManager::staticDeviceMatchingCallback(void *inContext,
  83.421 +                                                    IOReturn inResult,
  83.422 +                                                    void *inSender,
  83.423 +                                                    IOHIDDeviceRef inIOHIDDeviceRef)
  83.424 +{
  83.425 +    HIDDeviceManager* hidMgr = static_cast<HIDDeviceManager*>(inContext);
  83.426 +    HIDDeviceDesc hidDevDesc;
  83.427 +    hidMgr->getPath(inIOHIDDeviceRef, &hidDevDesc.Path);
  83.428 +    hidMgr->getFullDesc(inIOHIDDeviceRef, &hidDevDesc);
  83.429 +    
  83.430 +    hidMgr->DevManager->DetectHIDDevice(hidDevDesc);
  83.431 +}
  83.432 +
  83.433 +//-------------------------------------------------------------------------------------
  83.434 +// **** OSX::HIDDevice
  83.435 +
  83.436 +HIDDevice::HIDDevice(HIDDeviceManager* manager)
  83.437 + :  HIDManager(manager), InMinimalMode(false)
  83.438 +{
  83.439 +    Device = NULL;
  83.440 +    RepluggedNotificationPort = 0;
  83.441 +}
  83.442 +    
  83.443 +// This is a minimal constructor used during enumeration for us to pass
  83.444 +// a HIDDevice to the visit function (so that it can query feature reports).
  83.445 +HIDDevice::HIDDevice(HIDDeviceManager* manager, IOHIDDeviceRef device)
  83.446 +:   HIDManager(manager), Device(device), InMinimalMode(true)
  83.447 +{
  83.448 +    RepluggedNotificationPort = 0;
  83.449 +}
  83.450 +
  83.451 +HIDDevice::~HIDDevice()
  83.452 +{
  83.453 +    if (!InMinimalMode)
  83.454 +    {
  83.455 +        HIDShutdown();
  83.456 +    }
  83.457 +}
  83.458 +
  83.459 +bool HIDDevice::HIDInitialize(const String& path)
  83.460 +{
  83.461 +
  83.462 +    DevDesc.Path = path;
  83.463 +
  83.464 +    if (!openDevice())
  83.465 +    {
  83.466 +        LogText("OVR::OSX::HIDDevice - Failed to open HIDDevice: %s", path.ToCStr());
  83.467 +        return false;
  83.468 +    }
  83.469 +
  83.470 +    // Setup notification for when a device is unplugged and plugged back in.
  83.471 +    if (!setupDevicePluggedInNotification())
  83.472 +    {
  83.473 +        LogText("OVR::OSX::HIDDevice - Failed to setup notification for when device plugged back in.");
  83.474 +        closeDevice(false);
  83.475 +        return false;
  83.476 +    }
  83.477 +    
  83.478 +    HIDManager->DevManager->pThread->AddTicksNotifier(this);
  83.479 +
  83.480 +    
  83.481 +    LogText("OVR::OSX::HIDDevice - Opened '%s'\n"
  83.482 +            "                    Manufacturer:'%s'  Product:'%s'  Serial#:'%s'\n",
  83.483 +            DevDesc.Path.ToCStr(),
  83.484 +            DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(),
  83.485 +            DevDesc.SerialNumber.ToCStr());
  83.486 +    
  83.487 +    return true;
  83.488 +}
  83.489 +
  83.490 +bool HIDDevice::initInfo()
  83.491 +{
  83.492 +    // Device must have been successfully opened.
  83.493 +    OVR_ASSERT(Device);
  83.494 +    
  83.495 +    
  83.496 +    // Get report lengths.
  83.497 +    SInt32 bufferLength;
  83.498 +    bool getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxInputReportSizeKey), &bufferLength);
  83.499 +    OVR_ASSERT(getResult);
  83.500 +    InputReportBufferLength = (UInt16) bufferLength;
  83.501 +
  83.502 +    getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxOutputReportSizeKey), &bufferLength);
  83.503 +    OVR_ASSERT(getResult);
  83.504 +    OutputReportBufferLength = (UInt16) bufferLength;
  83.505 +
  83.506 +    getResult = HIDManager->getIntProperty(Device, CFSTR(kIOHIDMaxFeatureReportSizeKey), &bufferLength);
  83.507 +    OVR_ASSERT(getResult);
  83.508 +    FeatureReportBufferLength = (UInt16) bufferLength;
  83.509 +    
  83.510 +    
  83.511 +    if (ReadBufferSize < InputReportBufferLength)
  83.512 +    {
  83.513 +        OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
  83.514 +        return false;
  83.515 +    }
  83.516 +    
  83.517 +    // Get device desc.
  83.518 +    if (!HIDManager->getFullDesc(Device, &DevDesc))
  83.519 +    {
  83.520 +        OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device."));
  83.521 +        return false;
  83.522 +    }
  83.523 +    
  83.524 +    return true;
  83.525 +}
  83.526 +
  83.527 +void HIDDevice::staticDeviceAddedCallback(void* pContext, io_iterator_t iterator)
  83.528 +{
  83.529 +    HIDDevice* pDevice = (HIDDevice*) pContext;
  83.530 +    pDevice->deviceAddedCallback(iterator);
  83.531 +}
  83.532 +
  83.533 +void HIDDevice::deviceAddedCallback(io_iterator_t iterator)
  83.534 +{
  83.535 +
  83.536 +    if (Device == NULL)
  83.537 +    {
  83.538 +        if (openDevice())
  83.539 +        {
  83.540 +            LogText("OVR::OSX::HIDDevice - Reopened device : %s", DevDesc.Path.ToCStr());
  83.541 +
  83.542 +            Ptr<DeviceCreateDesc> existingHIDDev = HIDManager->DevManager->FindHIDDevice(DevDesc);
  83.543 +            if (existingHIDDev && existingHIDDev->pDevice)
  83.544 +            {
  83.545 +                HIDManager->DevManager->CallOnDeviceAdded(existingHIDDev);
  83.546 +            }
  83.547 +        }
  83.548 +    }
  83.549 +
  83.550 +    // Reset callback.
  83.551 +    while (IOIteratorNext(iterator))
  83.552 +        ;
  83.553 +}
  83.554 +    
  83.555 +bool HIDDevice::openDevice()
  83.556 +{
  83.557 +    
  83.558 +    // Have to iterate through devices again to generate paths.
  83.559 +	CFSetRef deviceSet = IOHIDManagerCopyDevices(HIDManager->HIDManager);
  83.560 +	CFIndex deviceCount = CFSetGetCount(deviceSet);
  83.561 +    
  83.562 +    // Allocate a block of memory and read the set into it.
  83.563 +    IOHIDDeviceRef* devices = (IOHIDDeviceRef*) OVR_ALLOC(sizeof(IOHIDDeviceRef) * deviceCount);
  83.564 +    CFSetGetValues(deviceSet, (const void **) devices);
  83.565 +    
  83.566 +    
  83.567 +    // Iterate over devices.
  83.568 +    IOHIDDeviceRef device = NULL;
  83.569 +
  83.570 +    for (CFIndex deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
  83.571 +    {
  83.572 +        IOHIDDeviceRef tmpDevice = devices[deviceIndex];
  83.573 +        
  83.574 +        if (!tmpDevice)
  83.575 +        {
  83.576 +            continue;
  83.577 +        }
  83.578 +        
  83.579 +        String path;
  83.580 +        if (!HIDManager->getPath(tmpDevice, &path))
  83.581 +        {
  83.582 +            continue;
  83.583 +        }
  83.584 +        
  83.585 +        if (path == DevDesc.Path)
  83.586 +        {
  83.587 +            device = tmpDevice;
  83.588 +            break;
  83.589 +        }
  83.590 +    }
  83.591 +    
  83.592 +    
  83.593 +    OVR_FREE(devices);
  83.594 +    
  83.595 +    if (!device)
  83.596 +    {
  83.597 +        CFRelease(deviceSet);
  83.598 +        return false;
  83.599 +    }
  83.600 +    
  83.601 +    // Attempt to open device.
  83.602 +    if (IOHIDDeviceOpen(device, kIOHIDOptionsTypeSeizeDevice)
  83.603 +        != kIOReturnSuccess)
  83.604 +    {
  83.605 +        CFRelease(deviceSet);
  83.606 +        return false;
  83.607 +    }
  83.608 +
  83.609 +    // Retain the device before we release the set.
  83.610 +    CFRetain(device);
  83.611 +    CFRelease(deviceSet);
  83.612 +    
  83.613 +    
  83.614 +    Device = device;
  83.615 +
  83.616 +    
  83.617 +    if (!initInfo())
  83.618 +    {
  83.619 +        IOHIDDeviceClose(Device, kIOHIDOptionsTypeSeizeDevice);
  83.620 +        CFRelease(Device);
  83.621 +        Device = NULL;
  83.622 +        return false;
  83.623 +    }
  83.624 +    
  83.625 +    
  83.626 +    // Setup the Run Loop and callbacks.
  83.627 +    IOHIDDeviceScheduleWithRunLoop(Device,
  83.628 +                                   HIDManager->getRunLoop(),
  83.629 +                                   kCFRunLoopDefaultMode);
  83.630 +    
  83.631 +    IOHIDDeviceRegisterInputReportCallback(Device,
  83.632 +                                           ReadBuffer,
  83.633 +                                           ReadBufferSize,
  83.634 +                                           staticHIDReportCallback,
  83.635 +                                           this);
  83.636 +
  83.637 +    IOHIDDeviceRegisterRemovalCallback(Device,
  83.638 +                                       staticDeviceRemovedCallback,
  83.639 +                                       this);
  83.640 +    
  83.641 +    return true;
  83.642 +}
  83.643 +    
  83.644 +void HIDDevice::HIDShutdown()
  83.645 +{
  83.646 +
  83.647 +    HIDManager->DevManager->pThread->RemoveTicksNotifier(this);
  83.648 +    
  83.649 +    if (Device != NULL) // Device may already have been closed if unplugged.
  83.650 +    {
  83.651 +        closeDevice(false);
  83.652 +    }
  83.653 +
  83.654 +    IOObjectRelease(RepluggedNotification);
  83.655 +    if (RepluggedNotificationPort)
  83.656 +        IONotificationPortDestroy(RepluggedNotificationPort);
  83.657 +    
  83.658 +    LogText("OVR::OSX::HIDDevice - HIDShutdown '%s'\n", DevDesc.Path.ToCStr());
  83.659 +}
  83.660 +
  83.661 +bool HIDDevice::setupDevicePluggedInNotification()
  83.662 +{
  83.663 +    
  83.664 +    // Setup notification when devices are plugged in.
  83.665 +    RepluggedNotificationPort = IONotificationPortCreate(kIOMasterPortDefault);
  83.666 +    
  83.667 +    CFRunLoopSourceRef notificationRunLoopSource =
  83.668 +        IONotificationPortGetRunLoopSource(RepluggedNotificationPort);
  83.669 +    
  83.670 +    CFRunLoopAddSource(HIDManager->getRunLoop(),
  83.671 +                       notificationRunLoopSource,
  83.672 +                       kCFRunLoopDefaultMode);
  83.673 +    
  83.674 +    CFMutableDictionaryRef matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
  83.675 +    
  83.676 +    // Have to specify vendorId and productId. Doesn't seem to accept additional
  83.677 +    // things like serial number.
  83.678 +    SInt32 vendorId = DevDesc.VendorId;
  83.679 +    CFNumberRef numberRef = CFNumberCreate(kCFAllocatorDefault,
  83.680 +                                           kCFNumberSInt32Type,
  83.681 +                                           &vendorId);
  83.682 +    CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);
  83.683 +    CFRelease(numberRef);
  83.684 +    
  83.685 +    SInt32 deviceProductId = DevDesc.ProductId;
  83.686 +    numberRef = CFNumberCreate(kCFAllocatorDefault,
  83.687 +                               kCFNumberSInt32Type,
  83.688 +                               &deviceProductId);
  83.689 +    CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef);
  83.690 +    CFRelease(numberRef);
  83.691 +    
  83.692 +    kern_return_t result =
  83.693 +            IOServiceAddMatchingNotification(RepluggedNotificationPort,
  83.694 +                                             kIOMatchedNotification,
  83.695 +                                             matchingDict,
  83.696 +                                             staticDeviceAddedCallback,
  83.697 +                                             this,
  83.698 +                                             &RepluggedNotification);
  83.699 +    
  83.700 +    if (result != KERN_SUCCESS)
  83.701 +    {
  83.702 +        CFRelease(RepluggedNotificationPort);
  83.703 +        RepluggedNotificationPort = 0;
  83.704 +        return false;
  83.705 +    }
  83.706 +    
  83.707 +    // Iterate through to arm.
  83.708 +    while (IOIteratorNext(RepluggedNotification))
  83.709 +    {
  83.710 +	}
  83.711 +    
  83.712 +    return true;
  83.713 +}
  83.714 +
  83.715 +void HIDDevice::closeDevice(bool wasUnplugged)
  83.716 +{
  83.717 +    OVR_ASSERT(Device != NULL);
  83.718 +    
  83.719 +    if (!wasUnplugged)
  83.720 +    {
  83.721 +        // Clear the registered callbacks.
  83.722 +        IOHIDDeviceRegisterInputReportCallback(Device,
  83.723 +                                               ReadBuffer,
  83.724 +                                               InputReportBufferLength,
  83.725 +                                               NULL,
  83.726 +                                               this);
  83.727 +        
  83.728 +        IOHIDDeviceRegisterRemovalCallback(Device, NULL, this);
  83.729 +        
  83.730 +        IOHIDDeviceUnscheduleFromRunLoop(Device,
  83.731 +                                         HIDManager->getRunLoop(),
  83.732 +                                         kCFRunLoopDefaultMode);
  83.733 +        IOHIDDeviceClose(Device, kIOHIDOptionsTypeNone);
  83.734 +    }
  83.735 +    
  83.736 +	CFRelease(Device);
  83.737 +    Device = NULL;
  83.738 +        
  83.739 +    LogText("OVR::OSX::HIDDevice - HID Device Closed '%s'\n", DevDesc.Path.ToCStr());
  83.740 +}
  83.741 +
  83.742 +void HIDDevice::staticHIDReportCallback(void* pContext,
  83.743 +                                        IOReturn result,
  83.744 +                                        void* pSender,
  83.745 +                                        IOHIDReportType reportType,
  83.746 +                                        uint32_t reportId,
  83.747 +                                        uint8_t* pReport,
  83.748 +                                        CFIndex reportLength)
  83.749 +{
  83.750 +    HIDDevice* pDevice = (HIDDevice*) pContext;
  83.751 +    return pDevice->hidReportCallback(pReport, (UInt32)reportLength);
  83.752 +}
  83.753 +
  83.754 +void HIDDevice::hidReportCallback(UByte* pData, UInt32 length)
  83.755 +{
  83.756 +    
  83.757 +    // We got data.
  83.758 +    if (Handler)
  83.759 +    {
  83.760 +        Handler->OnInputReport(pData, length);
  83.761 +    }
  83.762 +}
  83.763 +    
  83.764 +void HIDDevice::staticDeviceRemovedCallback(void* pContext, IOReturn result, void* pSender)
  83.765 +{
  83.766 +    HIDDevice* pDevice = (HIDDevice*) pContext;
  83.767 +    pDevice->deviceRemovedCallback();
  83.768 +}
  83.769 +    
  83.770 +void HIDDevice::deviceRemovedCallback()
  83.771 +{
  83.772 +    Ptr<HIDDevice> _this(this); // prevent from release
  83.773 +    
  83.774 +    Ptr<DeviceCreateDesc> existingHIDDev = HIDManager->DevManager->FindHIDDevice(DevDesc);
  83.775 +    if (existingHIDDev && existingHIDDev->pDevice)
  83.776 +    {
  83.777 +        HIDManager->DevManager->CallOnDeviceRemoved(existingHIDDev);
  83.778 +    }
  83.779 +    closeDevice(true);
  83.780 +}
  83.781 +
  83.782 +CFStringRef HIDDevice::generateRunLoopModeString(IOHIDDeviceRef device)
  83.783 +{
  83.784 +    const UInt32 safeBuffSize = 256;
  83.785 +    char nameBuff[safeBuffSize];
  83.786 +    OVR_sprintf(nameBuff, safeBuffSize, "%016lX", device);
  83.787 +  
  83.788 +    return CFStringCreateWithCString(NULL, nameBuff, kCFStringEncodingASCII);
  83.789 +}
  83.790 +    
  83.791 +bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length)
  83.792 +{
  83.793 +    
  83.794 +    if (!Device)
  83.795 +        return false;
  83.796 +    
  83.797 +    UByte reportID = data[0];
  83.798 +
  83.799 +    if (reportID == 0)
  83.800 +    {
  83.801 +        // Not using reports so remove from data packet.
  83.802 +        data++;
  83.803 +        length--;
  83.804 +    }
  83.805 +    
  83.806 +	IOReturn result = IOHIDDeviceSetReport( Device,
  83.807 +                                            kIOHIDReportTypeFeature,
  83.808 +                                            reportID,
  83.809 +                                            data,
  83.810 +                                            length);
  83.811 +    
  83.812 +    return (result == kIOReturnSuccess);
  83.813 +}
  83.814 +
  83.815 +bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length)
  83.816 +{
  83.817 +    if (!Device)
  83.818 +        return false;
  83.819 +    
  83.820 +    CFIndex bufferLength = length;
  83.821 +    
  83.822 +    // Report id is in first byte of the buffer.
  83.823 +	IOReturn result = IOHIDDeviceGetReport(Device, kIOHIDReportTypeFeature, data[0], data, &bufferLength);
  83.824 +	
  83.825 +    return (result == kIOReturnSuccess);
  83.826 +}
  83.827 +   
  83.828 +UInt64 HIDDevice::OnTicks(UInt64 ticksMks)
  83.829 +{
  83.830 +    
  83.831 +    if (Handler)
  83.832 +    {
  83.833 +        return Handler->OnTicks(ticksMks);
  83.834 +    }
  83.835 +    
  83.836 +    return DeviceManagerThread::Notifier::OnTicks(ticksMks);
  83.837 +}
  83.838 +
  83.839 +HIDDeviceManager* HIDDeviceManager::CreateInternal(OSX::DeviceManager* devManager)
  83.840 +{
  83.841 +        
  83.842 +    if (!System::IsInitialized())
  83.843 +    {
  83.844 +        // Use custom message, since Log is not yet installed.
  83.845 +        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
  83.846 +                            LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
  83.847 +        return 0;
  83.848 +    }
  83.849 +
  83.850 +    Ptr<OSX::HIDDeviceManager> manager = *new OSX::HIDDeviceManager(devManager);
  83.851 +
  83.852 +    if (manager)
  83.853 +    {
  83.854 +        if (manager->Initialize())
  83.855 +        {
  83.856 +            manager->AddRef();
  83.857 +        }
  83.858 +        else
  83.859 +        {
  83.860 +            manager.Clear();
  83.861 +        }
  83.862 +    }
  83.863 +
  83.864 +    return manager.GetPtr();
  83.865 +}
  83.866 +    
  83.867 +} // namespace OSX
  83.868 +
  83.869 +//-------------------------------------------------------------------------------------
  83.870 +// ***** Creation
  83.871 +
  83.872 +// Creates a new HIDDeviceManager and initializes OVR.
  83.873 +HIDDeviceManager* HIDDeviceManager::Create()
  83.874 +{
  83.875 +    OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet."));
  83.876 +    
  83.877 +    if (!System::IsInitialized())
  83.878 +    {
  83.879 +        // Use custom message, since Log is not yet installed.
  83.880 +        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
  83.881 +            LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
  83.882 +        return 0;
  83.883 +    }
  83.884 +
  83.885 +    Ptr<OSX::HIDDeviceManager> manager = *new OSX::HIDDeviceManager(NULL);
  83.886 +    
  83.887 +    if (manager)
  83.888 +    {
  83.889 +        if (manager->Initialize())
  83.890 +        {
  83.891 +            manager->AddRef();
  83.892 +        }
  83.893 +        else
  83.894 +        {
  83.895 +            manager.Clear();
  83.896 +        }
  83.897 +    }
  83.898 +
  83.899 +    return manager.GetPtr();
  83.900 +}
  83.901 +
  83.902 +} // namespace OVR
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/libovr/Src/osx/OVR_OSX_HIDDevice.h	Sat Sep 14 16:14:59 2013 +0300
    84.3 @@ -0,0 +1,149 @@
    84.4 +/************************************************************************************
    84.5 +Filename    :   OVR_OSX_HIDDevice.h
    84.6 +Content     :   OSX HID device implementation.
    84.7 +Created     :   February 26, 2013
    84.8 +Authors     :   Lee Cooper
    84.9 +
   84.10 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   84.11 +
   84.12 +Use of this software is subject to the terms of the Oculus license
   84.13 +agreement provided at the time of installation or download, or which
   84.14 +otherwise accompanies this software in either electronic or hard copy form.
   84.15 +
   84.16 +*************************************************************************************/
   84.17 +
   84.18 +#ifndef OVR_OSX_HIDDevice_h
   84.19 +#define OVR_OSX_HIDDevice_h
   84.20 +
   84.21 +#include "OVR_HIDDevice.h"
   84.22 +
   84.23 +#include "OVR_OSX_DeviceManager.h"
   84.24 +
   84.25 +#include <IOKit/IOKitLib.h>
   84.26 +
   84.27 +namespace OVR { namespace OSX {
   84.28 +
   84.29 +class HIDDeviceManager;
   84.30 +
   84.31 +//-------------------------------------------------------------------------------------
   84.32 +// ***** OSX HIDDevice
   84.33 +
   84.34 +class HIDDevice : public OVR::HIDDevice, public DeviceManagerThread::Notifier
   84.35 +{
   84.36 +private:
   84.37 +    friend class HIDDeviceManager;
   84.38 +
   84.39 +public:
   84.40 +    HIDDevice(HIDDeviceManager* manager);
   84.41 +
   84.42 +    // This is a minimal constructor used during enumeration for us to pass
   84.43 +    // a HIDDevice to the visit function (so that it can query feature reports).
   84.44 +    HIDDevice(HIDDeviceManager* manager, IOHIDDeviceRef device);
   84.45 +    
   84.46 +    virtual ~HIDDevice();
   84.47 +
   84.48 +    bool HIDInitialize(const String& path);
   84.49 +    void HIDShutdown();
   84.50 +    
   84.51 +    virtual bool SetFeatureReport(UByte* data, UInt32 length);
   84.52 +	virtual bool GetFeatureReport(UByte* data, UInt32 length);
   84.53 +
   84.54 +    bool Write(UByte* data, UInt32 length);
   84.55 +
   84.56 +    bool Read(UByte* pData, UInt32 length, UInt32 timeoutMilliS);
   84.57 +    bool ReadBlocking(UByte* pData, UInt32 length);
   84.58 +
   84.59 +
   84.60 +    // DeviceManagerThread::Notifier
   84.61 +    UInt64 OnTicks(UInt64 ticksMks);
   84.62 +    
   84.63 +private:
   84.64 +    bool initInfo();
   84.65 +    bool openDevice();
   84.66 +    void closeDevice(bool wasUnplugged);
   84.67 +    bool setupDevicePluggedInNotification();
   84.68 +    CFStringRef generateRunLoopModeString(IOHIDDeviceRef device);
   84.69 +    
   84.70 +    static void staticHIDReportCallback(void* pContext,
   84.71 +                                        IOReturn result,
   84.72 +                                        void* pSender,
   84.73 +                                        IOHIDReportType reportType,
   84.74 +                                        uint32_t reportId,
   84.75 +                                        uint8_t* pReport,
   84.76 +                                        CFIndex reportLength);
   84.77 +    void hidReportCallback(UByte* pData, UInt32 length);
   84.78 +
   84.79 +    static void staticDeviceRemovedCallback(void* pContext,
   84.80 +                                            IOReturn result,
   84.81 +                                            void* pSender);
   84.82 +    void deviceRemovedCallback();
   84.83 +    
   84.84 +    static void staticDeviceAddedCallback(void* pContext,
   84.85 +                                          io_iterator_t iterator);
   84.86 +    void deviceAddedCallback(io_iterator_t iterator);
   84.87 +    
   84.88 +    bool                    InMinimalMode;
   84.89 +    HIDDeviceManager*       HIDManager;
   84.90 +    IOHIDDeviceRef          Device;
   84.91 +    HIDDeviceDesc           DevDesc;
   84.92 +    
   84.93 +    enum { ReadBufferSize = 96 };
   84.94 +    UByte                   ReadBuffer[ReadBufferSize];
   84.95 +
   84.96 +    UInt16                  InputReportBufferLength;
   84.97 +    UInt16                  OutputReportBufferLength;
   84.98 +    UInt16                  FeatureReportBufferLength;
   84.99 +    
  84.100 +    IONotificationPortRef   RepluggedNotificationPort;
  84.101 +    io_iterator_t           RepluggedNotification;
  84.102 +};
  84.103 +
  84.104 +
  84.105 +//-------------------------------------------------------------------------------------
  84.106 +// ***** OSX HIDDeviceManager
  84.107 +
  84.108 +class HIDDeviceManager : public OVR::HIDDeviceManager
  84.109 +{
  84.110 +	friend class HIDDevice;
  84.111 +
  84.112 +public:
  84.113 +    HIDDeviceManager(OSX::DeviceManager* Manager);
  84.114 +    virtual ~HIDDeviceManager();
  84.115 +
  84.116 +    virtual bool Initialize();
  84.117 +    virtual void Shutdown();
  84.118 +
  84.119 +    virtual bool Enumerate(HIDEnumerateVisitor* enumVisitor);
  84.120 +    virtual OVR::HIDDevice* Open(const String& path);
  84.121 +
  84.122 +    static HIDDeviceManager* CreateInternal(DeviceManager* manager);
  84.123 +    
  84.124 +private:
  84.125 +    CFRunLoopRef getRunLoop();
  84.126 +    bool initializeManager();
  84.127 +    bool initVendorProductVersion(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc);
  84.128 +    bool initUsage(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc);
  84.129 +    bool initStrings(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc);
  84.130 +    bool initSerialNumber(IOHIDDeviceRef device, HIDDeviceDesc* pDevDesc);
  84.131 +    bool getVendorId(IOHIDDeviceRef device, UInt16* pResult);
  84.132 +    bool getProductId(IOHIDDeviceRef device, UInt16* pResult);
  84.133 +    bool getLocationId(IOHIDDeviceRef device, SInt32* pResult);
  84.134 +    bool getSerialNumberString(IOHIDDeviceRef device, String* pResult);
  84.135 +    bool getPath(IOHIDDeviceRef device, String* pPath);
  84.136 +    bool getIntProperty(IOHIDDeviceRef device, CFStringRef key, int32_t* pResult);
  84.137 +    bool getStringProperty(IOHIDDeviceRef device, CFStringRef propertyName, String* pResult);
  84.138 +    bool getFullDesc(IOHIDDeviceRef device, HIDDeviceDesc* desc);
  84.139 +    
  84.140 +    static void staticDeviceMatchingCallback(void *inContext,
  84.141 +                                             IOReturn inResult,
  84.142 +                                             void *inSender,
  84.143 +                                             IOHIDDeviceRef inIOHIDDeviceRef);
  84.144 +    
  84.145 +    DeviceManager* DevManager;
  84.146 +
  84.147 +    IOHIDManagerRef HIDManager;
  84.148 +};
  84.149 +
  84.150 +}} // namespace OVR::OSX
  84.151 +
  84.152 +#endif // OVR_OSX_HIDDevice_h
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/libovr/Src/osx/OVR_OSX_HMDDevice.cpp	Sat Sep 14 16:14:59 2013 +0300
    85.3 @@ -0,0 +1,400 @@
    85.4 +/************************************************************************************
    85.5 +
    85.6 +Filename    :   OVR_OSX_HMDDevice.cpp
    85.7 +Content     :   OSX Interface to HMD - detects HMD display
    85.8 +Created     :   September 21, 2012
    85.9 +Authors     :   Michael Antonov
   85.10 +
   85.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   85.12 +
   85.13 +Use of this software is subject to the terms of the Oculus license
   85.14 +agreement provided at the time of installation or download, or which
   85.15 +otherwise accompanies this software in either electronic or hard copy form.
   85.16 +
   85.17 +*************************************************************************************/
   85.18 +
   85.19 +#include "OVR_OSX_HMDDevice.h"
   85.20 +#include <CoreGraphics/CGDirectDisplay.h>
   85.21 +#include <CoreGraphics/CGDisplayConfiguration.h>
   85.22 +#include <CoreFoundation/CoreFoundation.h>
   85.23 +#include <CoreFoundation/CFString.h>
   85.24 +#include <IOKit/graphics/IOGraphicsLib.h>
   85.25 +
   85.26 +namespace OVR { namespace OSX {
   85.27 +
   85.28 +//-------------------------------------------------------------------------------------
   85.29 +
   85.30 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory, 
   85.31 +                                         UInt32 vend, UInt32 prod, const String& displayDeviceName, long dispId)
   85.32 +        : DeviceCreateDesc(factory, Device_HMD),
   85.33 +          DisplayDeviceName(displayDeviceName),
   85.34 +          DesktopX(0), DesktopY(0), Contents(0),
   85.35 +          HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0),
   85.36 +          DisplayId(dispId)
   85.37 +{
   85.38 +    /* //??????????
   85.39 +    char idstring[9];
   85.40 +    idstring[0] = 'A'-1+((vend>>10) & 31);
   85.41 +    idstring[1] = 'A'-1+((vend>>5) & 31);
   85.42 +    idstring[2] = 'A'-1+((vend>>0) & 31);
   85.43 +    snprintf(idstring+3, 5, "%04d", prod);
   85.44 +    DeviceId = idstring;*/
   85.45 +    DeviceId = DisplayDeviceName;
   85.46 +}
   85.47 +
   85.48 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other)
   85.49 +        : DeviceCreateDesc(other.pFactory, Device_HMD),
   85.50 +          DeviceId(other.DeviceId), DisplayDeviceName(other.DisplayDeviceName),
   85.51 +          DesktopX(other.DesktopX), DesktopY(other.DesktopY), Contents(other.Contents),
   85.52 +          HResolution(other.HResolution), VResolution(other.VResolution),
   85.53 +          HScreenSize(other.HScreenSize), VScreenSize(other.VScreenSize),
   85.54 +          DisplayId(other.DisplayId)
   85.55 +{
   85.56 +}
   85.57 +
   85.58 +HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCreateDesc& other,
   85.59 +                                                                  DeviceCreateDesc** pcandidate) const
   85.60 +{
   85.61 +    if ((other.Type != Device_HMD) || (other.pFactory != pFactory))
   85.62 +        return Match_None;
   85.63 +
   85.64 +    // There are several reasons we can come in here:
   85.65 +    //   a) Matching this HMD Monitor created desc to OTHER HMD Monitor desc
   85.66 +    //          - Require exact device DeviceId/DeviceName match
   85.67 +    //   b) Matching SensorDisplayInfo created desc to OTHER HMD Monitor desc
   85.68 +    //          - This DeviceId is empty; becomes candidate
   85.69 +    //   c) Matching this HMD Monitor created desc to SensorDisplayInfo desc
   85.70 +    //          - This other.DeviceId is empty; becomes candidate
   85.71 +
   85.72 +    const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
   85.73 +
   85.74 +    if ((DeviceId == s2.DeviceId) &&
   85.75 +        (DisplayId == s2.DisplayId))
   85.76 +    {
   85.77 +        // Non-null DeviceId may match while size is different if screen size was overwritten
   85.78 +        // by SensorDisplayInfo in prior iteration.
   85.79 +        if (!DeviceId.IsEmpty() ||
   85.80 +             ((HScreenSize == s2.HScreenSize) &&
   85.81 +              (VScreenSize == s2.VScreenSize)) )
   85.82 +        {            
   85.83 +            *pcandidate = 0;
   85.84 +            return Match_Found;
   85.85 +        }
   85.86 +    }
   85.87 +
   85.88 +
   85.89 +    // DisplayInfo takes precedence, although we try to match it first.
   85.90 +    if ((HResolution == s2.HResolution) &&
   85.91 +        (VResolution == s2.VResolution) &&
   85.92 +        (HScreenSize == s2.HScreenSize) &&
   85.93 +        (VScreenSize == s2.VScreenSize))
   85.94 +    {
   85.95 +        if (DeviceId.IsEmpty() && !s2.DeviceId.IsEmpty())
   85.96 +        {
   85.97 +            *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
   85.98 +            return Match_Candidate;
   85.99 +        }
  85.100 +
  85.101 +        *pcandidate = 0;
  85.102 +        return Match_Found;
  85.103 +    }    
  85.104 +    
  85.105 +    // SensorDisplayInfo may override resolution settings, so store as candidiate.
  85.106 +    if (s2.DeviceId.IsEmpty() && s2.DisplayId == 0)
  85.107 +    {        
  85.108 +        *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);        
  85.109 +        return Match_Candidate;
  85.110 +    }
  85.111 +    // OTHER HMD Monitor desc may initialize DeviceName/Id
  85.112 +    else if (DeviceId.IsEmpty() && DisplayId == 0)
  85.113 +    {
  85.114 +        *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);        
  85.115 +        return Match_Candidate;
  85.116 +    }
  85.117 +    
  85.118 +    return Match_None;
  85.119 +}
  85.120 +
  85.121 +
  85.122 +bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, bool* newDeviceFlag)
  85.123 +{
  85.124 +    // This candidate was the the "best fit" to apply sensor DisplayInfo to.
  85.125 +    OVR_ASSERT(other.Type == Device_HMD);
  85.126 +    
  85.127 +    const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
  85.128 +
  85.129 +    // Force screen size on resolution from SensorDisplayInfo.
  85.130 +    // We do this because USB detection is more reliable as compared to HDMI EDID,
  85.131 +    // which may be corrupted by splitter reporting wrong monitor 
  85.132 +    if (s2.DeviceId.IsEmpty() && s2.DisplayId == 0)
  85.133 +    {
  85.134 +        // disconnected HMD: replace old descriptor by the 'fake' one.
  85.135 +        HScreenSize = s2.HScreenSize;
  85.136 +        VScreenSize = s2.VScreenSize;
  85.137 +        Contents |= Contents_Screen;
  85.138 +
  85.139 +        if (s2.Contents & HMDDeviceCreateDesc::Contents_Distortion)
  85.140 +        {
  85.141 +            memcpy(DistortionK, s2.DistortionK, sizeof(float)*4);
  85.142 +            Contents |= Contents_Distortion;
  85.143 +        }
  85.144 +        DeviceId          = s2.DeviceId;
  85.145 +        DisplayId         = s2.DisplayId;
  85.146 +        DisplayDeviceName = s2.DisplayDeviceName;
  85.147 +        if (newDeviceFlag) *newDeviceFlag = true;
  85.148 +    }
  85.149 +    else if (DeviceId.IsEmpty())
  85.150 +    {
  85.151 +        // This branch is executed when 'fake' HMD descriptor is being replaced by
  85.152 +        // the real one.
  85.153 +        DeviceId          = s2.DeviceId;
  85.154 +        DisplayId         = s2.DisplayId;
  85.155 +        DisplayDeviceName = s2.DisplayDeviceName;
  85.156 +        if (newDeviceFlag) *newDeviceFlag = true;
  85.157 +    }
  85.158 +    else
  85.159 +    {
  85.160 +        if (newDeviceFlag) *newDeviceFlag = false;
  85.161 +    }
  85.162 +
  85.163 +    return true;
  85.164 +}
  85.165 +
  85.166 +    
  85.167 +//-------------------------------------------------------------------------------------
  85.168 +
  85.169 +
  85.170 +//-------------------------------------------------------------------------------------
  85.171 +// ***** HMDDeviceFactory
  85.172 +
  85.173 +HMDDeviceFactory HMDDeviceFactory::Instance;
  85.174 +
  85.175 +void HMDDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
  85.176 +{
  85.177 +    CGDirectDisplayID Displays[32];
  85.178 +    uint32_t NDisplays = 0;
  85.179 +    CGGetOnlineDisplayList(32, Displays, &NDisplays);
  85.180 +
  85.181 +    for (int i = 0; i < NDisplays; i++)
  85.182 +    {
  85.183 +        io_service_t port = CGDisplayIOServicePort(Displays[i]);
  85.184 +        CFDictionaryRef DispInfo = IODisplayCreateInfoDictionary(port, kIODisplayMatchingInfo);
  85.185 +
  85.186 +        uint32_t vendor = CGDisplayVendorNumber(Displays[i]);
  85.187 +        uint32_t product = CGDisplayModelNumber(Displays[i]);
  85.188 +        unsigned mwidth = (unsigned)CGDisplayPixelsWide(Displays[i]);
  85.189 +        unsigned mheight = (unsigned)CGDisplayPixelsHigh(Displays[i]);
  85.190 +        CGRect desktop = CGDisplayBounds(Displays[i]);
  85.191 +        
  85.192 +        if (vendor == 16082 && product == 1)
  85.193 +        {
  85.194 +            char idstring[9];
  85.195 +            idstring[0] = 'A'-1+((vendor>>10) & 31);
  85.196 +            idstring[1] = 'A'-1+((vendor>>5) & 31);
  85.197 +            idstring[2] = 'A'-1+((vendor>>0) & 31);
  85.198 +            snprintf(idstring+3, 5, "%04d", product);
  85.199 +
  85.200 +            HMDDeviceCreateDesc hmdCreateDesc(this, vendor, product, idstring, Displays[i]);
  85.201 +            
  85.202 +			if (product == 2)
  85.203 +			{
  85.204 +                hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y,
  85.205 +                                                  mwidth, mheight, 0.12096f, 0.06804f);
  85.206 +			}
  85.207 +			else
  85.208 +			{
  85.209 +				if (hmdCreateDesc.Is7Inch())
  85.210 +				{
  85.211 +					// Physical dimension of SLA screen.
  85.212 +					hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y,
  85.213 +                                                      mwidth, mheight, 0.14976f, 0.0936f);
  85.214 +				}
  85.215 +				else
  85.216 +				{
  85.217 +					hmdCreateDesc.SetScreenParameters(desktop.origin.x, desktop.origin.y,
  85.218 +                                                      mwidth, mheight, 0.12096f, 0.0756f);
  85.219 +				}
  85.220 +			}
  85.221 +
  85.222 +            OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %x:%x\n", vendor, product));
  85.223 +            
  85.224 +            // Notify caller about detected device. This will call EnumerateAddDevice
  85.225 +            // if the this is the first time device was detected.
  85.226 +            visitor.Visit(hmdCreateDesc);
  85.227 +        }
  85.228 +        CFRelease(DispInfo);
  85.229 +    }
  85.230 +}
  85.231 +
  85.232 +DeviceBase* HMDDeviceCreateDesc::NewDeviceInstance()
  85.233 +{
  85.234 +    return new HMDDevice(this);
  85.235 +}
  85.236 +
  85.237 +bool HMDDeviceCreateDesc::Is7Inch() const
  85.238 +{
  85.239 +    return (strstr(DeviceId.ToCStr(), "OVR0001") != 0) || (Contents & Contents_7Inch);
  85.240 +}
  85.241 +
  85.242 +Profile* HMDDeviceCreateDesc::GetProfileAddRef() const
  85.243 +{
  85.244 +    // Create device may override profile name, so get it from there is possible.
  85.245 +    ProfileManager* profileManager = GetManagerImpl()->GetProfileManager();
  85.246 +    ProfileType     profileType    = GetProfileType();
  85.247 +    const char *    profileName    = pDevice ?
  85.248 +                        ((HMDDevice*)pDevice)->GetProfileName() :
  85.249 +                        profileManager->GetDefaultProfileName(profileType);
  85.250 +
  85.251 +    return profileName ?
  85.252 +        profileManager->LoadProfile(profileType, profileName) :
  85.253 +        profileManager->GetDeviceDefaultProfile(profileType);
  85.254 +}
  85.255 +
  85.256 +bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
  85.257 +{
  85.258 +    if ((info->InfoClassType != Device_HMD) &&
  85.259 +        (info->InfoClassType != Device_None))
  85.260 +        return false;
  85.261 +
  85.262 +    bool is7Inch = Is7Inch();
  85.263 +
  85.264 +    OVR_strcpy(info->ProductName,  DeviceInfo::MaxNameLength,
  85.265 +               is7Inch ? "Oculus Rift DK1" :
  85.266 +			   ((HResolution >= 1920) ? "Oculus Rift DK HD" : "Oculus Rift DK1-Prototype") );
  85.267 +    OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, "Oculus VR");
  85.268 +    info->Type    = Device_HMD;
  85.269 +    info->Version = 0;
  85.270 +
  85.271 +    // Display detection.
  85.272 +    if (info->InfoClassType == Device_HMD)
  85.273 +    {
  85.274 +        HMDInfo* hmdInfo = static_cast<HMDInfo*>(info);
  85.275 +
  85.276 +        hmdInfo->DesktopX               = DesktopX;
  85.277 +        hmdInfo->DesktopY               = DesktopY;
  85.278 +        hmdInfo->HResolution            = HResolution;
  85.279 +        hmdInfo->VResolution            = VResolution;
  85.280 +        hmdInfo->HScreenSize            = HScreenSize;
  85.281 +        hmdInfo->VScreenSize            = VScreenSize;
  85.282 +        hmdInfo->VScreenCenter          = VScreenSize * 0.5f;
  85.283 +        hmdInfo->InterpupillaryDistance = 0.064f;  // Default IPD; should be configurable.
  85.284 +        hmdInfo->LensSeparationDistance = 0.0635f;
  85.285 +
  85.286 +        // Obtain IPD from profile.
  85.287 +        Ptr<Profile> profile = *GetProfileAddRef();
  85.288 +
  85.289 +        if (profile)
  85.290 +        {
  85.291 +            hmdInfo->InterpupillaryDistance = profile->GetIPD();
  85.292 +            // TBD: Switch on EyeCup type.
  85.293 +        }
  85.294 +        
  85.295 +        if (Contents & Contents_Distortion)
  85.296 +        {
  85.297 +            memcpy(hmdInfo->DistortionK, DistortionK, sizeof(float)*4);
  85.298 +        }
  85.299 +        else
  85.300 +        {
  85.301 +            if (is7Inch)
  85.302 +            {
  85.303 +                // 7" screen.
  85.304 +                hmdInfo->DistortionK[0]        = 1.0f;
  85.305 +                hmdInfo->DistortionK[1]        = 0.22f;
  85.306 +                hmdInfo->DistortionK[2]        = 0.24f;
  85.307 +                hmdInfo->EyeToScreenDistance   = 0.041f;                
  85.308 +            }
  85.309 +            else
  85.310 +            {
  85.311 +                hmdInfo->DistortionK[0]        = 1.0f;
  85.312 +                hmdInfo->DistortionK[1]        = 0.18f;
  85.313 +                hmdInfo->DistortionK[2]        = 0.115f;
  85.314 +
  85.315 +                if (HResolution == 1920)
  85.316 +                    hmdInfo->EyeToScreenDistance = 0.040f;
  85.317 +                else
  85.318 +                    hmdInfo->EyeToScreenDistance = 0.0387f;
  85.319 +            }
  85.320 +
  85.321 +            hmdInfo->ChromaAbCorrection[0] = 0.996f;
  85.322 +            hmdInfo->ChromaAbCorrection[1] = -0.004f;
  85.323 +            hmdInfo->ChromaAbCorrection[2] = 1.014f;
  85.324 +            hmdInfo->ChromaAbCorrection[3] = 0.0f;
  85.325 +        }
  85.326 +
  85.327 +        OVR_strcpy(hmdInfo->DisplayDeviceName, sizeof(hmdInfo->DisplayDeviceName),
  85.328 +                   DisplayDeviceName.ToCStr());
  85.329 +        hmdInfo->DisplayId = DisplayId;
  85.330 +    }
  85.331 +
  85.332 +    return true;
  85.333 +}
  85.334 +
  85.335 +//-------------------------------------------------------------------------------------
  85.336 +// ***** HMDDevice
  85.337 +
  85.338 +HMDDevice::HMDDevice(HMDDeviceCreateDesc* createDesc)
  85.339 +    : OVR::DeviceImpl<OVR::HMDDevice>(createDesc, 0)
  85.340 +{
  85.341 +}
  85.342 +HMDDevice::~HMDDevice()
  85.343 +{
  85.344 +}
  85.345 +
  85.346 +bool HMDDevice::Initialize(DeviceBase* parent)
  85.347 +{
  85.348 +    pParent = parent;
  85.349 +
  85.350 +    // Initialize user profile to default for device.
  85.351 +    ProfileManager* profileManager = GetManager()->GetProfileManager();    
  85.352 +    ProfileName = profileManager->GetDefaultProfileName(getDesc()->GetProfileType());
  85.353 +
  85.354 +    return true;
  85.355 +}
  85.356 +void HMDDevice::Shutdown()
  85.357 +{
  85.358 +    ProfileName.Clear();
  85.359 +    pCachedProfile.Clear();
  85.360 +    pParent.Clear();
  85.361 +}
  85.362 +
  85.363 +Profile* HMDDevice::GetProfile() const
  85.364 +{    
  85.365 +    if (!pCachedProfile)
  85.366 +        pCachedProfile = *getDesc()->GetProfileAddRef();
  85.367 +    return pCachedProfile.GetPtr();
  85.368 +}
  85.369 +
  85.370 +const char* HMDDevice::GetProfileName() const
  85.371 +{
  85.372 +    return ProfileName.ToCStr();
  85.373 +}
  85.374 +
  85.375 +bool HMDDevice::SetProfileName(const char* name)
  85.376 +{
  85.377 +    pCachedProfile.Clear();
  85.378 +    if (!name)
  85.379 +    {
  85.380 +        ProfileName.Clear();
  85.381 +        return 0;
  85.382 +    }
  85.383 +    if (GetManager()->GetProfileManager()->HasProfile(getDesc()->GetProfileType(), name))
  85.384 +    {
  85.385 +        ProfileName = name;
  85.386 +        return true;
  85.387 +    }
  85.388 +    return false;
  85.389 +}
  85.390 +
  85.391 +OVR::SensorDevice* HMDDevice::GetSensor()
  85.392 +{
  85.393 +    // Just return first sensor found since we have no way to match it yet.
  85.394 +    OVR::SensorDevice* sensor = GetManager()->EnumerateDevices<SensorDevice>().CreateDevice();
  85.395 +    if (sensor)
  85.396 +        sensor->SetCoordinateFrame(SensorDevice::Coord_HMD);
  85.397 +    return sensor;
  85.398 +}
  85.399 +
  85.400 +
  85.401 +}} // namespace OVR::OSX
  85.402 +
  85.403 +
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/libovr/Src/osx/OVR_OSX_HMDDevice.h	Sat Sep 14 16:14:59 2013 +0300
    86.3 @@ -0,0 +1,160 @@
    86.4 +/************************************************************************************
    86.5 +
    86.6 +Filename    :   OVR_OSX_HMDDevice.h
    86.7 +Content     :   OSX HMDDevice implementation
    86.8 +Created     :   September 21, 2012
    86.9 +Authors     :   Michael Antonov
   86.10 +
   86.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   86.12 +
   86.13 +Use of this software is subject to the terms of the Oculus license
   86.14 +agreement provided at the time of installation or download, or which
   86.15 +otherwise accompanies this software in either electronic or hard copy form.
   86.16 +
   86.17 +*************************************************************************************/
   86.18 +
   86.19 +#ifndef OVR_OSX_HMDDevice_h
   86.20 +#define OVR_OSX_HMDDevice_h
   86.21 +
   86.22 +#include "OVR_DeviceImpl.h"
   86.23 +#include <Kernel/OVR_String.h>
   86.24 +#include "OVR_Profile.h"
   86.25 +
   86.26 +namespace OVR { namespace OSX {
   86.27 +
   86.28 +class HMDDevice;
   86.29 +
   86.30 +
   86.31 +//-------------------------------------------------------------------------------------
   86.32 +
   86.33 +// HMDDeviceFactory enumerates attached Oculus HMD devices.
   86.34 +//
   86.35 +// This is currently done by matching monitor device strings.
   86.36 +
   86.37 +class HMDDeviceFactory : public DeviceFactory
   86.38 +{
   86.39 +public:
   86.40 +    static HMDDeviceFactory Instance;
   86.41 +
   86.42 +    // Enumerates devices, creating and destroying relevant objects in manager.
   86.43 +    virtual void EnumerateDevices(EnumerateVisitor& visitor);
   86.44 +
   86.45 +protected:
   86.46 +    DeviceManager* getManager() const { return (DeviceManager*) pManager; }
   86.47 +};
   86.48 +
   86.49 +
   86.50 +class HMDDeviceCreateDesc : public DeviceCreateDesc
   86.51 +{
   86.52 +    friend class HMDDevice;
   86.53 +
   86.54 +protected:
   86.55 +    enum
   86.56 +    {
   86.57 +        Contents_Screen     = 1,
   86.58 +        Contents_Distortion = 2,
   86.59 +        Contents_7Inch      = 4,
   86.60 +    };
   86.61 +
   86.62 +public:
   86.63 +
   86.64 +    HMDDeviceCreateDesc(DeviceFactory* factory,
   86.65 +                        UInt32 vendor, UInt32 product, const String& displayDeviceName, long dispId);
   86.66 +    HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other);
   86.67 +
   86.68 +    virtual DeviceCreateDesc* Clone() const
   86.69 +    {
   86.70 +        return new HMDDeviceCreateDesc(*this);
   86.71 +    }
   86.72 +
   86.73 +    virtual DeviceBase* NewDeviceInstance();
   86.74 +
   86.75 +    virtual MatchResult MatchDevice(const DeviceCreateDesc& other,
   86.76 +                                    DeviceCreateDesc**) const;
   86.77 +
   86.78 +    virtual bool        UpdateMatchedCandidate(const DeviceCreateDesc&, bool* newDeviceFlag = NULL);
   86.79 +
   86.80 +    virtual bool GetDeviceInfo(DeviceInfo* info) const;
   86.81 +
   86.82 +    // Requests the currently used default profile. This profile affects the
   86.83 +    // settings reported by HMDInfo. 
   86.84 +    Profile* GetProfileAddRef() const;
   86.85 +
   86.86 +    ProfileType GetProfileType() const
   86.87 +    {
   86.88 +        return (HResolution >= 1920) ? Profile_RiftDKHD : Profile_RiftDK1;
   86.89 +    }
   86.90 +	
   86.91 +    void  SetScreenParameters(int x, int y, unsigned hres, unsigned vres, float hsize, float vsize)
   86.92 +    {
   86.93 +        DesktopX = x;
   86.94 +        DesktopY = y;
   86.95 +        HResolution = hres;
   86.96 +        VResolution = vres;
   86.97 +        HScreenSize = hsize;
   86.98 +        VScreenSize = vsize;
   86.99 +        Contents |= Contents_Screen;
  86.100 +    }
  86.101 +
  86.102 +    void SetDistortion(const float* dks)
  86.103 +    {
  86.104 +        for (int i = 0; i < 4; i++)
  86.105 +            DistortionK[i] = dks[i];
  86.106 +        Contents |= Contents_Distortion;
  86.107 +    }
  86.108 +
  86.109 +    void Set7Inch() { Contents |= Contents_7Inch; }
  86.110 +
  86.111 +    bool Is7Inch() const;
  86.112 +
  86.113 +protected:
  86.114 +    String      DeviceId;
  86.115 +    String      DisplayDeviceName;
  86.116 +    int         DesktopX, DesktopY;
  86.117 +    unsigned    Contents;
  86.118 +    unsigned    HResolution, VResolution;
  86.119 +    float       HScreenSize, VScreenSize;
  86.120 +    long        DisplayId;
  86.121 +    float       DistortionK[4];
  86.122 +};
  86.123 +
  86.124 +
  86.125 +//-------------------------------------------------------------------------------------
  86.126 +
  86.127 +// HMDDevice represents an Oculus HMD device unit. An instance of this class
  86.128 +// is typically created from the DeviceManager.
  86.129 +//  After HMD device is created, we its sensor data can be obtained by 
  86.130 +//  first creating a Sensor object and then wrappig it in SensorFusion.
  86.131 +
  86.132 +class HMDDevice : public DeviceImpl<OVR::HMDDevice>
  86.133 +{
  86.134 +public:
  86.135 +    HMDDevice(HMDDeviceCreateDesc* createDesc);
  86.136 +    ~HMDDevice();
  86.137 +
  86.138 +    virtual bool Initialize(DeviceBase* parent);
  86.139 +    virtual void Shutdown();
  86.140 +
  86.141 +
  86.142 +    // Requests the currently used default profile. This profile affects the
  86.143 +    // settings reported by HMDInfo. 
  86.144 +    virtual Profile*    GetProfile() const;
  86.145 +    virtual const char* GetProfileName() const;
  86.146 +    virtual bool        SetProfileName(const char* name);
  86.147 +
  86.148 +    // Query associated sensor.
  86.149 +    virtual OVR::SensorDevice* GetSensor();  
  86.150 +
  86.151 +protected:
  86.152 +    HMDDeviceCreateDesc* getDesc() const { return (HMDDeviceCreateDesc*)pCreateDesc.GetPtr(); }
  86.153 +
  86.154 +    // User name for the profile used with this device.
  86.155 +    String               ProfileName;
  86.156 +    mutable Ptr<Profile> pCachedProfile;
  86.157 +};
  86.158 +
  86.159 +
  86.160 +}} // namespace OVR::OSX
  86.161 +
  86.162 +#endif // OVR_OSX_HMDDevice_h
  86.163 +
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/libovr/Src/osx/OVR_OSX_SensorDevice.cpp	Sat Sep 14 16:14:59 2013 +0300
    87.3 @@ -0,0 +1,45 @@
    87.4 +/************************************************************************************
    87.5 +
    87.6 +Filename    :   OVR_OSX_SensorDevice.cpp
    87.7 +Content     :   OSX SensorDevice implementation
    87.8 +Created     :   March 14, 2013
    87.9 +Authors     :   Lee Cooper
   87.10 +
   87.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   87.12 +
   87.13 +Use of this software is subject to the terms of the Oculus license
   87.14 +agreement provided at the time of installation or download, or which
   87.15 +otherwise accompanies this software in either electronic or hard copy form.
   87.16 +
   87.17 +*************************************************************************************/
   87.18 +
   87.19 +#include "OVR_OSX_HMDDevice.h"
   87.20 +#include "OVR_SensorImpl.h"
   87.21 +#include "OVR_DeviceImpl.h"
   87.22 +
   87.23 +namespace OVR { namespace OSX {
   87.24 +
   87.25 +} // namespace OSX
   87.26 +
   87.27 +//-------------------------------------------------------------------------------------
   87.28 +void SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo(   const SensorDisplayInfoImpl& displayInfo, 
   87.29 +                                                            DeviceFactory::EnumerateVisitor& visitor)
   87.30 +{
   87.31 +
   87.32 +    OSX::HMDDeviceCreateDesc hmdCreateDesc(&OSX::HMDDeviceFactory::Instance, 1, 1, "", 0);
   87.33 +    
   87.34 +    hmdCreateDesc.SetScreenParameters(  0, 0,
   87.35 +                                        displayInfo.HResolution, displayInfo.VResolution,
   87.36 +                                        displayInfo.HScreenSize, displayInfo.VScreenSize);
   87.37 +
   87.38 +    if ((displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) == SensorDisplayInfoImpl::Base_Distortion)
   87.39 +        hmdCreateDesc.SetDistortion(displayInfo.DistortionK);
   87.40 +    if (displayInfo.HScreenSize > 0.14f)
   87.41 +        hmdCreateDesc.Set7Inch();
   87.42 +
   87.43 +    visitor.Visit(hmdCreateDesc);
   87.44 +}
   87.45 +
   87.46 +} // namespace OVR
   87.47 +
   87.48 +
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/libovr/Src/osx/OVR_ThreadsPthread.cpp	Sat Sep 14 16:14:59 2013 +0300
    88.3 @@ -0,0 +1,1 @@
    88.4 +
    88.5 #include "OVR_Threads.h"
    88.6 #include "OVR_Hash.h"
    88.7 
    88.8 #ifdef OVR_ENABLE_THREADS
    88.9 
   88.10 #include "OVR_Timer.h"
   88.11 #include "OVR_Log.h"
   88.12 
   88.13 #include <pthread.h>
   88.14 #include <time.h>
   88.15 
   88.16 #ifdef OVR_OS_PS3
   88.17 #include <sys/sys_time.h>
   88.18 #include <sys/timer.h>
   88.19 #include <sys/synchronization.h>
   88.20 #define sleep(x) sys_timer_sleep(x)
   88.21 #define usleep(x) sys_timer_usleep(x)
   88.22 using std::timespec;
   88.23 #else
   88.24 #include <unistd.h>
   88.25 #include <sys/time.h>
   88.26 #include <errno.h>
   88.27 #endif
   88.28 
   88.29 namespace OVR {
   88.30 
   88.31 // ***** Mutex implementation
   88.32 
   88.33 
   88.34 // *** Internal Mutex implementation structure
   88.35 
   88.36 class MutexImpl : public NewOverrideBase
   88.37 {
   88.38     // System mutex or semaphore
   88.39     pthread_mutex_t   SMutex;
   88.40     bool          Recursive;
   88.41     unsigned      LockCount;
   88.42     pthread_t     LockedBy;
   88.43 
   88.44     friend class WaitConditionImpl;
   88.45 
   88.46 public:
   88.47     // Constructor/destructor
   88.48     MutexImpl(Mutex* pmutex, bool recursive = 1);
   88.49     ~MutexImpl();
   88.50 
   88.51     // Locking functions
   88.52     void                DoLock();
   88.53     bool                TryLock();
   88.54     void                Unlock(Mutex* pmutex);
   88.55     // Returns 1 if the mutes is currently locked
   88.56     bool                IsLockedByAnotherThread(Mutex* pmutex);        
   88.57     bool                IsSignaled() const;
   88.58 };
   88.59 
   88.60 pthread_mutexattr_t Lock::RecursiveAttr;
   88.61 bool Lock::RecursiveAttrInit = 0;
   88.62 
   88.63 // *** Constructor/destructor
   88.64 MutexImpl::MutexImpl(Mutex* pmutex, bool recursive)
   88.65 {   
   88.66     Recursive           = recursive;
   88.67     LockCount           = 0;
   88.68 
   88.69     if (Recursive)
   88.70     {
   88.71         if (!Lock::RecursiveAttrInit)
   88.72         {
   88.73             pthread_mutexattr_init(&Lock::RecursiveAttr);
   88.74             pthread_mutexattr_settype(&Lock::RecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
   88.75             Lock::RecursiveAttrInit = 1;
   88.76         }
   88.77 
   88.78         pthread_mutex_init(&SMutex, &Lock::RecursiveAttr);
   88.79     }
   88.80     else
   88.81         pthread_mutex_init(&SMutex, 0);
   88.82 }
   88.83 
   88.84 MutexImpl::~MutexImpl()
   88.85 {
   88.86     pthread_mutex_destroy(&SMutex);
   88.87 }
   88.88 
   88.89 
   88.90 // Lock and try lock
   88.91 void MutexImpl::DoLock()
   88.92 {
   88.93     while (pthread_mutex_lock(&SMutex));
   88.94     LockCount++;
   88.95     LockedBy = pthread_self();
   88.96 }
   88.97 
   88.98 bool MutexImpl::TryLock()
   88.99 {
  88.100     if (!pthread_mutex_trylock(&SMutex))
  88.101     {
  88.102         LockCount++;
  88.103         LockedBy = pthread_self();
  88.104         return 1;
  88.105     }
  88.106     
  88.107     return 0;
  88.108 }
  88.109 
  88.110 void MutexImpl::Unlock(Mutex* pmutex)
  88.111 {
  88.112     OVR_ASSERT(pthread_self() == LockedBy && LockCount > 0);
  88.113 
  88.114     unsigned lockCount;
  88.115     LockCount--;
  88.116     lockCount = LockCount;
  88.117 
  88.118     pthread_mutex_unlock(&SMutex);
  88.119 }
  88.120 
  88.121 bool    MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
  88.122 {
  88.123     // There could be multiple interpretations of IsLocked with respect to current thread
  88.124     if (LockCount == 0)
  88.125         return 0;
  88.126     if (pthread_self() != LockedBy)
  88.127         return 1;
  88.128     return 0;
  88.129 }
  88.130 
  88.131 bool    MutexImpl::IsSignaled() const
  88.132 {
  88.133     // An mutex is signaled if it is not locked ANYWHERE
  88.134     // Note that this is different from IsLockedByAnotherThread function,
  88.135     // that takes current thread into account
  88.136     return LockCount == 0;
  88.137 }
  88.138 
  88.139 
  88.140 // *** Actual Mutex class implementation
  88.141 
  88.142 Mutex::Mutex(bool recursive)
  88.143 {
  88.144     // NOTE: RefCount mode already thread-safe for all waitables.
  88.145     pImpl = new MutexImpl(this, recursive);
  88.146 }
  88.147 
  88.148 Mutex::~Mutex()
  88.149 {
  88.150     delete pImpl;
  88.151 }
  88.152 
  88.153 // Lock and try lock
  88.154 void Mutex::DoLock()
  88.155 {
  88.156     pImpl->DoLock();
  88.157 }
  88.158 bool Mutex::TryLock()
  88.159 {
  88.160     return pImpl->TryLock();
  88.161 }
  88.162 void Mutex::Unlock()
  88.163 {
  88.164     pImpl->Unlock(this);
  88.165 }
  88.166 bool    Mutex::IsLockedByAnotherThread()
  88.167 {
  88.168     return pImpl->IsLockedByAnotherThread(this);
  88.169 }
  88.170 
  88.171 
  88.172 
  88.173 //-----------------------------------------------------------------------------------
  88.174 // ***** Event
  88.175 
  88.176 bool Event::Wait(unsigned delay)
  88.177 {
  88.178     Mutex::Locker lock(&StateMutex);
  88.179 
  88.180     // Do the correct amount of waiting
  88.181     if (delay == OVR_WAIT_INFINITE)
  88.182     {
  88.183         while(!State)
  88.184             StateWaitCondition.Wait(&StateMutex);
  88.185     }
  88.186     else if (delay)
  88.187     {
  88.188         if (!State)
  88.189             StateWaitCondition.Wait(&StateMutex, delay);
  88.190     }
  88.191 
  88.192     bool state = State;
  88.193     // Take care of temporary 'pulsing' of a state
  88.194     if (Temporary)
  88.195     {
  88.196         Temporary   = false;
  88.197         State       = false;
  88.198     }
  88.199     return state;
  88.200 }
  88.201 
  88.202 void Event::updateState(bool newState, bool newTemp, bool mustNotify)
  88.203 {
  88.204     Mutex::Locker lock(&StateMutex);
  88.205     State       = newState;
  88.206     Temporary   = newTemp;
  88.207     if (mustNotify)
  88.208         StateWaitCondition.NotifyAll();    
  88.209 }
  88.210 
  88.211 
  88.212 
  88.213 // ***** Wait Condition Implementation
  88.214 
  88.215 // Internal implementation class
  88.216 class WaitConditionImpl : public NewOverrideBase
  88.217 {
  88.218     pthread_mutex_t     SMutex;
  88.219     pthread_cond_t      Condv;
  88.220 
  88.221 public:
  88.222 
  88.223     // Constructor/destructor
  88.224     WaitConditionImpl();
  88.225     ~WaitConditionImpl();
  88.226 
  88.227     // Release mutex and wait for condition. The mutex is re-aqured after the wait.
  88.228     bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
  88.229 
  88.230     // Notify a condition, releasing at one object waiting
  88.231     void    Notify();
  88.232     // Notify a condition, releasing all objects waiting
  88.233     void    NotifyAll();
  88.234 };
  88.235 
  88.236 
  88.237 WaitConditionImpl::WaitConditionImpl()
  88.238 {
  88.239     pthread_mutex_init(&SMutex, 0);
  88.240     pthread_cond_init(&Condv, 0);
  88.241 }
  88.242 
  88.243 WaitConditionImpl::~WaitConditionImpl()
  88.244 {
  88.245     pthread_mutex_destroy(&SMutex);
  88.246     pthread_cond_destroy(&Condv);
  88.247 }    
  88.248 
  88.249 bool    WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
  88.250 {
  88.251     bool            result = 1;
  88.252     unsigned            lockCount = pmutex->pImpl->LockCount;
  88.253 
  88.254     // Mutex must have been locked
  88.255     if (lockCount == 0)
  88.256         return 0;
  88.257 
  88.258     pthread_mutex_lock(&SMutex);
  88.259 
  88.260     // Finally, release a mutex or semaphore
  88.261     if (pmutex->pImpl->Recursive)
  88.262     {
  88.263         // Release the recursive mutex N times
  88.264         pmutex->pImpl->LockCount = 0;
  88.265         for(unsigned i=0; i<lockCount; i++)
  88.266             pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  88.267     }
  88.268     else
  88.269     {
  88.270         pmutex->pImpl->LockCount = 0;
  88.271         pthread_mutex_unlock(&pmutex->pImpl->SMutex);
  88.272     }
  88.273 
  88.274     // Note that there is a gap here between mutex.Unlock() and Wait().
  88.275     // The other mutex protects this gap.
  88.276 
  88.277     if (delay == OVR_WAIT_INFINITE)
  88.278         pthread_cond_wait(&Condv,&SMutex);
  88.279     else
  88.280     {
  88.281         timespec ts;
  88.282 #ifdef OVR_OS_PS3
  88.283         sys_time_sec_t s;
  88.284         sys_time_nsec_t ns;
  88.285         sys_time_get_current_time(&s, &ns);
  88.286 
  88.287         ts.tv_sec = s + (delay / 1000);
  88.288         ts.tv_nsec = ns + (delay % 1000) * 1000000;
  88.289 
  88.290 #else
  88.291         struct timeval tv;
  88.292         gettimeofday(&tv, 0);
  88.293 
  88.294         ts.tv_sec = tv.tv_sec + (delay / 1000);
  88.295         ts.tv_nsec = (tv.tv_usec + (delay % 1000) * 1000) * 1000;
  88.296 #endif
  88.297         if (ts.tv_nsec > 999999999)
  88.298         {
  88.299             ts.tv_sec++;
  88.300             ts.tv_nsec -= 1000000000;
  88.301         }
  88.302         int r = pthread_cond_timedwait(&Condv,&SMutex, &ts);
  88.303         OVR_ASSERT(r == 0 || r == ETIMEDOUT);
  88.304         if (r)
  88.305             result = 0;
  88.306     }
  88.307 
  88.308     pthread_mutex_unlock(&SMutex);
  88.309 
  88.310     // Re-aquire the mutex
  88.311     for(unsigned i=0; i<lockCount; i++)
  88.312         pmutex->DoLock(); 
  88.313 
  88.314     // Return the result
  88.315     return result;
  88.316 }
  88.317 
  88.318 // Notify a condition, releasing the least object in a queue
  88.319 void    WaitConditionImpl::Notify()
  88.320 {
  88.321     pthread_mutex_lock(&SMutex);
  88.322     pthread_cond_signal(&Condv);
  88.323     pthread_mutex_unlock(&SMutex);
  88.324 }
  88.325 
  88.326 // Notify a condition, releasing all objects waiting
  88.327 void    WaitConditionImpl::NotifyAll()
  88.328 {
  88.329     pthread_mutex_lock(&SMutex);
  88.330     pthread_cond_broadcast(&Condv);
  88.331     pthread_mutex_unlock(&SMutex);
  88.332 }
  88.333 
  88.334 
  88.335 
  88.336 // *** Actual implementation of WaitCondition
  88.337 
  88.338 WaitCondition::WaitCondition()
  88.339 {
  88.340     pImpl = new WaitConditionImpl;
  88.341 }
  88.342 WaitCondition::~WaitCondition()
  88.343 {
  88.344     delete pImpl;
  88.345 }
  88.346     
  88.347 bool    WaitCondition::Wait(Mutex *pmutex, unsigned delay)
  88.348 {
  88.349     return pImpl->Wait(pmutex, delay);
  88.350 }
  88.351 // Notification
  88.352 void    WaitCondition::Notify()
  88.353 {
  88.354     pImpl->Notify();
  88.355 }
  88.356 void    WaitCondition::NotifyAll()
  88.357 {
  88.358     pImpl->NotifyAll();
  88.359 }
  88.360 
  88.361 
  88.362 // ***** Current thread
  88.363 
  88.364 // Per-thread variable
  88.365 /*
  88.366 static __thread Thread* pCurrentThread = 0;
  88.367 
  88.368 // Static function to return a pointer to the current thread
  88.369 void    Thread::InitCurrentThread(Thread *pthread)
  88.370 {
  88.371     pCurrentThread = pthread;
  88.372 }
  88.373 
  88.374 // Static function to return a pointer to the current thread
  88.375 Thread*    Thread::GetThread()
  88.376 {
  88.377     return pCurrentThread;
  88.378 }
  88.379 */
  88.380 
  88.381 
  88.382 // *** Thread constructors.
  88.383 
  88.384 Thread::Thread(UPInt stackSize, int processor)
  88.385 {
  88.386     // NOTE: RefCount mode already thread-safe for all Waitable objects.
  88.387     CreateParams params;
  88.388     params.stackSize = stackSize;
  88.389     params.processor = processor;
  88.390     Init(params);
  88.391 }
  88.392 
  88.393 Thread::Thread(Thread::ThreadFn threadFunction, void*  userHandle, UPInt stackSize,
  88.394                  int processor, Thread::ThreadState initialState)
  88.395 {
  88.396     CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
  88.397     Init(params);
  88.398 }
  88.399 
  88.400 Thread::Thread(const CreateParams& params)
  88.401 {
  88.402     Init(params);
  88.403 }
  88.404 
  88.405 void Thread::Init(const CreateParams& params)
  88.406 {
  88.407     // Clear the variables    
  88.408     ThreadFlags     = 0;
  88.409     ThreadHandle    = 0;
  88.410     ExitCode        = 0;
  88.411     SuspendCount    = 0;
  88.412     StackSize       = params.stackSize;
  88.413     Processor       = params.processor;
  88.414     Priority        = params.priority;
  88.415 
  88.416     // Clear Function pointers
  88.417     ThreadFunction  = params.threadFunction;
  88.418     UserHandle      = params.userHandle;
  88.419     if (params.initialState != NotRunning)
  88.420         Start(params.initialState);
  88.421 }
  88.422 
  88.423 Thread::~Thread()
  88.424 {
  88.425     // Thread should not running while object is being destroyed,
  88.426     // this would indicate ref-counting issue.
  88.427     //OVR_ASSERT(IsRunning() == 0);
  88.428 
  88.429     // Clean up thread.    
  88.430     ThreadHandle = 0;
  88.431 }
  88.432 
  88.433 
  88.434 
  88.435 // *** Overridable User functions.
  88.436 
  88.437 // Default Run implementation
  88.438 int    Thread::Run()
  88.439 {
  88.440     // Call pointer to function, if available.    
  88.441     return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
  88.442 }
  88.443 void    Thread::OnExit()
  88.444 {   
  88.445 }
  88.446 
  88.447 
  88.448 // Finishes the thread and releases internal reference to it.
  88.449 void    Thread::FinishAndRelease()
  88.450 {
  88.451     // Note: thread must be US.
  88.452     ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
  88.453     ThreadFlags |= OVR_THREAD_FINISHED;
  88.454 
  88.455     // Release our reference; this is equivalent to 'delete this'
  88.456     // from the point of view of our thread.
  88.457     Release();
  88.458 }
  88.459 
  88.460 
  88.461 
  88.462 // *** ThreadList - used to track all created threads
  88.463 
  88.464 class ThreadList : public NewOverrideBase
  88.465 {
  88.466     //------------------------------------------------------------------------
  88.467     struct ThreadHashOp
  88.468     {
  88.469         size_t operator()(const Thread* ptr)
  88.470         {
  88.471             return (((size_t)ptr) >> 6) ^ (size_t)ptr;
  88.472         }
  88.473     };
  88.474 
  88.475     HashSet<Thread*, ThreadHashOp>        ThreadSet;
  88.476     Mutex                                 ThreadMutex;
  88.477     WaitCondition                         ThreadsEmpty;
  88.478     // Track the root thread that created us.
  88.479     pthread_t                             RootThreadId;
  88.480 
  88.481     static ThreadList* volatile pRunningThreads;
  88.482 
  88.483     void addThread(Thread *pthread)
  88.484     {
  88.485         Mutex::Locker lock(&ThreadMutex);
  88.486         ThreadSet.Add(pthread);
  88.487     }
  88.488 
  88.489     void removeThread(Thread *pthread)
  88.490     {
  88.491         Mutex::Locker lock(&ThreadMutex);
  88.492         ThreadSet.Remove(pthread);
  88.493         if (ThreadSet.GetSize() == 0)
  88.494             ThreadsEmpty.Notify();
  88.495     }
  88.496 
  88.497     void finishAllThreads()
  88.498     {
  88.499         // Only original root thread can call this.
  88.500         OVR_ASSERT(pthread_self() == RootThreadId);
  88.501 
  88.502         Mutex::Locker lock(&ThreadMutex);
  88.503         while (ThreadSet.GetSize() != 0)
  88.504             ThreadsEmpty.Wait(&ThreadMutex);
  88.505     }
  88.506 
  88.507 public:
  88.508 
  88.509     ThreadList()
  88.510     {
  88.511         RootThreadId = pthread_self();
  88.512     }
  88.513     ~ThreadList() { }
  88.514 
  88.515 
  88.516     static void AddRunningThread(Thread *pthread)
  88.517     {
  88.518         // Non-atomic creation ok since only the root thread
  88.519         if (!pRunningThreads)
  88.520         {
  88.521             pRunningThreads = new ThreadList;
  88.522             OVR_ASSERT(pRunningThreads);
  88.523         }
  88.524         pRunningThreads->addThread(pthread);
  88.525     }
  88.526 
  88.527     // NOTE: 'pthread' might be a dead pointer when this is
  88.528     // called so it should not be accessed; it is only used
  88.529     // for removal.
  88.530     static void RemoveRunningThread(Thread *pthread)
  88.531     {
  88.532         OVR_ASSERT(pRunningThreads);        
  88.533         pRunningThreads->removeThread(pthread);
  88.534     }
  88.535 
  88.536     static void FinishAllThreads()
  88.537     {
  88.538         // This is ok because only root thread can wait for other thread finish.
  88.539         if (pRunningThreads)
  88.540         {           
  88.541             pRunningThreads->finishAllThreads();
  88.542             delete pRunningThreads;
  88.543             pRunningThreads = 0;
  88.544         }        
  88.545     }
  88.546 };
  88.547 
  88.548 // By default, we have no thread list.
  88.549 ThreadList* volatile ThreadList::pRunningThreads = 0;
  88.550 
  88.551 
  88.552 // FinishAllThreads - exposed publicly in Thread.
  88.553 void Thread::FinishAllThreads()
  88.554 {
  88.555     ThreadList::FinishAllThreads();
  88.556 }
  88.557 
  88.558 // *** Run override
  88.559 
  88.560 int    Thread::PRun()
  88.561 {
  88.562     // Suspend us on start, if requested
  88.563     if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
  88.564     {
  88.565         Suspend();
  88.566         ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
  88.567     }
  88.568 
  88.569     // Call the virtual run function
  88.570     ExitCode = Run();    
  88.571     return ExitCode;
  88.572 }
  88.573 
  88.574 
  88.575 
  88.576 
  88.577 // *** User overridables
  88.578 
  88.579 bool    Thread::GetExitFlag() const
  88.580 {
  88.581     return (ThreadFlags & OVR_THREAD_EXIT) != 0;
  88.582 }       
  88.583 
  88.584 void    Thread::SetExitFlag(bool exitFlag)
  88.585 {
  88.586     // The below is atomic since ThreadFlags is AtomicInt.
  88.587     if (exitFlag)
  88.588         ThreadFlags |= OVR_THREAD_EXIT;
  88.589     else
  88.590         ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
  88.591 }
  88.592 
  88.593 
  88.594 // Determines whether the thread was running and is now finished
  88.595 bool    Thread::IsFinished() const
  88.596 {
  88.597     return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
  88.598 }
  88.599 // Determines whether the thread is suspended
  88.600 bool    Thread::IsSuspended() const
  88.601 {   
  88.602     return SuspendCount > 0;
  88.603 }
  88.604 // Returns current thread state
  88.605 Thread::ThreadState Thread::GetThreadState() const
  88.606 {
  88.607     if (IsSuspended())
  88.608         return Suspended;    
  88.609     if (ThreadFlags & OVR_THREAD_STARTED)
  88.610         return Running;    
  88.611     return NotRunning;
  88.612 }
  88.613 /*
  88.614 static const char* mapsched_policy(int policy)
  88.615 {
  88.616     switch(policy)
  88.617     {
  88.618     case SCHED_OTHER:
  88.619         return "SCHED_OTHER";
  88.620     case SCHED_RR:
  88.621         return "SCHED_RR";
  88.622     case SCHED_FIFO:
  88.623         return "SCHED_FIFO";
  88.624 
  88.625     }
  88.626     return "UNKNOWN";
  88.627 }
  88.628     int policy;
  88.629     sched_param sparam;
  88.630     pthread_getschedparam(pthread_self(), &policy, &sparam);
  88.631     int max_prior = sched_get_priority_max(policy);
  88.632     int min_prior = sched_get_priority_min(policy);
  88.633     printf(" !!!! policy: %s, priority: %d, max priority: %d, min priority: %d\n", mapsched_policy(policy), sparam.sched_priority, max_prior, min_prior);
  88.634 #include <stdio.h>
  88.635 */
  88.636 // ***** Thread management
  88.637 
  88.638 // The actual first function called on thread start
  88.639 void* Thread_PthreadStartFn(void* phandle)
  88.640 {
  88.641     Thread* pthread = (Thread*)phandle;
  88.642     int     result = pthread->PRun();
  88.643     // Signal the thread as done and release it atomically.
  88.644     pthread->FinishAndRelease();
  88.645     // At this point Thread object might be dead; however we can still pass
  88.646     // it to RemoveRunningThread since it is only used as a key there.   
  88.647     ThreadList::RemoveRunningThread(pthread);
  88.648     return (void*) result;
  88.649 }
  88.650 
  88.651 int Thread::InitAttr = 0;
  88.652 pthread_attr_t Thread::Attr; 
  88.653 
  88.654 /* static */
  88.655 int Thread::GetOSPriority(ThreadPriority p)
  88.656 //static inline int MapToSystemPrority(Thread::ThreadPriority p)
  88.657 {
  88.658 #ifdef OVR_OS_PS3 
  88.659     switch(p)
  88.660     {
  88.661     case Thread::CriticalPriority:     return 0;
  88.662     case Thread::HighestPriority:      return 300;
  88.663     case Thread::AboveNormalPriority:  return 600;
  88.664     case Thread::NormalPriority:       return 1000;
  88.665     case Thread::BelowNormalPriority:  return 1500;
  88.666     case Thread::LowestPriority:       return 2500;
  88.667     case Thread::IdlePriority:         return 3071;
  88.668     }                                  return 1000;
  88.669 #else
  88.670     OVR_UNUSED(p);
  88.671     return -1;
  88.672 #endif
  88.673 }
  88.674 
  88.675 bool    Thread::Start(ThreadState initialState)
  88.676 {
  88.677     if (initialState == NotRunning)
  88.678         return 0;
  88.679     if (GetThreadState() != NotRunning)
  88.680     {
  88.681         OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
  88.682         return 0;
  88.683     }
  88.684 
  88.685     if (!InitAttr)
  88.686     {
  88.687         pthread_attr_init(&Attr);
  88.688         pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
  88.689         pthread_attr_setstacksize(&Attr, 128 * 1024);
  88.690         sched_param sparam;
  88.691         sparam.sched_priority = Thread::GetOSPriority(NormalPriority);
  88.692         pthread_attr_setschedparam(&Attr, &sparam);
  88.693         InitAttr = 1;
  88.694     }
  88.695 
  88.696     ExitCode        = 0;
  88.697     SuspendCount    = 0;
  88.698     ThreadFlags     = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
  88.699 
  88.700     // AddRef to us until the thread is finished
  88.701     AddRef();
  88.702     ThreadList::AddRunningThread(this);
  88.703 
  88.704     int result;
  88.705     if (StackSize != 128 * 1024 || Priority != NormalPriority)
  88.706     {
  88.707         pthread_attr_t attr;
  88.708 
  88.709         pthread_attr_init(&attr);
  88.710         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
  88.711         pthread_attr_setstacksize(&attr, StackSize);
  88.712         sched_param sparam;
  88.713         sparam.sched_priority = Thread::GetOSPriority(Priority);
  88.714         pthread_attr_setschedparam(&attr, &sparam);
  88.715         result = pthread_create(&ThreadHandle, &attr, Thread_PthreadStartFn, this);
  88.716         pthread_attr_destroy(&attr);
  88.717     }
  88.718     else
  88.719         result = pthread_create(&ThreadHandle, &Attr, Thread_PthreadStartFn, this);
  88.720 
  88.721     if (result)
  88.722     {
  88.723         ThreadFlags = 0;
  88.724         Release();
  88.725         ThreadList::RemoveRunningThread(this);
  88.726         return 0;
  88.727     }
  88.728     return 1;
  88.729 }
  88.730 
  88.731 
  88.732 // Suspend the thread until resumed
  88.733 bool    Thread::Suspend()
  88.734 {
  88.735     OVR_DEBUG_LOG(("Thread::Suspend - cannot suspend threads on this system"));
  88.736     return 0;
  88.737 }
  88.738 
  88.739 // Resumes currently suspended thread
  88.740 bool    Thread::Resume()
  88.741 {
  88.742     return 0;
  88.743 }
  88.744 
  88.745 
  88.746 // Quits with an exit code  
  88.747 void    Thread::Exit(int exitCode)
  88.748 {
  88.749     // Can only exist the current thread
  88.750    // if (GetThread() != this)
  88.751    //     return;
  88.752 
  88.753     // Call the virtual OnExit function
  88.754     OnExit();   
  88.755 
  88.756     // Signal this thread object as done and release it's references.
  88.757     FinishAndRelease();
  88.758     ThreadList::RemoveRunningThread(this);
  88.759 
  88.760     pthread_exit((void *) exitCode);
  88.761 }
  88.762 
  88.763 ThreadId GetCurrentThreadId()
  88.764 {
  88.765     return (void*)pthread_self();
  88.766 }
  88.767 
  88.768 // *** Sleep functions
  88.769 
  88.770 /* static */
  88.771 bool    Thread::Sleep(unsigned secs)
  88.772 {
  88.773     sleep(secs);
  88.774     return 1;
  88.775 }
  88.776 /* static */
  88.777 bool    Thread::MSleep(unsigned msecs)
  88.778 {
  88.779     usleep(msecs*1000);
  88.780     return 1;
  88.781 }
  88.782 
  88.783 /* static */
  88.784 int     Thread::GetCPUCount()
  88.785 {
  88.786     return 1;
  88.787 }
  88.788 
  88.789 
  88.790 #ifdef OVR_OS_PS3
  88.791 
  88.792 sys_lwmutex_attribute_t Lock::LockAttr = { SYS_SYNC_PRIORITY, SYS_SYNC_RECURSIVE };
  88.793 
  88.794 #endif
  88.795 
  88.796 }
  88.797 
  88.798 #endif  // OVR_ENABLE_THREADS
  88.799 \ No newline at end of file
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/libovr/Src/win32/OVR_ThreadsWinAPI.cpp	Sat Sep 14 16:14:59 2013 +0300
    89.3 @@ -0,0 +1,1 @@
    89.4 +/************************************************************************************
    89.5 
    89.6 Filename    :   OVR_ThreadsWinAPI.cpp
    89.7 Platform    :   WinAPI
    89.8 Content     :   Windows specific thread-related (safe) functionality
    89.9 Created     :   September 19, 2012
   89.10 Notes       : 
   89.11 
   89.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   89.13 
   89.14 Use of this software is subject to the terms of the Oculus license
   89.15 agreement provided at the time of installation or download, or which
   89.16 otherwise accompanies this software in either electronic or hard copy form.
   89.17 
   89.18 ************************************************************************************/
   89.19 
   89.20 #include "OVR_Threads.h"
   89.21 #include "OVR_Hash.h"
   89.22 #include "OVR_Log.h"
   89.23 
   89.24 #ifdef OVR_ENABLE_THREADS
   89.25 
   89.26 // For _beginthreadex / _endtheadex
   89.27 #include <process.h>
   89.28 
   89.29 namespace OVR {
   89.30 
   89.31 
   89.32 //-----------------------------------------------------------------------------------
   89.33 // *** Internal Mutex implementation class
   89.34 
   89.35 class MutexImpl : public NewOverrideBase
   89.36 {
   89.37     // System mutex or semaphore
   89.38     HANDLE            hMutexOrSemaphore;
   89.39     bool              Recursive;
   89.40     volatile unsigned LockCount;
   89.41     
   89.42     friend class WaitConditionImpl;
   89.43 
   89.44 public:
   89.45     // Constructor/destructor
   89.46     MutexImpl(bool recursive = 1);
   89.47     ~MutexImpl();
   89.48 
   89.49     // Locking functions
   89.50     void                DoLock();
   89.51     bool                TryLock();
   89.52     void                Unlock(Mutex* pmutex);
   89.53     // Returns 1 if the mutes is currently locked
   89.54     bool                IsLockedByAnotherThread(Mutex* pmutex);
   89.55 };
   89.56 
   89.57 // *** Constructor/destructor
   89.58 MutexImpl::MutexImpl(bool recursive)
   89.59 {    
   89.60     Recursive                   = recursive;
   89.61     LockCount                   = 0;
   89.62     hMutexOrSemaphore           = Recursive ? CreateMutex(NULL, 0, NULL) : CreateSemaphore(NULL, 1, 1, NULL);
   89.63 }
   89.64 MutexImpl::~MutexImpl()
   89.65 {
   89.66     CloseHandle(hMutexOrSemaphore);
   89.67 }
   89.68 
   89.69 
   89.70 // Lock and try lock
   89.71 void MutexImpl::DoLock()
   89.72 {
   89.73     if (::WaitForSingleObject(hMutexOrSemaphore, INFINITE) != WAIT_OBJECT_0)
   89.74         return;
   89.75     LockCount++;
   89.76 }
   89.77 
   89.78 bool MutexImpl::TryLock()
   89.79 {
   89.80     DWORD ret;
   89.81     if ((ret=::WaitForSingleObject(hMutexOrSemaphore, 0)) != WAIT_OBJECT_0)
   89.82         return 0;
   89.83     LockCount++;
   89.84     return 1;
   89.85 }
   89.86 
   89.87 void MutexImpl::Unlock(Mutex* pmutex)
   89.88 {
   89.89     OVR_UNUSED(pmutex);
   89.90 
   89.91     unsigned lockCount;
   89.92     LockCount--;
   89.93     lockCount = LockCount;
   89.94 
   89.95     // Release mutex
   89.96     if ((Recursive ? ReleaseMutex(hMutexOrSemaphore) :
   89.97                      ReleaseSemaphore(hMutexOrSemaphore, 1, NULL))  != 0)
   89.98     {
   89.99         // This used to call Wait handlers if lockCount == 0.
  89.100     }
  89.101 }
  89.102 
  89.103 bool MutexImpl::IsLockedByAnotherThread(Mutex* pmutex)
  89.104 {
  89.105     // There could be multiple interpretations of IsLocked with respect to current thread
  89.106     if (LockCount == 0)
  89.107         return 0;
  89.108     if (!TryLock())
  89.109         return 1;
  89.110     Unlock(pmutex);
  89.111     return 0;
  89.112 }
  89.113 
  89.114 /*
  89.115 bool    MutexImpl::IsSignaled() const
  89.116 {
  89.117     // An mutex is signaled if it is not locked ANYWHERE
  89.118     // Note that this is different from IsLockedByAnotherThread function,
  89.119     // that takes current thread into account
  89.120     return LockCount == 0;
  89.121 }
  89.122 */
  89.123 
  89.124 
  89.125 // *** Actual Mutex class implementation
  89.126 
  89.127 Mutex::Mutex(bool recursive)
  89.128 {    
  89.129     pImpl = new MutexImpl(recursive);
  89.130 }
  89.131 Mutex::~Mutex()
  89.132 {
  89.133     delete pImpl;
  89.134 }
  89.135 
  89.136 // Lock and try lock
  89.137 void Mutex::DoLock()
  89.138 {
  89.139     pImpl->DoLock();
  89.140 }
  89.141 bool Mutex::TryLock()
  89.142 {
  89.143     return pImpl->TryLock();
  89.144 }
  89.145 void Mutex::Unlock()
  89.146 {
  89.147     pImpl->Unlock(this);
  89.148 }
  89.149 bool Mutex::IsLockedByAnotherThread()
  89.150 {
  89.151     return pImpl->IsLockedByAnotherThread(this);
  89.152 }
  89.153 
  89.154 //-----------------------------------------------------------------------------------
  89.155 // ***** Event
  89.156 
  89.157 bool Event::Wait(unsigned delay)
  89.158 {
  89.159     Mutex::Locker lock(&StateMutex);
  89.160 
  89.161     // Do the correct amount of waiting
  89.162     if (delay == OVR_WAIT_INFINITE)
  89.163     {
  89.164         while(!State)
  89.165             StateWaitCondition.Wait(&StateMutex);
  89.166     }
  89.167     else if (delay)
  89.168     {
  89.169         if (!State)
  89.170             StateWaitCondition.Wait(&StateMutex, delay);
  89.171     }
  89.172 
  89.173     bool state = State;
  89.174     // Take care of temporary 'pulsing' of a state
  89.175     if (Temporary)
  89.176     {
  89.177         Temporary   = false;
  89.178         State       = false;
  89.179     }
  89.180     return state;
  89.181 }
  89.182 
  89.183 void Event::updateState(bool newState, bool newTemp, bool mustNotify)
  89.184 {
  89.185     Mutex::Locker lock(&StateMutex);
  89.186     State       = newState;
  89.187     Temporary   = newTemp;
  89.188     if (mustNotify)
  89.189         StateWaitCondition.NotifyAll();    
  89.190 }
  89.191 
  89.192 
  89.193 //-----------------------------------------------------------------------------------
  89.194 // ***** Win32 Wait Condition Implementation
  89.195 
  89.196 // Internal implementation class
  89.197 class WaitConditionImpl : public NewOverrideBase
  89.198 {   
  89.199     // Event pool entries for extra events
  89.200     struct EventPoolEntry  : public NewOverrideBase
  89.201     {
  89.202         HANDLE          hEvent;
  89.203         EventPoolEntry  *pNext;
  89.204         EventPoolEntry  *pPrev;
  89.205     };
  89.206     
  89.207     Lock                WaitQueueLoc;
  89.208     // Stores free events that can be used later
  89.209     EventPoolEntry  *   pFreeEventList;
  89.210     
  89.211     // A queue of waiting objects to be signaled    
  89.212     EventPoolEntry*     pQueueHead;
  89.213     EventPoolEntry*     pQueueTail;
  89.214 
  89.215     // Allocation functions for free events
  89.216     EventPoolEntry*     GetNewEvent();
  89.217     void                ReleaseEvent(EventPoolEntry* pevent);
  89.218 
  89.219     // Queue operations
  89.220     void                QueuePush(EventPoolEntry* pentry);
  89.221     EventPoolEntry*     QueuePop();
  89.222     void                QueueFindAndRemove(EventPoolEntry* pentry);
  89.223 
  89.224 public:
  89.225 
  89.226     // Constructor/destructor
  89.227     WaitConditionImpl();
  89.228     ~WaitConditionImpl();
  89.229 
  89.230     // Release mutex and wait for condition. The mutex is re-acqured after the wait.
  89.231     bool    Wait(Mutex *pmutex, unsigned delay = OVR_WAIT_INFINITE);
  89.232 
  89.233     // Notify a condition, releasing at one object waiting
  89.234     void    Notify();
  89.235     // Notify a condition, releasing all objects waiting
  89.236     void    NotifyAll();
  89.237 };
  89.238 
  89.239 
  89.240 
  89.241 WaitConditionImpl::WaitConditionImpl()
  89.242 {
  89.243     pFreeEventList  = 0;
  89.244     pQueueHead      =
  89.245     pQueueTail      = 0;
  89.246 }
  89.247 
  89.248 WaitConditionImpl::~WaitConditionImpl()
  89.249 {
  89.250     // Free all the resources
  89.251     EventPoolEntry* p       = pFreeEventList;
  89.252     EventPoolEntry* pentry;
  89.253 
  89.254     while(p)
  89.255     {
  89.256         // Move to next
  89.257         pentry = p;
  89.258         p = p->pNext;
  89.259         // Delete old
  89.260         ::CloseHandle(pentry->hEvent);
  89.261         delete pentry;  
  89.262     }   
  89.263     // Shouldn't we also consider the queue?
  89.264 
  89.265     // To be safe
  89.266     pFreeEventList  = 0;
  89.267     pQueueHead      =
  89.268     pQueueTail      = 0;
  89.269 }
  89.270 
  89.271 
  89.272 // Allocation functions for free events
  89.273 WaitConditionImpl::EventPoolEntry* WaitConditionImpl::GetNewEvent()
  89.274 {
  89.275     EventPoolEntry* pentry;
  89.276 
  89.277     // If there are any free nodes, use them
  89.278     if (pFreeEventList)
  89.279     {
  89.280         pentry          = pFreeEventList;
  89.281         pFreeEventList  = pFreeEventList->pNext;        
  89.282     }
  89.283     else
  89.284     {
  89.285         // Allocate a new node
  89.286         pentry          = new EventPoolEntry;
  89.287         pentry->pNext   = 0;
  89.288         pentry->pPrev   = 0;
  89.289         // Non-signaled manual event
  89.290         pentry->hEvent  = ::CreateEvent(NULL, TRUE, 0, NULL);
  89.291     }
  89.292     
  89.293     return pentry;
  89.294 }
  89.295 
  89.296 void WaitConditionImpl::ReleaseEvent(EventPoolEntry* pevent)
  89.297 {
  89.298     // Mark event as non-signaled
  89.299     ::ResetEvent(pevent->hEvent);
  89.300     // And add it to free pool
  89.301     pevent->pNext   = pFreeEventList;
  89.302     pevent->pPrev   = 0;
  89.303     pFreeEventList  = pevent;
  89.304 }
  89.305 
  89.306 // Queue operations
  89.307 void WaitConditionImpl::QueuePush(EventPoolEntry* pentry)
  89.308 {
  89.309     // Items already exist? Just add to tail
  89.310     if (pQueueTail)
  89.311     {
  89.312         pentry->pPrev       = pQueueTail;
  89.313         pQueueTail->pNext   = pentry;
  89.314         pentry->pNext       = 0;        
  89.315         pQueueTail          = pentry;       
  89.316     }
  89.317     else
  89.318     {
  89.319         // No items in queue
  89.320         pentry->pNext   = 
  89.321         pentry->pPrev   = 0;
  89.322         pQueueHead      =
  89.323         pQueueTail      = pentry;
  89.324     }
  89.325 }
  89.326 
  89.327 WaitConditionImpl::EventPoolEntry* WaitConditionImpl::QueuePop()
  89.328 {
  89.329     EventPoolEntry* pentry = pQueueHead;
  89.330 
  89.331     // No items, null pointer
  89.332     if (pentry)
  89.333     {
  89.334         // More items after this one? just grab the first item
  89.335         if (pQueueHead->pNext)
  89.336         {       
  89.337             pQueueHead  = pentry->pNext;
  89.338             pQueueHead->pPrev = 0;      
  89.339         }
  89.340         else
  89.341         {
  89.342             // Last item left
  89.343             pQueueTail =
  89.344             pQueueHead = 0;
  89.345         }
  89.346     }   
  89.347     return pentry;
  89.348 }
  89.349 
  89.350 void WaitConditionImpl::QueueFindAndRemove(EventPoolEntry* pentry)
  89.351 {
  89.352     // Do an exhaustive search looking for an entry
  89.353     EventPoolEntry* p = pQueueHead;
  89.354 
  89.355     while(p)
  89.356     {
  89.357         // Entry found? Remove.
  89.358         if (p == pentry)
  89.359         {
  89.360             
  89.361             // Remove the node form the list
  89.362             // Prev link
  89.363             if (pentry->pPrev)
  89.364                 pentry->pPrev->pNext = pentry->pNext;
  89.365             else
  89.366                 pQueueHead = pentry->pNext;
  89.367             // Next link
  89.368             if (pentry->pNext)
  89.369                 pentry->pNext->pPrev = pentry->pPrev;
  89.370             else
  89.371                 pQueueTail = pentry->pPrev;
  89.372             // Done
  89.373             return;
  89.374         }
  89.375 
  89.376         // Move to next item
  89.377         p = p->pNext;
  89.378     }
  89.379 }
  89.380     
  89.381 
  89.382 bool WaitConditionImpl::Wait(Mutex *pmutex, unsigned delay)
  89.383 {
  89.384     bool            result = 0;
  89.385     unsigned        i;
  89.386     unsigned        lockCount = pmutex->pImpl->LockCount;
  89.387     EventPoolEntry* pentry;
  89.388 
  89.389     // Mutex must have been locked
  89.390     if (lockCount == 0)
  89.391         return 0;
  89.392     
  89.393     // Add an object to the wait queue
  89.394     WaitQueueLoc.DoLock();
  89.395     QueuePush(pentry = GetNewEvent());
  89.396     WaitQueueLoc.Unlock();
  89.397 
  89.398     // Finally, release a mutex or semaphore
  89.399     if (pmutex->pImpl->Recursive)
  89.400     {
  89.401         // Release the recursive mutex N times
  89.402         pmutex->pImpl->LockCount = 0;
  89.403         for(i=0; i<lockCount; i++)
  89.404             ::ReleaseMutex(pmutex->pImpl->hMutexOrSemaphore);
  89.405     }
  89.406     else
  89.407     {
  89.408         pmutex->pImpl->LockCount = 0;
  89.409         ::ReleaseSemaphore(pmutex->pImpl->hMutexOrSemaphore, 1, NULL);
  89.410     }
  89.411 
  89.412     // Note that there is a gap here between mutex.Unlock() and Wait(). However,
  89.413     // if notify() comes in at this point in the other thread it will set our
  89.414     // corresponding event so wait will just fall through, as expected.
  89.415 
  89.416     // Block and wait on the event
  89.417     DWORD waitResult = ::WaitForSingleObject(pentry->hEvent,
  89.418                             (delay == OVR_WAIT_INFINITE) ? INFINITE : delay);
  89.419     /*
  89.420 repeat_wait:
  89.421     DWORD waitResult =
  89.422 
  89.423     ::MsgWaitForMultipleObjects(1, &pentry->hEvent, FALSE,
  89.424                                 (delay == OVR_WAIT_INFINITE) ? INFINITE : delay,
  89.425                                 QS_ALLINPUT);
  89.426     */
  89.427 
  89.428     WaitQueueLoc.DoLock();
  89.429     switch(waitResult)
  89.430     {
  89.431         case WAIT_ABANDONED:
  89.432         case WAIT_OBJECT_0: 
  89.433             result = 1;
  89.434             // Wait was successful, therefore the event entry should already be removed
  89.435             // So just add entry back to a free list
  89.436             ReleaseEvent(pentry);
  89.437             break;
  89.438             /*
  89.439         case WAIT_OBJECT_0 + 1:
  89.440             // Messages in WINDOWS queue
  89.441             {
  89.442                 MSG msg;
  89.443                 PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);             
  89.444                 WaitQueueLoc.Unlock();
  89.445                 goto repeat_wait;
  89.446             }
  89.447             break; */
  89.448         default:
  89.449             // Timeout, our entry should still be in a queue
  89.450             QueueFindAndRemove(pentry);
  89.451             ReleaseEvent(pentry);
  89.452     }
  89.453     WaitQueueLoc.Unlock();
  89.454 
  89.455     // Re-aquire the mutex
  89.456     for(i=0; i<lockCount; i++)
  89.457         pmutex->DoLock(); 
  89.458 
  89.459     // Return the result
  89.460     return result;
  89.461 }
  89.462 
  89.463 // Notify a condition, releasing the least object in a queue
  89.464 void WaitConditionImpl::Notify()
  89.465 {
  89.466     Lock::Locker   lock(&WaitQueueLoc);
  89.467     
  89.468     // Pop last entry & signal it
  89.469     EventPoolEntry* pentry = QueuePop();    
  89.470     if (pentry)
  89.471         ::SetEvent(pentry->hEvent); 
  89.472 }
  89.473 
  89.474 // Notify a condition, releasing all objects waiting
  89.475 void WaitConditionImpl::NotifyAll()
  89.476 {
  89.477     Lock::Locker   lock(&WaitQueueLoc);
  89.478 
  89.479     // Pop and signal all events
  89.480     // NOTE : There is no need to release the events, it's the waiters job to do so 
  89.481     EventPoolEntry* pentry = QueuePop();
  89.482     while (pentry)
  89.483     {
  89.484         ::SetEvent(pentry->hEvent);
  89.485         pentry = QueuePop();
  89.486     }
  89.487 }
  89.488 
  89.489 
  89.490 
  89.491 // *** Actual implementation of WaitCondition
  89.492 
  89.493 WaitCondition::WaitCondition()
  89.494 {
  89.495     pImpl = new WaitConditionImpl;
  89.496 }
  89.497 WaitCondition::~WaitCondition()
  89.498 {
  89.499     delete pImpl;
  89.500 }
  89.501     
  89.502 // Wait without a mutex
  89.503 bool    WaitCondition::Wait(Mutex *pmutex, unsigned delay)
  89.504 {
  89.505     return pImpl->Wait(pmutex, delay);
  89.506 }
  89.507 // Notification
  89.508 void    WaitCondition::Notify()
  89.509 {
  89.510     pImpl->Notify();
  89.511 }
  89.512 void    WaitCondition::NotifyAll()
  89.513 {
  89.514     pImpl->NotifyAll();
  89.515 }
  89.516 
  89.517 
  89.518 
  89.519 //-----------------------------------------------------------------------------------
  89.520 // ***** Thread Class
  89.521 
  89.522 //  Per-thread variable
  89.523 //  MA: Don't use TLS for now - portability issues with DLLs, etc.
  89.524 /*
  89.525 #if !defined(OVR_CC_MSVC) || (OVR_CC_MSVC < 1300)
  89.526 __declspec(thread)  Thread*    pCurrentThread      = 0;
  89.527 #else
  89.528 #pragma data_seg(".tls$")
  89.529 __declspec(thread)  Thread*    pCurrentThread      = 0;
  89.530 #pragma data_seg(".rwdata")
  89.531 #endif
  89.532 */
  89.533 
  89.534 // *** Thread constructors.
  89.535 
  89.536 Thread::Thread(UPInt stackSize, int processor)
  89.537 {    
  89.538     CreateParams params;
  89.539     params.stackSize = stackSize;
  89.540     params.processor = processor;
  89.541     Init(params);
  89.542 }
  89.543 
  89.544 Thread::Thread(Thread::ThreadFn threadFunction, void*  userHandle, UPInt stackSize, 
  89.545                  int processor, Thread::ThreadState initialState)
  89.546 {
  89.547     CreateParams params(threadFunction, userHandle, stackSize, processor, initialState);
  89.548     Init(params);
  89.549 }
  89.550 
  89.551 Thread::Thread(const CreateParams& params)
  89.552 {
  89.553     Init(params);
  89.554 }
  89.555 void Thread::Init(const CreateParams& params)
  89.556 {
  89.557     // Clear the variables    
  89.558     ThreadFlags     = 0;
  89.559     ThreadHandle    = 0;
  89.560     IdValue         = 0;
  89.561     ExitCode        = 0;
  89.562     SuspendCount    = 0;
  89.563     StackSize       = params.stackSize;
  89.564     Processor       = params.processor;
  89.565     Priority        = params.priority;
  89.566 
  89.567     // Clear Function pointers
  89.568     ThreadFunction  = params.threadFunction;
  89.569     UserHandle      = params.userHandle;
  89.570     if (params.initialState != NotRunning)
  89.571         Start(params.initialState);
  89.572 
  89.573 }
  89.574 
  89.575 Thread::~Thread()
  89.576 {
  89.577     // Thread should not running while object is being destroyed,
  89.578     // this would indicate ref-counting issue.
  89.579     //OVR_ASSERT(IsRunning() == 0);
  89.580   
  89.581     // Clean up thread.    
  89.582     CleanupSystemThread();
  89.583     ThreadHandle = 0;
  89.584 }
  89.585 
  89.586 
  89.587 // *** Overridable User functions.
  89.588 
  89.589 // Default Run implementation
  89.590 int Thread::Run()
  89.591 {
  89.592     // Call pointer to function, if available.    
  89.593     return (ThreadFunction) ? ThreadFunction(this, UserHandle) : 0;
  89.594 }
  89.595 void Thread::OnExit()
  89.596 {   
  89.597 }
  89.598 
  89.599 // Finishes the thread and releases internal reference to it.
  89.600 void Thread::FinishAndRelease()
  89.601 {
  89.602     // Note: thread must be US.
  89.603     ThreadFlags &= (UInt32)~(OVR_THREAD_STARTED);
  89.604     ThreadFlags |= OVR_THREAD_FINISHED;
  89.605 
  89.606     // Release our reference; this is equivalent to 'delete this'
  89.607     // from the point of view of our thread.
  89.608     Release();
  89.609 }
  89.610 
  89.611 
  89.612 // *** ThreadList - used to tack all created threads
  89.613 
  89.614 class ThreadList : public NewOverrideBase
  89.615 {
  89.616     //------------------------------------------------------------------------
  89.617     struct ThreadHashOp
  89.618     {
  89.619         UPInt operator()(const Thread* ptr)
  89.620         {
  89.621             return (((UPInt)ptr) >> 6) ^ (UPInt)ptr;
  89.622         }
  89.623     };
  89.624 
  89.625     HashSet<Thread*, ThreadHashOp>  ThreadSet;
  89.626     Mutex                           ThreadMutex;
  89.627     WaitCondition                   ThreadsEmpty;
  89.628     // Track the root thread that created us.
  89.629     ThreadId                        RootThreadId;
  89.630 
  89.631     static ThreadList* volatile pRunningThreads;
  89.632 
  89.633     void addThread(Thread *pthread)
  89.634     {
  89.635          Mutex::Locker lock(&ThreadMutex);
  89.636          ThreadSet.Add(pthread);
  89.637     }
  89.638 
  89.639     void removeThread(Thread *pthread)
  89.640     {
  89.641         Mutex::Locker lock(&ThreadMutex);
  89.642         ThreadSet.Remove(pthread);
  89.643         if (ThreadSet.GetSize() == 0)
  89.644             ThreadsEmpty.Notify();
  89.645     }
  89.646 
  89.647     void finishAllThreads()
  89.648     {
  89.649         // Only original root thread can call this.
  89.650         OVR_ASSERT(GetCurrentThreadId() == RootThreadId);
  89.651 
  89.652         Mutex::Locker lock(&ThreadMutex);
  89.653         while (ThreadSet.GetSize() != 0)
  89.654             ThreadsEmpty.Wait(&ThreadMutex);
  89.655     }
  89.656 
  89.657 public:
  89.658 
  89.659     ThreadList()
  89.660     {
  89.661         RootThreadId = GetCurrentThreadId();
  89.662     }
  89.663     ~ThreadList() { }
  89.664 
  89.665 
  89.666     static void AddRunningThread(Thread *pthread)
  89.667     {
  89.668         // Non-atomic creation ok since only the root thread
  89.669         if (!pRunningThreads)
  89.670         {
  89.671             pRunningThreads = new ThreadList;
  89.672             OVR_ASSERT(pRunningThreads);
  89.673         }
  89.674         pRunningThreads->addThread(pthread);
  89.675     }
  89.676 
  89.677     // NOTE: 'pthread' might be a dead pointer when this is
  89.678     // called so it should not be accessed; it is only used
  89.679     // for removal.
  89.680     static void RemoveRunningThread(Thread *pthread)
  89.681     {
  89.682         OVR_ASSERT(pRunningThreads);        
  89.683         pRunningThreads->removeThread(pthread);
  89.684     }
  89.685 
  89.686     static void FinishAllThreads()
  89.687     {
  89.688         // This is ok because only root thread can wait for other thread finish.
  89.689         if (pRunningThreads)
  89.690         {           
  89.691             pRunningThreads->finishAllThreads();
  89.692             delete pRunningThreads;
  89.693             pRunningThreads = 0;
  89.694         }        
  89.695     }
  89.696 };
  89.697 
  89.698 // By default, we have no thread list.
  89.699 ThreadList* volatile ThreadList::pRunningThreads = 0;
  89.700 
  89.701 
  89.702 // FinishAllThreads - exposed publicly in Thread.
  89.703 void Thread::FinishAllThreads()
  89.704 {
  89.705     ThreadList::FinishAllThreads();
  89.706 }
  89.707 
  89.708 
  89.709 // *** Run override
  89.710 
  89.711 int Thread::PRun()
  89.712 {
  89.713     // Suspend us on start, if requested
  89.714     if (ThreadFlags & OVR_THREAD_START_SUSPENDED)
  89.715     {
  89.716         Suspend();
  89.717         ThreadFlags &= (UInt32)~OVR_THREAD_START_SUSPENDED;
  89.718     }
  89.719 
  89.720     // Call the virtual run function
  89.721     ExitCode = Run();    
  89.722     return ExitCode;
  89.723 }
  89.724 
  89.725 
  89.726 
  89.727 /* MA: Don't use TLS for now.
  89.728 
  89.729 // Static function to return a pointer to the current thread
  89.730 void    Thread::InitCurrentThread(Thread *pthread)
  89.731 {
  89.732     pCurrentThread = pthread;
  89.733 }
  89.734 
  89.735 // Static function to return a pointer to the current thread
  89.736 Thread*    Thread::GetThread()
  89.737 {
  89.738     return pCurrentThread;
  89.739 }
  89.740 */
  89.741 
  89.742 
  89.743 // *** User overridables
  89.744 
  89.745 bool    Thread::GetExitFlag() const
  89.746 {
  89.747     return (ThreadFlags & OVR_THREAD_EXIT) != 0;
  89.748 }       
  89.749 
  89.750 void    Thread::SetExitFlag(bool exitFlag)
  89.751 {
  89.752     // The below is atomic since ThreadFlags is AtomicInt.
  89.753     if (exitFlag)
  89.754         ThreadFlags |= OVR_THREAD_EXIT;
  89.755     else
  89.756         ThreadFlags &= (UInt32) ~OVR_THREAD_EXIT;
  89.757 }
  89.758 
  89.759 
  89.760 // Determines whether the thread was running and is now finished
  89.761 bool    Thread::IsFinished() const
  89.762 {
  89.763     return (ThreadFlags & OVR_THREAD_FINISHED) != 0;
  89.764 }
  89.765 // Determines whether the thread is suspended
  89.766 bool    Thread::IsSuspended() const
  89.767 {   
  89.768     return SuspendCount > 0;
  89.769 }
  89.770 // Returns current thread state
  89.771 Thread::ThreadState Thread::GetThreadState() const
  89.772 {
  89.773     if (IsSuspended())
  89.774         return Suspended;    
  89.775     if (ThreadFlags & OVR_THREAD_STARTED)
  89.776         return Running;    
  89.777     return NotRunning;
  89.778 }
  89.779 
  89.780 
  89.781 
  89.782 // ***** Thread management
  89.783 /* static */
  89.784 int Thread::GetOSPriority(ThreadPriority p)
  89.785 {
  89.786     switch(p)
  89.787     {
  89.788     case Thread::CriticalPriority:      return THREAD_PRIORITY_TIME_CRITICAL;
  89.789     case Thread::HighestPriority:       return THREAD_PRIORITY_HIGHEST;
  89.790     case Thread::AboveNormalPriority:   return THREAD_PRIORITY_ABOVE_NORMAL;
  89.791     case Thread::NormalPriority:        return THREAD_PRIORITY_NORMAL;
  89.792     case Thread::BelowNormalPriority:   return THREAD_PRIORITY_BELOW_NORMAL;
  89.793     case Thread::LowestPriority:        return THREAD_PRIORITY_LOWEST;
  89.794     case Thread::IdlePriority:          return THREAD_PRIORITY_IDLE;
  89.795     }
  89.796     return THREAD_PRIORITY_NORMAL;
  89.797 }
  89.798 
  89.799 // The actual first function called on thread start
  89.800 unsigned WINAPI Thread_Win32StartFn(void * phandle)
  89.801 {
  89.802     Thread *   pthread = (Thread*)phandle;
  89.803     if (pthread->Processor != -1)
  89.804     {
  89.805         DWORD_PTR ret = SetThreadAffinityMask(GetCurrentThread(), (DWORD)pthread->Processor);
  89.806         if (ret == 0)
  89.807             OVR_DEBUG_LOG(("Could not set hardware processor for the thread"));
  89.808     }
  89.809     BOOL ret = ::SetThreadPriority(GetCurrentThread(), Thread::GetOSPriority(pthread->Priority));
  89.810     if (ret == 0)
  89.811         OVR_DEBUG_LOG(("Could not set thread priority"));
  89.812     OVR_UNUSED(ret);
  89.813 
  89.814     // Ensure that ThreadId is assigned once thread is running, in case
  89.815     // beginthread hasn't filled it in yet.
  89.816     pthread->IdValue = (ThreadId)::GetCurrentThreadId();
  89.817 
  89.818     DWORD       result = pthread->PRun();
  89.819     // Signal the thread as done and release it atomically.
  89.820     pthread->FinishAndRelease();
  89.821     // At this point Thread object might be dead; however we can still pass
  89.822     // it to RemoveRunningThread since it is only used as a key there.    
  89.823     ThreadList::RemoveRunningThread(pthread);
  89.824     return (unsigned) result;
  89.825 }
  89.826 
  89.827 bool Thread::Start(ThreadState initialState)
  89.828 {
  89.829     if (initialState == NotRunning)
  89.830         return 0;
  89.831     if (GetThreadState() != NotRunning)
  89.832     {
  89.833         OVR_DEBUG_LOG(("Thread::Start failed - thread %p already running", this));
  89.834         return 0;
  89.835     }
  89.836 
  89.837     // Free old thread handle before creating the new one
  89.838     CleanupSystemThread();
  89.839 
  89.840     // AddRef to us until the thread is finished.
  89.841     AddRef();
  89.842     ThreadList::AddRunningThread(this);
  89.843     
  89.844     ExitCode        = 0;
  89.845     SuspendCount    = 0;
  89.846     ThreadFlags     = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED;
  89.847     ThreadHandle = (HANDLE) _beginthreadex(0, (unsigned)StackSize,
  89.848                                            Thread_Win32StartFn, this, 0, (unsigned*)&IdValue);
  89.849 
  89.850     // Failed? Fail the function
  89.851     if (ThreadHandle == 0)
  89.852     {
  89.853         ThreadFlags = 0;
  89.854         Release();
  89.855         ThreadList::RemoveRunningThread(this);
  89.856         return 0;
  89.857     }
  89.858     return 1;
  89.859 }
  89.860 
  89.861 
  89.862 // Suspend the thread until resumed
  89.863 bool Thread::Suspend()
  89.864 {
  89.865     // Can't suspend a thread that wasn't started
  89.866     if (!(ThreadFlags & OVR_THREAD_STARTED))
  89.867         return 0;
  89.868 
  89.869     if (::SuspendThread(ThreadHandle) != 0xFFFFFFFF)
  89.870     {        
  89.871         SuspendCount++;        
  89.872         return 1;
  89.873     }
  89.874     return 0;
  89.875 }
  89.876 
  89.877 // Resumes currently suspended thread
  89.878 bool Thread::Resume()
  89.879 {
  89.880     // Can't suspend a thread that wasn't started
  89.881     if (!(ThreadFlags & OVR_THREAD_STARTED))
  89.882         return 0;
  89.883 
  89.884     // Decrement count, and resume thread if it is 0
  89.885     SInt32 oldCount = SuspendCount.ExchangeAdd_Acquire(-1);
  89.886     if (oldCount >= 1)
  89.887     {
  89.888         if (oldCount == 1)
  89.889         {
  89.890             if (::ResumeThread(ThreadHandle) != 0xFFFFFFFF)            
  89.891                 return 1;            
  89.892         }
  89.893         else
  89.894         {
  89.895             return 1;
  89.896         }
  89.897     }   
  89.898     return 0;
  89.899 }
  89.900 
  89.901 
  89.902 // Quits with an exit code  
  89.903 void Thread::Exit(int exitCode)
  89.904 {
  89.905     // Can only exist the current thread.
  89.906     // MA: Don't use TLS for now.
  89.907     //if (GetThread() != this)
  89.908     //    return;
  89.909 
  89.910     // Call the virtual OnExit function.
  89.911     OnExit();   
  89.912 
  89.913     // Signal this thread object as done and release it's references.
  89.914     FinishAndRelease();
  89.915     ThreadList::RemoveRunningThread(this);
  89.916 
  89.917     // Call the exit function.    
  89.918     _endthreadex((unsigned)exitCode);
  89.919 }
  89.920 
  89.921 
  89.922 void Thread::CleanupSystemThread()
  89.923 {
  89.924     if (ThreadHandle != 0)
  89.925     {
  89.926         ::CloseHandle(ThreadHandle);
  89.927         ThreadHandle = 0;
  89.928     }
  89.929 }
  89.930 
  89.931 // *** Sleep functions
  89.932 // static
  89.933 bool Thread::Sleep(unsigned secs)
  89.934 {
  89.935     ::Sleep(secs*1000);
  89.936     return 1;
  89.937 }
  89.938 
  89.939 // static
  89.940 bool Thread::MSleep(unsigned msecs)
  89.941 {
  89.942     ::Sleep(msecs);
  89.943     return 1;
  89.944 }
  89.945 
  89.946 void Thread::SetThreadName( const char* name )
  89.947 {
  89.948 #if !defined(OVR_BUILD_SHIPPING) || defined(OVR_BUILD_PROFILING)
  89.949     // Looks ugly, but it is the recommended way to name a thread.
  89.950     typedef struct tagTHREADNAME_INFO {
  89.951         DWORD dwType;     // Must be 0x1000
  89.952         LPCSTR szName;    // Pointer to name (in user address space)
  89.953         DWORD dwThreadID; // Thread ID (-1 for caller thread)
  89.954         DWORD dwFlags;    // Reserved for future use; must be zero
  89.955     } THREADNAME_INFO;
  89.956 
  89.957     THREADNAME_INFO info;
  89.958 
  89.959     info.dwType = 0x1000;
  89.960     info.szName = name;
  89.961     info.dwThreadID = reinterpret_cast<DWORD>(GetThreadId());
  89.962     info.dwFlags = 0;
  89.963 
  89.964     __try
  89.965     {
  89.966 #ifdef _WIN64
  89.967         RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR *)&info );
  89.968 #else
  89.969         RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD), (DWORD *)&info );
  89.970 #endif
  89.971     }
  89.972     __except( GetExceptionCode()==0x406D1388 ? EXCEPTION_CONTINUE_EXECUTION : EXCEPTION_EXECUTE_HANDLER )
  89.973     {
  89.974     }
  89.975 #endif // OVR_BUILD_SHIPPING
  89.976 }
  89.977 
  89.978 // static
  89.979 int  Thread::GetCPUCount()
  89.980 {
  89.981     SYSTEM_INFO sysInfo;
  89.982     GetSystemInfo(&sysInfo);
  89.983     return (int) sysInfo.dwNumberOfProcessors;
  89.984 }
  89.985 
  89.986 // Returns the unique Id of a thread it is called on, intended for
  89.987 // comparison purposes.
  89.988 ThreadId GetCurrentThreadId()
  89.989 {
  89.990     return (ThreadId)::GetCurrentThreadId();
  89.991 }
  89.992 
  89.993 } // OVR
  89.994 
  89.995 #endif
  89.996 
  89.997 
  89.998 \ No newline at end of file
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/libovr/Src/win32/OVR_Win32_DeviceManager.cpp	Sat Sep 14 16:14:59 2013 +0300
    90.3 @@ -0,0 +1,423 @@
    90.4 +/************************************************************************************
    90.5 +
    90.6 +Filename    :   OVR_Win32_DeviceManager.cpp
    90.7 +Content     :   Win32 implementation of DeviceManager.
    90.8 +Created     :   September 21, 2012
    90.9 +Authors     :   Michael Antonov
   90.10 +
   90.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   90.12 +
   90.13 +Use of this software is subject to the terms of the Oculus license
   90.14 +agreement provided at the time of installation or download, or which
   90.15 +otherwise accompanies this software in either electronic or hard copy form.
   90.16 +
   90.17 +*************************************************************************************/
   90.18 +
   90.19 +#include "OVR_Win32_DeviceManager.h"
   90.20 +
   90.21 +// Sensor & HMD Factories
   90.22 +#include "OVR_SensorImpl.h"
   90.23 +#include "OVR_LatencyTestImpl.h"
   90.24 +#include "OVR_Win32_HMDDevice.h"
   90.25 +#include "OVR_Win32_DeviceStatus.h"
   90.26 +#include "OVR_Win32_HIDDevice.h"
   90.27 +
   90.28 +#include "Kernel/OVR_Timer.h"
   90.29 +#include "Kernel/OVR_Std.h"
   90.30 +#include "Kernel/OVR_Log.h"
   90.31 +
   90.32 +DWORD Debug_WaitedObjectCount = 0;
   90.33 +
   90.34 +namespace OVR { namespace Win32 {
   90.35 +
   90.36 +
   90.37 +//-------------------------------------------------------------------------------------
   90.38 +// **** Win32::DeviceManager
   90.39 +
   90.40 +DeviceManager::DeviceManager()
   90.41 +{
   90.42 +    HidDeviceManager = *HIDDeviceManager::CreateInternal(this);
   90.43 +}
   90.44 +
   90.45 +DeviceManager::~DeviceManager()
   90.46 +{
   90.47 +    // make sure Shutdown was called.
   90.48 +    OVR_ASSERT(!pThread);
   90.49 +}
   90.50 +
   90.51 +bool DeviceManager::Initialize(DeviceBase*)
   90.52 +{
   90.53 +    if (!DeviceManagerImpl::Initialize(0))
   90.54 +        return false;
   90.55 +
   90.56 +    pThread = *new DeviceManagerThread(this);
   90.57 +    if (!pThread || !pThread->Start())
   90.58 +        return false;
   90.59 +         
   90.60 +    pCreateDesc->pDevice = this;
   90.61 +    LogText("OVR::DeviceManager - initialized.\n");
   90.62 +    return true;
   90.63 +}
   90.64 +
   90.65 +void DeviceManager::Shutdown()
   90.66 +{   
   90.67 +    LogText("OVR::DeviceManager - shutting down.\n");
   90.68 +
   90.69 +    // Set Manager shutdown marker variable; this prevents
   90.70 +    // any existing DeviceHandle objects from accessing device.
   90.71 +    pCreateDesc->pLock->pManager = 0;
   90.72 +
   90.73 +    // Push for thread shutdown *WITH NO WAIT*.
   90.74 +    // This will have the following effect:
   90.75 +    //  - Exit command will get enqueued, which will be executed later on the thread itself.
   90.76 +    //  - Beyond this point, this DeviceManager object may be deleted by our caller.
   90.77 +    //  - Other commands, such as CreateDevice, may execute before ExitCommand, but they will
   90.78 +    //    fail gracefully due to pLock->pManager == 0. Future commands can't be enqued
   90.79 +    //    after pManager is null.
   90.80 +    //  - Once ExitCommand executes, ThreadCommand::Run loop will exit and release the last
   90.81 +    //    reference to the thread object.
   90.82 +    pThread->PushExitCommand(false);
   90.83 +    pThread->DetachDeviceManager();
   90.84 +    pThread.Clear();
   90.85 +
   90.86 +    DeviceManagerImpl::Shutdown();
   90.87 +}
   90.88 +
   90.89 +ThreadCommandQueue* DeviceManager::GetThreadQueue()
   90.90 +{
   90.91 +    return pThread;
   90.92 +}
   90.93 +
   90.94 +bool DeviceManager::GetDeviceInfo(DeviceInfo* info) const
   90.95 +{
   90.96 +    if ((info->InfoClassType != Device_Manager) &&
   90.97 +        (info->InfoClassType != Device_None))
   90.98 +        return false;
   90.99 +    
  90.100 +    info->Type    = Device_Manager;
  90.101 +    info->Version = 0;
  90.102 +    OVR_strcpy(info->ProductName, DeviceInfo::MaxNameLength, "DeviceManager");
  90.103 +    OVR_strcpy(info->Manufacturer,DeviceInfo::MaxNameLength, "Oculus VR, Inc.");        
  90.104 +    return true;
  90.105 +}
  90.106 +
  90.107 +DeviceEnumerator<> DeviceManager::EnumerateDevicesEx(const DeviceEnumerationArgs& args)
  90.108 +{
  90.109 +    // TBD: Can this be avoided in the future, once proper device notification is in place?
  90.110 +    if (GetThreadId() != OVR::GetCurrentThreadId())
  90.111 +    {
  90.112 +        pThread->PushCall((DeviceManagerImpl*)this,
  90.113 +            &DeviceManager::EnumerateAllFactoryDevices, true);
  90.114 +    }
  90.115 +    else
  90.116 +        DeviceManager::EnumerateAllFactoryDevices();
  90.117 +
  90.118 +    return DeviceManagerImpl::EnumerateDevicesEx(args);
  90.119 +}
  90.120 +
  90.121 +ThreadId DeviceManager::GetThreadId() const
  90.122 +{
  90.123 +    return pThread->GetThreadId();
  90.124 +}
  90.125 +    
  90.126 +bool DeviceManager::GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const
  90.127 +{
  90.128 +    if (GetHIDDeviceManager())
  90.129 +        return static_cast<HIDDeviceManager*>(GetHIDDeviceManager())->GetHIDDeviceDesc(path, pdevDesc);
  90.130 +    return false;
  90.131 +}
  90.132 +
  90.133 +
  90.134 +//-------------------------------------------------------------------------------------
  90.135 +// ***** DeviceManager Thread 
  90.136 +
  90.137 +DeviceManagerThread::DeviceManagerThread(DeviceManager* pdevMgr)
  90.138 +    : Thread(ThreadStackSize), hCommandEvent(0), pDeviceMgr(pdevMgr)
  90.139 +{    
  90.140 +    // Create a non-signaled manual-reset event.
  90.141 +    hCommandEvent = ::CreateEvent(0, TRUE, FALSE, 0);
  90.142 +    if (!hCommandEvent)
  90.143 +        return;
  90.144 +
  90.145 +    // Must add event before starting.
  90.146 +    AddOverlappedEvent(0, hCommandEvent);
  90.147 +
  90.148 +	// Create device messages object.
  90.149 +	pStatusObject = *new DeviceStatus(this);
  90.150 +}
  90.151 +
  90.152 +DeviceManagerThread::~DeviceManagerThread()
  90.153 +{
  90.154 +    // Remove overlapped event [0], after thread service exit.
  90.155 +    if (hCommandEvent)
  90.156 +    {
  90.157 +        RemoveOverlappedEvent(0, hCommandEvent);    
  90.158 +        ::CloseHandle(hCommandEvent);
  90.159 +        hCommandEvent = 0;
  90.160 +    }
  90.161 +}
  90.162 +
  90.163 +int DeviceManagerThread::Run()
  90.164 +{
  90.165 +    ThreadCommand::PopBuffer command;
  90.166 +
  90.167 +    SetThreadName("OVR::DeviceManagerThread");
  90.168 +    LogText("OVR::DeviceManagerThread - running (ThreadId=0x%X).\n", GetThreadId());
  90.169 +  
  90.170 +	if (!pStatusObject->Initialize())
  90.171 +	{
  90.172 +		LogText("OVR::DeviceManagerThread - failed to initialize MessageObject.\n");
  90.173 +	}
  90.174 +
  90.175 +    while(!IsExiting())
  90.176 +    {
  90.177 +        // PopCommand will reset event on empty queue.
  90.178 +        if (PopCommand(&command))
  90.179 +        {
  90.180 +            command.Execute();
  90.181 +        }
  90.182 +        else
  90.183 +        {
  90.184 +            DWORD eventIndex = 0;
  90.185 +            do {
  90.186 +                UPInt numberOfWaitHandles = WaitHandles.GetSize();
  90.187 +				Debug_WaitedObjectCount = (DWORD)numberOfWaitHandles;
  90.188 +
  90.189 +                DWORD waitMs = INFINITE;
  90.190 +
  90.191 +                // If devices have time-dependent logic registered, get the longest wait
  90.192 +                // allowed based on current ticks.
  90.193 +                if (!TicksNotifiers.IsEmpty())
  90.194 +                {
  90.195 +                    UInt64 ticksMks = Timer::GetTicks();
  90.196 +                    DWORD  waitAllowed;
  90.197 +                    
  90.198 +                    for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++)
  90.199 +                    {
  90.200 +                        waitAllowed = (DWORD)(TicksNotifiers[j]->OnTicks(ticksMks) / Timer::MksPerMs);
  90.201 +                        if (waitAllowed < waitMs)
  90.202 +                            waitMs = waitAllowed;
  90.203 +                    }
  90.204 +                }
  90.205 +          
  90.206 +				// Wait for event signals or window messages.
  90.207 +                eventIndex = MsgWaitForMultipleObjects((DWORD)numberOfWaitHandles, &WaitHandles[0], FALSE, waitMs, QS_ALLINPUT);
  90.208 +				
  90.209 +                if (eventIndex != WAIT_FAILED)
  90.210 +                {
  90.211 +                    if (eventIndex == WAIT_TIMEOUT)
  90.212 +                        continue;
  90.213 +
  90.214 +                    // TBD: Does this ever apply?
  90.215 +                    OVR_ASSERT(eventIndex < WAIT_ABANDONED_0);
  90.216 +
  90.217 +                    if (eventIndex == WAIT_OBJECT_0)
  90.218 +                    {
  90.219 +                        // Handle [0] services commands.
  90.220 +                        break;
  90.221 +                    }
  90.222 +					else if (eventIndex == WAIT_OBJECT_0 + numberOfWaitHandles)
  90.223 +					{
  90.224 +						// Handle Windows messages.
  90.225 +						pStatusObject->ProcessMessages();
  90.226 +					}
  90.227 +                    else 
  90.228 +                    {
  90.229 +                        // Notify waiting device that its event is signaled.
  90.230 +                        unsigned i = eventIndex - WAIT_OBJECT_0; 
  90.231 +                        OVR_ASSERT(i < numberOfWaitHandles);
  90.232 +                        if (WaitNotifiers[i])                        
  90.233 +                            WaitNotifiers[i]->OnOverlappedEvent(WaitHandles[i]);
  90.234 +                    }
  90.235 +                }
  90.236 +
  90.237 +            } while(eventIndex != WAIT_FAILED);
  90.238 +                    
  90.239 +        }
  90.240 +    }
  90.241 +
  90.242 +	pStatusObject->ShutDown();
  90.243 +
  90.244 +    LogText("OVR::DeviceManagerThread - exiting (ThreadId=0x%X).\n", GetThreadId());
  90.245 +    return 0;
  90.246 +}
  90.247 +
  90.248 +bool DeviceManagerThread::AddOverlappedEvent(Notifier* notify, HANDLE hevent)
  90.249 +{
  90.250 +    WaitNotifiers.PushBack(notify);
  90.251 +    WaitHandles.PushBack(hevent);
  90.252 +
  90.253 +    OVR_ASSERT(WaitNotifiers.GetSize() <= MAXIMUM_WAIT_OBJECTS);
  90.254 +    return true;
  90.255 +}
  90.256 +
  90.257 +bool DeviceManagerThread::RemoveOverlappedEvent(Notifier* notify, HANDLE hevent)
  90.258 +{
  90.259 +    // [0] is reserved for thread commands with notify of null, but we still
  90.260 +    // can use this function to remove it.
  90.261 +    for (UPInt i = 0; i < WaitNotifiers.GetSize(); i++)
  90.262 +    {
  90.263 +        if ((WaitNotifiers[i] == notify) && (WaitHandles[i] == hevent))
  90.264 +        {
  90.265 +            WaitNotifiers.RemoveAt(i);
  90.266 +            WaitHandles.RemoveAt(i);
  90.267 +            return true;
  90.268 +        }
  90.269 +    }
  90.270 +    return false;
  90.271 +}
  90.272 +
  90.273 +bool DeviceManagerThread::AddTicksNotifier(Notifier* notify)
  90.274 +{
  90.275 +     TicksNotifiers.PushBack(notify);
  90.276 +     return true;
  90.277 +}
  90.278 +
  90.279 +bool DeviceManagerThread::RemoveTicksNotifier(Notifier* notify)
  90.280 +{
  90.281 +    for (UPInt i = 0; i < TicksNotifiers.GetSize(); i++)
  90.282 +    {
  90.283 +        if (TicksNotifiers[i] == notify)
  90.284 +        {
  90.285 +            TicksNotifiers.RemoveAt(i);
  90.286 +            return true;
  90.287 +        }
  90.288 +    }
  90.289 +    return false;
  90.290 +}
  90.291 +
  90.292 +bool DeviceManagerThread::AddMessageNotifier(Notifier* notify)
  90.293 +{
  90.294 +	MessageNotifiers.PushBack(notify);
  90.295 +	return true;
  90.296 +}
  90.297 +
  90.298 +bool DeviceManagerThread::RemoveMessageNotifier(Notifier* notify)
  90.299 +{
  90.300 +	for (UPInt i = 0; i < MessageNotifiers.GetSize(); i++)
  90.301 +	{
  90.302 +		if (MessageNotifiers[i] == notify)
  90.303 +		{
  90.304 +			MessageNotifiers.RemoveAt(i);
  90.305 +			return true;
  90.306 +		}
  90.307 +	}
  90.308 +	return false;
  90.309 +}
  90.310 +
  90.311 +bool DeviceManagerThread::OnMessage(MessageType type, const String& devicePath)
  90.312 +{
  90.313 +	Notifier::DeviceMessageType notifierMessageType = Notifier::DeviceMessage_DeviceAdded;
  90.314 +	if (type == DeviceAdded)
  90.315 +	{
  90.316 +	}
  90.317 +	else if (type == DeviceRemoved)
  90.318 +	{
  90.319 +		notifierMessageType = Notifier::DeviceMessage_DeviceRemoved;
  90.320 +	}
  90.321 +	else
  90.322 +	{
  90.323 +		OVR_ASSERT(false);
  90.324 +	}
  90.325 +
  90.326 +	bool error = false;
  90.327 +    bool deviceFound = false;
  90.328 +	for (UPInt i = 0; i < MessageNotifiers.GetSize(); i++)
  90.329 +    {
  90.330 +		if (MessageNotifiers[i] && 
  90.331 +			MessageNotifiers[i]->OnDeviceMessage(notifierMessageType, devicePath, &error))
  90.332 +		{
  90.333 +			// The notifier belonged to a device with the specified device name so we're done.
  90.334 +            deviceFound = true;
  90.335 +			break;
  90.336 +		}
  90.337 +    }
  90.338 +    if (type == DeviceAdded && !deviceFound)
  90.339 +    {
  90.340 +        Lock::Locker devMgrLock(&DevMgrLock);
  90.341 +        // a new device was connected. Go through all device factories and
  90.342 +        // try to detect the device using HIDDeviceDesc.
  90.343 +        HIDDeviceDesc devDesc;
  90.344 +        if (pDeviceMgr->GetHIDDeviceDesc(devicePath, &devDesc))
  90.345 +        {
  90.346 +            Lock::Locker deviceLock(pDeviceMgr->GetLock());
  90.347 +            DeviceFactory* factory = pDeviceMgr->Factories.GetFirst();
  90.348 +            while(!pDeviceMgr->Factories.IsNull(factory))
  90.349 +            {
  90.350 +                if (factory->DetectHIDDevice(pDeviceMgr, devDesc))
  90.351 +                {
  90.352 +                    deviceFound = true;
  90.353 +                    break;
  90.354 +                }
  90.355 +                factory = factory->pNext;
  90.356 +            }
  90.357 +        }
  90.358 +    }
  90.359 +
  90.360 +    if (!deviceFound && strstr(devicePath.ToCStr(), "#OVR00"))
  90.361 +    {
  90.362 +        Ptr<DeviceManager> pmgr;
  90.363 +        {
  90.364 +            Lock::Locker devMgrLock(&DevMgrLock);
  90.365 +            pmgr = pDeviceMgr;
  90.366 +        }
  90.367 +        // HMD plugged/unplugged
  90.368 +        // This is not a final solution to enumerate HMD devices and get
  90.369 +        // a first available handle. This won't work with multiple rifts.
  90.370 +        // @TODO (!AB)
  90.371 +        pmgr->EnumerateDevices<HMDDevice>();
  90.372 +    }
  90.373 +
  90.374 +	return !error;
  90.375 +}
  90.376 +
  90.377 +void DeviceManagerThread::DetachDeviceManager()
  90.378 +{
  90.379 +    Lock::Locker devMgrLock(&DevMgrLock);
  90.380 +    pDeviceMgr = NULL;
  90.381 +}
  90.382 +
  90.383 +} // namespace Win32
  90.384 +
  90.385 +
  90.386 +//-------------------------------------------------------------------------------------
  90.387 +// ***** Creation
  90.388 +
  90.389 +
  90.390 +// Creates a new DeviceManager and initializes OVR.
  90.391 +DeviceManager* DeviceManager::Create()
  90.392 +{
  90.393 +
  90.394 +    if (!System::IsInitialized())
  90.395 +    {
  90.396 +        // Use custom message, since Log is not yet installed.
  90.397 +        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
  90.398 +            LogMessage(Log_Debug, "DeviceManager::Create failed - OVR::System not initialized"); );
  90.399 +        return 0;
  90.400 +    }
  90.401 +
  90.402 +    Ptr<Win32::DeviceManager> manager = *new Win32::DeviceManager;
  90.403 +
  90.404 +    if (manager)
  90.405 +    {
  90.406 +        if (manager->Initialize(0))
  90.407 +        {            
  90.408 +            manager->AddFactory(&SensorDeviceFactory::Instance);
  90.409 +            manager->AddFactory(&LatencyTestDeviceFactory::Instance);
  90.410 +            manager->AddFactory(&Win32::HMDDeviceFactory::Instance);
  90.411 +
  90.412 +            manager->AddRef();
  90.413 +        }
  90.414 +        else
  90.415 +        {
  90.416 +            manager.Clear();
  90.417 +        }
  90.418 +
  90.419 +    }    
  90.420 +
  90.421 +    return manager.GetPtr();
  90.422 +}
  90.423 +
  90.424 +
  90.425 +} // namespace OVR
  90.426 +
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/libovr/Src/win32/OVR_Win32_DeviceManager.h	Sat Sep 14 16:14:59 2013 +0300
    91.3 @@ -0,0 +1,146 @@
    91.4 +/************************************************************************************
    91.5 +
    91.6 +Filename    :   OVR_Win32_DeviceManager.h
    91.7 +Content     :   Win32-specific DeviceManager header.
    91.8 +Created     :   September 21, 2012
    91.9 +Authors     :   Michael Antonov
   91.10 +
   91.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   91.12 +
   91.13 +Use of this software is subject to the terms of the Oculus license
   91.14 +agreement provided at the time of installation or download, or which
   91.15 +otherwise accompanies this software in either electronic or hard copy form.
   91.16 +
   91.17 +*************************************************************************************/
   91.18 +
   91.19 +#ifndef OVR_Win32_DeviceManager_h
   91.20 +#define OVR_Win32_DeviceManager_h
   91.21 +
   91.22 +#include "OVR_DeviceImpl.h"
   91.23 +#include "OVR_Win32_DeviceStatus.h"
   91.24 +
   91.25 +#include "Kernel/OVR_Timer.h"
   91.26 +
   91.27 +
   91.28 +namespace OVR { namespace Win32 {
   91.29 +
   91.30 +class DeviceManagerThread;
   91.31 +
   91.32 +//-------------------------------------------------------------------------------------
   91.33 +// ***** Win32 DeviceManager
   91.34 +
   91.35 +class DeviceManager : public DeviceManagerImpl
   91.36 +{
   91.37 +public:
   91.38 +    DeviceManager();
   91.39 +    ~DeviceManager();
   91.40 +
   91.41 +    // Initialize/Shutdowncreate and shutdown manger thread.
   91.42 +    virtual bool Initialize(DeviceBase* parent);
   91.43 +    virtual void Shutdown();
   91.44 +
   91.45 +    virtual ThreadCommandQueue* GetThreadQueue();
   91.46 +    virtual ThreadId GetThreadId() const;
   91.47 +
   91.48 +    virtual DeviceEnumerator<> EnumerateDevicesEx(const DeviceEnumerationArgs& args);    
   91.49 +
   91.50 +    virtual bool  GetDeviceInfo(DeviceInfo* info) const;
   91.51 +
   91.52 +    // Fills HIDDeviceDesc by using the path.
   91.53 +    // Returns 'true' if successful, 'false' otherwise.
   91.54 +    bool GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const;
   91.55 +    
   91.56 +    Ptr<DeviceManagerThread> pThread;
   91.57 +};
   91.58 +
   91.59 +//-------------------------------------------------------------------------------------
   91.60 +// ***** Device Manager Background Thread
   91.61 +
   91.62 +class DeviceManagerThread : public Thread, public ThreadCommandQueue, public DeviceStatus::Notifier
   91.63 +{
   91.64 +    friend class DeviceManager;
   91.65 +    enum { ThreadStackSize = 32 * 1024 };
   91.66 +public:
   91.67 +    DeviceManagerThread(DeviceManager* pdevMgr);
   91.68 +    ~DeviceManagerThread();
   91.69 +
   91.70 +    virtual int Run();
   91.71 +
   91.72 +    // ThreadCommandQueue notifications for CommandEvent handling.
   91.73 +    virtual void OnPushNonEmpty_Locked() { ::SetEvent(hCommandEvent); }
   91.74 +    virtual void OnPopEmpty_Locked()     { ::ResetEvent(hCommandEvent); }
   91.75 +
   91.76 +
   91.77 +    // Notifier used for different updates (EVENT or regular timing or messages).
   91.78 +    class Notifier
   91.79 +    {
   91.80 +    public:
   91.81 +		// Called when overlapped I/O handle is signaled.
   91.82 +        virtual void    OnOverlappedEvent(HANDLE hevent) { OVR_UNUSED1(hevent); }
   91.83 +
   91.84 +        // Called when timing ticks are updated.
   91.85 +        // Returns the largest number of microseconds this function can
   91.86 +        // wait till next call.
   91.87 +        virtual UInt64  OnTicks(UInt64 ticksMks)
   91.88 +        { OVR_UNUSED1(ticksMks);  return Timer::MksPerSecond * 1000; }
   91.89 +
   91.90 +		enum DeviceMessageType
   91.91 +		{
   91.92 +			DeviceMessage_DeviceAdded     = 0,
   91.93 +			DeviceMessage_DeviceRemoved   = 1,
   91.94 +		};
   91.95 +
   91.96 +		// Called to notify device object.
   91.97 +		virtual bool    OnDeviceMessage(DeviceMessageType messageType, 
   91.98 +										const String& devicePath,
   91.99 +										bool* error) 
  91.100 +        { OVR_UNUSED3(messageType, devicePath, error); return false; }
  91.101 +    };
  91.102 +
  91.103 + 
  91.104 +    // Adds device's OVERLAPPED structure for I/O.
  91.105 +    // After it's added, Overlapped object will be signaled if a message arrives.
  91.106 +    bool AddOverlappedEvent(Notifier* notify, HANDLE hevent);
  91.107 +    bool RemoveOverlappedEvent(Notifier* notify, HANDLE hevent);
  91.108 +
  91.109 +    // Add notifier that will be called at regular intervals. 
  91.110 +    bool AddTicksNotifier(Notifier* notify);
  91.111 +    bool RemoveTicksNotifier(Notifier* notify);
  91.112 +
  91.113 +	bool AddMessageNotifier(Notifier* notify);
  91.114 +	bool RemoveMessageNotifier(Notifier* notify);
  91.115 +
  91.116 +    // DeviceStatus::Notifier interface.
  91.117 +	bool OnMessage(MessageType type, const String& devicePath);
  91.118 +
  91.119 +    void DetachDeviceManager();
  91.120 +
  91.121 +private:
  91.122 +    bool threadInitialized() { return hCommandEvent != 0; }
  91.123 +
  91.124 +    // Event used to wake us up thread commands are enqueued.    
  91.125 +    HANDLE                  hCommandEvent;
  91.126 +
  91.127 +    // Event notifications for devices whose OVERLAPPED I/O we service.
  91.128 +    // This list is modified through AddDeviceOverlappedEvent.
  91.129 +    // WaitHandles[0] always == hCommandEvent, with null device.
  91.130 +    Array<HANDLE>           WaitHandles;
  91.131 +    Array<Notifier*>        WaitNotifiers;
  91.132 +
  91.133 +    // Ticks notifiers - used for time-dependent events such as keep-alive.
  91.134 +    Array<Notifier*>        TicksNotifiers;
  91.135 +
  91.136 +	// Message notifiers.
  91.137 +    Array<Notifier*>        MessageNotifiers;
  91.138 +
  91.139 +	// Object that manages notifications originating from Windows messages.
  91.140 +	Ptr<DeviceStatus>		pStatusObject;
  91.141 +
  91.142 +    Lock                    DevMgrLock;
  91.143 +    // pDeviceMgr should be accessed under DevMgrLock
  91.144 +    DeviceManager*          pDeviceMgr; // back ptr, no addref. 
  91.145 +};
  91.146 +
  91.147 +}} // namespace Win32::OVR
  91.148 +
  91.149 +#endif // OVR_Win32_DeviceManager_h
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/libovr/Src/win32/OVR_Win32_DeviceStatus.cpp	Sat Sep 14 16:14:59 2013 +0300
    92.3 @@ -0,0 +1,350 @@
    92.4 +/************************************************************************************
    92.5 +
    92.6 +Filename    :   OVR_Win32_DeviceStatus.cpp
    92.7 +Content     :   Win32 implementation of DeviceStatus.
    92.8 +Created     :   January 24, 2013
    92.9 +Authors     :   Lee Cooper
   92.10 +
   92.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   92.12 +
   92.13 +Use of this software is subject to the terms of the Oculus license
   92.14 +agreement provided at the time of installation or download, or which
   92.15 +otherwise accompanies this software in either electronic or hard copy form.
   92.16 +
   92.17 +*************************************************************************************/
   92.18 +
   92.19 +#include "OVR_Win32_DeviceStatus.h"
   92.20 +
   92.21 +#include "OVR_Win32_HIDDevice.h"
   92.22 +
   92.23 +#include "Kernel/OVR_Log.h"
   92.24 +
   92.25 +#include <dbt.h>
   92.26 +
   92.27 +namespace OVR { namespace Win32 {
   92.28 +
   92.29 +static TCHAR windowClassName[] = TEXT("LibOVR_DeviceStatus_WindowClass");
   92.30 +
   92.31 +//-------------------------------------------------------------------------------------
   92.32 +DeviceStatus::DeviceStatus(Notifier* const pClient)
   92.33 +	: pNotificationClient(pClient), LastTimerId(0)
   92.34 +{	
   92.35 +}
   92.36 +
   92.37 +bool DeviceStatus::Initialize()
   92.38 +{
   92.39 +
   92.40 +	WNDCLASS wndClass;
   92.41 +	wndClass.style         = CS_HREDRAW | CS_VREDRAW;
   92.42 +	wndClass.lpfnWndProc   = WindowsMessageCallback;
   92.43 +	wndClass.cbClsExtra    = 0;
   92.44 +	wndClass.cbWndExtra    = 0;
   92.45 +	wndClass.hInstance     = 0;
   92.46 +	wndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
   92.47 +	wndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
   92.48 +	wndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
   92.49 +	wndClass.lpszMenuName  = NULL;
   92.50 +	wndClass.lpszClassName = windowClassName;
   92.51 +
   92.52 +	if (!RegisterClass(&wndClass))
   92.53 +	{
   92.54 +		OVR_ASSERT_LOG(false, ("Failed to register window class."));
   92.55 +		return false;
   92.56 +	}
   92.57 +
   92.58 +    // We're going to create a 'message-only' window. This will be hidden, can't be enumerated etc.
   92.59 +    // To do this we supply 'HWND_MESSAGE' as the hWndParent.
   92.60 +    // http://msdn.microsoft.com/en-us/library/ms632599%28VS.85%29.aspx#message_only
   92.61 +	hMessageWindow = CreateWindow(	windowClassName,
   92.62 +									windowClassName,
   92.63 +									WS_OVERLAPPEDWINDOW,
   92.64 +									CW_USEDEFAULT,
   92.65 +									CW_USEDEFAULT,
   92.66 +									CW_USEDEFAULT,
   92.67 +									CW_USEDEFAULT,
   92.68 +									HWND_MESSAGE,
   92.69 +									NULL,
   92.70 +									0,
   92.71 +									this);	// Pass this object via the CREATESTRUCT mechanism 
   92.72 +                                            // so that we can attach it to the window user data.
   92.73 +
   92.74 +    if (hMessageWindow == NULL)
   92.75 +	{
   92.76 +		OVR_ASSERT_LOG(false, ("Failed to create window."));
   92.77 +		return false;
   92.78 +	}
   92.79 +
   92.80 +    // According to MS, topmost windows receive WM_DEVICECHANGE faster.
   92.81 +	::SetWindowPos(hMessageWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
   92.82 +	UpdateWindow(hMessageWindow);
   92.83 +
   92.84 +
   92.85 +	// Register notification for additional HID messages.
   92.86 +    HIDDeviceManager* hidDeviceManager = new HIDDeviceManager(NULL);
   92.87 +	HidGuid = hidDeviceManager->GetHIDGuid();
   92.88 +    hidDeviceManager->Release();
   92.89 +
   92.90 +	DEV_BROADCAST_DEVICEINTERFACE notificationFilter;
   92.91 +
   92.92 +	ZeroMemory(&notificationFilter, sizeof(notificationFilter));
   92.93 +	notificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
   92.94 +	notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
   92.95 +	//notificationFilter.dbcc_classguid = hidguid;
   92.96 +
   92.97 +    // We need DEVICE_NOTIFY_ALL_INTERFACE_CLASSES to detect
   92.98 +    // HDMI plug/unplug events.
   92.99 +	hDeviceNotify = RegisterDeviceNotification(	
  92.100 +        hMessageWindow,
  92.101 +		&notificationFilter,
  92.102 +		DEVICE_NOTIFY_ALL_INTERFACE_CLASSES|DEVICE_NOTIFY_WINDOW_HANDLE);
  92.103 +
  92.104 +	if (hDeviceNotify == NULL)
  92.105 +	{
  92.106 +		OVR_ASSERT_LOG(false, ("Failed to register for device notifications."));
  92.107 +		return false;
  92.108 +	}
  92.109 +
  92.110 +	return true;
  92.111 +}
  92.112 +
  92.113 +void DeviceStatus::ShutDown()
  92.114 +{
  92.115 +	OVR_ASSERT(hMessageWindow);
  92.116 +
  92.117 +	if (!UnregisterDeviceNotification(hDeviceNotify))
  92.118 +	{
  92.119 +		OVR_ASSERT_LOG(false, ("Failed to unregister device notification."));
  92.120 +	}
  92.121 +
  92.122 +	PostMessage(hMessageWindow, WM_CLOSE, 0, 0);
  92.123 +
  92.124 +	while (hMessageWindow != NULL)
  92.125 +	{
  92.126 +		ProcessMessages();
  92.127 +		Sleep(1);
  92.128 +	}
  92.129 +
  92.130 +    if (!UnregisterClass(windowClassName, NULL))
  92.131 +    {
  92.132 +        OVR_ASSERT_LOG(false, ("Failed to unregister window class."));
  92.133 +    }
  92.134 +}
  92.135 +
  92.136 +DeviceStatus::~DeviceStatus()
  92.137 +{    
  92.138 +	OVR_ASSERT_LOG(hMessageWindow == NULL, ("Need to call 'ShutDown' from DeviceManagerThread."));
  92.139 +}
  92.140 +
  92.141 +void DeviceStatus::ProcessMessages()
  92.142 +{
  92.143 +	OVR_ASSERT_LOG(hMessageWindow != NULL, ("Need to call 'Initialize' before first use."));
  92.144 +
  92.145 +	MSG msg;
  92.146 +
  92.147 +	// Note WM_DEVICECHANGED messages are dispatched but not retrieved by PeekMessage.
  92.148 +    // I think this is because they are pending, non-queued messages.
  92.149 +	while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 
  92.150 +	{
  92.151 +		TranslateMessage(&msg);
  92.152 +		DispatchMessage(&msg);
  92.153 +	}
  92.154 +}
  92.155 +
  92.156 +bool DeviceStatus::MessageCallback(WORD messageType, const String& devicePath)
  92.157 +{
  92.158 +	bool rv = true;
  92.159 +	if (messageType == DBT_DEVICEARRIVAL)
  92.160 +	{
  92.161 +		rv = pNotificationClient->OnMessage(Notifier::DeviceAdded, devicePath);
  92.162 +	}
  92.163 +	else if (messageType == DBT_DEVICEREMOVECOMPLETE)
  92.164 +	{
  92.165 +		pNotificationClient->OnMessage(Notifier::DeviceRemoved, devicePath);
  92.166 +	}
  92.167 +	else
  92.168 +	{
  92.169 +		OVR_ASSERT(0);
  92.170 +	}
  92.171 +	return rv;
  92.172 +}
  92.173 +
  92.174 +void DeviceStatus::CleanupRecoveryTimer(UPInt index)
  92.175 +{
  92.176 +    ::KillTimer(hMessageWindow, RecoveryTimers[index].TimerId);
  92.177 +    RecoveryTimers.RemoveAt(index);
  92.178 +}
  92.179 +    
  92.180 +DeviceStatus::RecoveryTimerDesc* 
  92.181 +DeviceStatus::FindRecoveryTimer(UINT_PTR timerId, UPInt* pindex)
  92.182 +{
  92.183 +    for (UPInt i = 0, n = RecoveryTimers.GetSize(); i < n; ++i)
  92.184 +    {
  92.185 +        RecoveryTimerDesc* pdesc = &RecoveryTimers[i];
  92.186 +        if (pdesc->TimerId == timerId)
  92.187 +        {
  92.188 +            *pindex = i;
  92.189 +            return pdesc;
  92.190 +        }
  92.191 +    }
  92.192 +    return NULL;
  92.193 +}
  92.194 +
  92.195 +void DeviceStatus::FindAndCleanupRecoveryTimer(const String& devicePath)
  92.196 +{
  92.197 +    for (UPInt i = 0, n = RecoveryTimers.GetSize(); i < n; ++i)
  92.198 +    {
  92.199 +        RecoveryTimerDesc* pdesc = &RecoveryTimers[i];
  92.200 +        if (pdesc->DevicePath.CompareNoCase(devicePath))
  92.201 +        {
  92.202 +            CleanupRecoveryTimer(i);
  92.203 +            break;
  92.204 +        }
  92.205 +    }
  92.206 +}
  92.207 +
  92.208 +LRESULT CALLBACK DeviceStatus::WindowsMessageCallback(  HWND hwnd, 
  92.209 +                                                        UINT message, 
  92.210 +                                                        WPARAM wParam, 
  92.211 +                                                        LPARAM lParam)
  92.212 +{
  92.213 +	switch (message)
  92.214 +	{
  92.215 +	case WM_CREATE:
  92.216 +		{
  92.217 +			// Setup window user data with device status object pointer.
  92.218 +			LPCREATESTRUCT create_struct = reinterpret_cast<LPCREATESTRUCT>(lParam);
  92.219 +			void *lpCreateParam = create_struct->lpCreateParams;
  92.220 +			DeviceStatus *pDeviceStatus = reinterpret_cast<DeviceStatus*>(lpCreateParam);
  92.221 +
  92.222 +			SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(pDeviceStatus));
  92.223 +		}
  92.224 +		return 0;	// Return 0 for successfully handled WM_CREATE.
  92.225 +
  92.226 +	case WM_DEVICECHANGE:
  92.227 +		{
  92.228 +			WORD loword = LOWORD(wParam);
  92.229 +
  92.230 +			if (loword != DBT_DEVICEARRIVAL &&
  92.231 +				loword != DBT_DEVICEREMOVECOMPLETE) 
  92.232 +			{
  92.233 +				// Ignore messages other than device arrive and remove complete 
  92.234 +                // (we're not handling intermediate ones).
  92.235 +				return TRUE;	// Grant WM_DEVICECHANGE request.
  92.236 +			}
  92.237 +
  92.238 +			DEV_BROADCAST_DEVICEINTERFACE* hdr;
  92.239 +			hdr = (DEV_BROADCAST_DEVICEINTERFACE*) lParam;
  92.240 +
  92.241 +			if (hdr->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE) 
  92.242 +			{
  92.243 +				// Ignore non interface device messages.
  92.244 +				return TRUE;	// Grant WM_DEVICECHANGE request.
  92.245 +			}
  92.246 +
  92.247 +			LONG_PTR userData = GetWindowLongPtr(hwnd, GWLP_USERDATA);
  92.248 +			OVR_ASSERT(userData != NULL);
  92.249 +
  92.250 +			// Call callback on device messages object with the device path.
  92.251 +			DeviceStatus* pDeviceStatus = (DeviceStatus*) userData;
  92.252 +			String devicePath(hdr->dbcc_name);
  92.253 +
  92.254 +            // check if HID device caused the event...
  92.255 +            if (pDeviceStatus->HidGuid == hdr->dbcc_classguid)
  92.256 +            {
  92.257 +                // check if recovery timer is already running; stop it and 
  92.258 +                // remove it, if so.
  92.259 +                pDeviceStatus->FindAndCleanupRecoveryTimer(devicePath);
  92.260 +
  92.261 +                if (!pDeviceStatus->MessageCallback(loword, devicePath))
  92.262 +                {
  92.263 +                    // hmmm.... unsuccessful
  92.264 +                    if (loword == DBT_DEVICEARRIVAL)
  92.265 +                    {
  92.266 +                        // Windows sometimes may return errors ERROR_SHARING_VIOLATION and
  92.267 +                        // ERROR_FILE_NOT_FOUND when trying to open an USB device via
  92.268 +                        // CreateFile. Need to start a recovery timer that will try to 
  92.269 +                        // re-open the device again.
  92.270 +                        OVR_DEBUG_LOG(("Adding failed, recovering through a timer..."));
  92.271 +                        UINT_PTR tid = ::SetTimer(hwnd, ++pDeviceStatus->LastTimerId, 
  92.272 +                            USBRecoveryTimeInterval, NULL);
  92.273 +                        RecoveryTimerDesc rtDesc;
  92.274 +                        rtDesc.TimerId = tid;
  92.275 +                        rtDesc.DevicePath = devicePath;
  92.276 +                        rtDesc.NumAttempts= 0;
  92.277 +                        pDeviceStatus->RecoveryTimers.PushBack(rtDesc);
  92.278 +                        // wrap around the timer counter, avoid timerId == 0...
  92.279 +                        if (pDeviceStatus->LastTimerId + 1 == 0)
  92.280 +                            pDeviceStatus->LastTimerId = 0;
  92.281 +                    }
  92.282 +                }
  92.283 +            }
  92.284 +            // Check if Oculus HDMI device was plugged/unplugged, preliminary
  92.285 +            // filtering. (is there any way to get GUID? !AB)
  92.286 +            //else if (strstr(devicePath.ToCStr(), "DISPLAY#"))
  92.287 +            else if (strstr(devicePath.ToCStr(), "#OVR00"))
  92.288 +            {
  92.289 +                pDeviceStatus->MessageCallback(loword, devicePath);
  92.290 +            }
  92.291 +		}
  92.292 +		return TRUE;	// Grant WM_DEVICECHANGE request.
  92.293 +
  92.294 +	case WM_TIMER:
  92.295 +		{
  92.296 +			if (wParam != 0)
  92.297 +			{
  92.298 +				LONG_PTR userData = GetWindowLongPtr(hwnd, GWLP_USERDATA);
  92.299 +				OVR_ASSERT(userData != NULL);
  92.300 +
  92.301 +				// Call callback on device messages object with the device path.
  92.302 +				DeviceStatus* pDeviceStatus = (DeviceStatus*) userData;
  92.303 +
  92.304 +                // Check if we have recovery timer running (actually, we must be!)
  92.305 +                UPInt rtIndex;
  92.306 +                RecoveryTimerDesc* prtDesc = pDeviceStatus->FindRecoveryTimer(wParam, &rtIndex);
  92.307 +				if (prtDesc)
  92.308 +				{
  92.309 +					if (pDeviceStatus->MessageCallback(DBT_DEVICEARRIVAL, prtDesc->DevicePath))
  92.310 +					{
  92.311 +                        OVR_DEBUG_LOG(("Recovered, adding is successful, cleaning up the timer..."));
  92.312 +                        // now it is successful, kill the timer and cleanup
  92.313 +                        pDeviceStatus->CleanupRecoveryTimer(rtIndex);
  92.314 +					}
  92.315 +                    else
  92.316 +                    {
  92.317 +                        if (++prtDesc->NumAttempts >= MaxUSBRecoveryAttempts)
  92.318 +                        {
  92.319 +                            OVR_DEBUG_LOG(("Failed to recover USB after %d attempts, path = '%s', aborting...",
  92.320 +                                prtDesc->NumAttempts, prtDesc->DevicePath.ToCStr()));
  92.321 +                            pDeviceStatus->CleanupRecoveryTimer(rtIndex);
  92.322 +                        }
  92.323 +                        else
  92.324 +                        {
  92.325 +                            OVR_DEBUG_LOG(("Failed to recover USB, %d attempts, path = '%s'",
  92.326 +                                prtDesc->NumAttempts, prtDesc->DevicePath.ToCStr()));
  92.327 +                        }
  92.328 +                    }
  92.329 +				}
  92.330 +			}
  92.331 +		}
  92.332 +		return 0;
  92.333 +
  92.334 +	case WM_CLOSE:
  92.335 +		{
  92.336 +			LONG_PTR userData = GetWindowLongPtr(hwnd, GWLP_USERDATA);
  92.337 +			OVR_ASSERT(userData != NULL);
  92.338 +			DeviceStatus* pDeviceStatus = (DeviceStatus*) userData;
  92.339 +			pDeviceStatus->hMessageWindow = NULL;
  92.340 +
  92.341 +			DestroyWindow(hwnd);
  92.342 +		}
  92.343 +		return 0;	// We processed the WM_CLOSE message.
  92.344 +
  92.345 +	case WM_DESTROY:
  92.346 +		PostQuitMessage(0);
  92.347 +		return 0;	// We processed the WM_DESTROY message.
  92.348 +	}
  92.349 +
  92.350 +	return DefWindowProc(hwnd, message, wParam, lParam);
  92.351 +}
  92.352 +
  92.353 +}} // namespace OVR::Win32
    93.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.2 +++ b/libovr/Src/win32/OVR_Win32_DeviceStatus.h	Sat Sep 14 16:14:59 2013 +0300
    93.3 @@ -0,0 +1,101 @@
    93.4 +/************************************************************************************
    93.5 +
    93.6 +Filename    :   OVR_Win32_DeviceStatus.h
    93.7 +Content     :   Win32-specific DeviceStatus header.
    93.8 +Created     :   January 24, 2013
    93.9 +Authors     :   Lee Cooper
   93.10 +
   93.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   93.12 +
   93.13 +Use of this software is subject to the terms of the Oculus license
   93.14 +agreement provided at the time of installation or download, or which
   93.15 +otherwise accompanies this software in either electronic or hard copy form.
   93.16 +
   93.17 +*************************************************************************************/
   93.18 +
   93.19 +#ifndef OVR_Win32_DeviceStatus_h
   93.20 +#define OVR_Win32_DeviceStatus_h
   93.21 +
   93.22 +#include <windows.h>
   93.23 +#include "Kernel/OVR_String.h"
   93.24 +#include "Kernel/OVR_RefCount.h"
   93.25 +#include "Kernel/OVR_Array.h"
   93.26 +
   93.27 +namespace OVR { namespace Win32 {
   93.28 +
   93.29 +//-------------------------------------------------------------------------------------
   93.30 +// ***** DeviceStatus
   93.31 +//
   93.32 +// DeviceStatus abstracts the handling of windows messages of interest for
   93.33 +// example the WM_DEVICECHANGED message which occurs when a device is plugged/unplugged.
   93.34 +// The device manager thread creates an instance of this class and passes its pointer
   93.35 +// in the constructor. That thread is also responsible for periodically calling 'ProcessMessages'
   93.36 +// to process queued windows messages. The client is notified via the 'OnMessage' method
   93.37 +// declared in the 'DeviceMessages::Notifier' interface.
   93.38 +class DeviceStatus : public RefCountBase<DeviceStatus>
   93.39 +{
   93.40 +public:
   93.41 +
   93.42 +	// Notifier used for device messages.
   93.43 +	class Notifier  
   93.44 +	{
   93.45 +	public:
   93.46 +		enum MessageType
   93.47 +		{
   93.48 +			DeviceAdded     = 0,
   93.49 +			DeviceRemoved   = 1,
   93.50 +		};
   93.51 +
   93.52 +		virtual bool OnMessage(MessageType type, const String& devicePath) 
   93.53 +        { OVR_UNUSED2(type, devicePath); return true; }
   93.54 +	};
   93.55 +
   93.56 +	DeviceStatus(Notifier* const pClient);
   93.57 +	~DeviceStatus();
   93.58 +
   93.59 +	void operator = (const DeviceStatus&);	// No assignment implementation.
   93.60 +
   93.61 +	bool Initialize();
   93.62 +	void ShutDown();
   93.63 +
   93.64 +	void ProcessMessages();
   93.65 +
   93.66 +private:	
   93.67 +    enum 
   93.68 +    { 
   93.69 +        MaxUSBRecoveryAttempts  = 20,
   93.70 +        USBRecoveryTimeInterval = 500   // ms
   93.71 +    };
   93.72 +    struct RecoveryTimerDesc
   93.73 +    {
   93.74 +        UINT_PTR    TimerId;
   93.75 +        String      DevicePath;
   93.76 +        unsigned    NumAttempts;
   93.77 +    };
   93.78 +
   93.79 +	static LRESULT CALLBACK WindowsMessageCallback( HWND hwnd, 
   93.80 +                                                    UINT message, 
   93.81 +                                                    WPARAM wParam, 
   93.82 +                                                    LPARAM lParam);
   93.83 +
   93.84 +	bool MessageCallback(WORD messageType, const String& devicePath);
   93.85 +
   93.86 +    void CleanupRecoveryTimer(UPInt index);
   93.87 +    RecoveryTimerDesc* FindRecoveryTimer(UINT_PTR timerId, UPInt* pindex);
   93.88 +    void FindAndCleanupRecoveryTimer(const String& devicePath);
   93.89 +
   93.90 +private: // data
   93.91 +    Notifier* const     pNotificationClient;	// Don't reference count a back-pointer.
   93.92 +
   93.93 +    HWND                hMessageWindow;
   93.94 +    HDEVNOTIFY          hDeviceNotify;
   93.95 +
   93.96 +    UINT_PTR            LastTimerId;
   93.97 +    Array<RecoveryTimerDesc> RecoveryTimers;
   93.98 +
   93.99 +    GUID                HidGuid;
  93.100 +};
  93.101 +
  93.102 +}} // namespace OVR::Win32
  93.103 +
  93.104 +#endif // OVR_Win32_DeviceStatus_h
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/libovr/Src/win32/OVR_Win32_HIDDevice.cpp	Sat Sep 14 16:14:59 2013 +0300
    94.3 @@ -0,0 +1,637 @@
    94.4 +/************************************************************************************
    94.5 +
    94.6 +Filename    :   OVR_Win32_HIDDevice.cpp
    94.7 +Content     :   Win32 HID device implementation.
    94.8 +Created     :   February 22, 2013
    94.9 +Authors     :   Lee Cooper
   94.10 +
   94.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   94.12 +
   94.13 +Use of this software is subject to the terms of the Oculus license
   94.14 +agreement provided at the time of installation or download, or which
   94.15 +otherwise accompanies this software in either electronic or hard copy form.
   94.16 +
   94.17 +*************************************************************************************/
   94.18 +
   94.19 +#include "OVR_Win32_HIDDevice.h"
   94.20 +#include "OVR_Win32_DeviceManager.h"
   94.21 +
   94.22 +#include "Kernel/OVR_System.h"
   94.23 +#include "Kernel/OVR_Log.h"
   94.24 +
   94.25 +namespace OVR { namespace Win32 {
   94.26 +
   94.27 +//-------------------------------------------------------------------------------------
   94.28 +// HIDDevicePathWrapper is a simple class used to extract HID device file path
   94.29 +// through SetupDiGetDeviceInterfaceDetail. We use a class since this is a bit messy.
   94.30 +class HIDDevicePathWrapper
   94.31 +{
   94.32 +    SP_INTERFACE_DEVICE_DETAIL_DATA_A* pData;
   94.33 +public:
   94.34 +    HIDDevicePathWrapper() : pData(0) { }
   94.35 +    ~HIDDevicePathWrapper() { if (pData) OVR_FREE(pData); }
   94.36 +
   94.37 +    const char* GetPath() const { return pData ? pData->DevicePath : 0; }
   94.38 +
   94.39 +    bool InitPathFromInterfaceData(HDEVINFO hdevInfoSet, SP_DEVICE_INTERFACE_DATA* pidata);
   94.40 +};
   94.41 +
   94.42 +bool HIDDevicePathWrapper::InitPathFromInterfaceData(HDEVINFO hdevInfoSet, SP_DEVICE_INTERFACE_DATA* pidata)
   94.43 +{
   94.44 +    DWORD detailSize = 0;
   94.45 +    // SetupDiGetDeviceInterfaceDetailA returns "not enough buffer error code"
   94.46 +    // doe size request. Just check valid size.
   94.47 +    SetupDiGetDeviceInterfaceDetailA(hdevInfoSet, pidata, NULL, 0, &detailSize, NULL);
   94.48 +    if (!detailSize ||
   94.49 +        ((pData = (SP_INTERFACE_DEVICE_DETAIL_DATA_A*)OVR_ALLOC(detailSize)) == 0))
   94.50 +        return false;
   94.51 +    pData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA_A);
   94.52 +
   94.53 +    if (!SetupDiGetDeviceInterfaceDetailA(hdevInfoSet, pidata, pData, detailSize, NULL, NULL))
   94.54 +        return false;
   94.55 +    return true;
   94.56 +}
   94.57 +
   94.58 +
   94.59 +//-------------------------------------------------------------------------------------
   94.60 +// **** Win32::DeviceManager
   94.61 +
   94.62 +HIDDeviceManager::HIDDeviceManager(DeviceManager* manager)
   94.63 + :  Manager(manager)
   94.64 +{
   94.65 +    hHidLib = ::LoadLibraryA("hid.dll");
   94.66 +    OVR_ASSERT_LOG(hHidLib, ("Couldn't load Win32 'hid.dll'."));
   94.67 +
   94.68 +    OVR_RESOLVE_HIDFUNC(HidD_GetHidGuid);
   94.69 +    OVR_RESOLVE_HIDFUNC(HidD_SetNumInputBuffers);
   94.70 +    OVR_RESOLVE_HIDFUNC(HidD_GetFeature);
   94.71 +    OVR_RESOLVE_HIDFUNC(HidD_SetFeature);
   94.72 +    OVR_RESOLVE_HIDFUNC(HidD_GetAttributes);
   94.73 +    OVR_RESOLVE_HIDFUNC(HidD_GetManufacturerString);
   94.74 +    OVR_RESOLVE_HIDFUNC(HidD_GetProductString);
   94.75 +    OVR_RESOLVE_HIDFUNC(HidD_GetSerialNumberString);
   94.76 +    OVR_RESOLVE_HIDFUNC(HidD_GetPreparsedData);   
   94.77 +    OVR_RESOLVE_HIDFUNC(HidD_FreePreparsedData);  
   94.78 +    OVR_RESOLVE_HIDFUNC(HidP_GetCaps);    
   94.79 +
   94.80 +    if (HidD_GetHidGuid)
   94.81 +        HidD_GetHidGuid(&HidGuid);
   94.82 +}
   94.83 +
   94.84 +HIDDeviceManager::~HIDDeviceManager()
   94.85 +{
   94.86 +    ::FreeLibrary(hHidLib);
   94.87 +}
   94.88 +
   94.89 +bool HIDDeviceManager::Initialize()
   94.90 +{
   94.91 +    return true;
   94.92 +}
   94.93 +
   94.94 +void HIDDeviceManager::Shutdown()
   94.95 +{   
   94.96 +    LogText("OVR::Win32::HIDDeviceManager - shutting down.\n");
   94.97 +}
   94.98 +
   94.99 +bool HIDDeviceManager::Enumerate(HIDEnumerateVisitor* enumVisitor)
  94.100 +{
  94.101 +    HDEVINFO                 hdevInfoSet;
  94.102 +    SP_DEVICE_INTERFACE_DATA interfaceData;
  94.103 +    interfaceData.cbSize = sizeof(interfaceData);
  94.104 +
  94.105 +    // Get handle to info data set describing all available HIDs.
  94.106 +    hdevInfoSet = SetupDiGetClassDevsA(&HidGuid, NULL, NULL, DIGCF_INTERFACEDEVICE | DIGCF_PRESENT);
  94.107 +    if (hdevInfoSet == INVALID_HANDLE_VALUE)
  94.108 +        return false;
  94.109 +
  94.110 +    for(int deviceIndex = 0;
  94.111 +        SetupDiEnumDeviceInterfaces(hdevInfoSet, NULL, &HidGuid, deviceIndex, &interfaceData);
  94.112 +        deviceIndex++)
  94.113 +    {
  94.114 +        // For each device, we extract its file path and open it to get attributes,
  94.115 +        // such as vendor and product id. If anything goes wrong, we move onto next device.
  94.116 +        HIDDevicePathWrapper pathWrapper;
  94.117 +        if (!pathWrapper.InitPathFromInterfaceData(hdevInfoSet, &interfaceData))
  94.118 +            continue;
  94.119 +
  94.120 +        // Look for the device to check if it is already opened.
  94.121 +        Ptr<DeviceCreateDesc> existingDevice = Manager->FindDevice(pathWrapper.GetPath());
  94.122 +        // if device exists and it is opened then most likely the CreateHIDFile
  94.123 +        // will fail; therefore, we just set Enumerated to 'true' and continue.
  94.124 +        if (existingDevice && existingDevice->pDevice)
  94.125 +        {
  94.126 +            existingDevice->Enumerated = true;
  94.127 +            continue;
  94.128 +        }
  94.129 +
  94.130 +        // open device in non-exclusive mode for detection...
  94.131 +        HANDLE hidDev = CreateHIDFile(pathWrapper.GetPath(), false);
  94.132 +        if (hidDev == INVALID_HANDLE_VALUE)
  94.133 +            continue;
  94.134 +
  94.135 +        HIDDeviceDesc devDesc;
  94.136 +        devDesc.Path = pathWrapper.GetPath();
  94.137 +        if (initVendorProductVersion(hidDev, &devDesc) &&
  94.138 +            enumVisitor->MatchVendorProduct(devDesc.VendorId, devDesc.ProductId) &&
  94.139 +            initUsage(hidDev, &devDesc))
  94.140 +        {
  94.141 +            initStrings(hidDev, &devDesc);
  94.142 +
  94.143 +            // Construct minimal device that the visitor callback can get feature reports from.
  94.144 +            Win32::HIDDevice device(this, hidDev);
  94.145 +            enumVisitor->Visit(device, devDesc);
  94.146 +        }
  94.147 +
  94.148 +        ::CloseHandle(hidDev);
  94.149 +    }
  94.150 +
  94.151 +    SetupDiDestroyDeviceInfoList(hdevInfoSet);
  94.152 +    return true;
  94.153 +}
  94.154 +
  94.155 +bool HIDDeviceManager::GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const
  94.156 +{
  94.157 +    // open device in non-exclusive mode for detection...
  94.158 +    HANDLE hidDev = CreateHIDFile(path, false);
  94.159 +    if (hidDev == INVALID_HANDLE_VALUE)
  94.160 +        return false;
  94.161 +
  94.162 +    pdevDesc->Path = path;
  94.163 +    getFullDesc(hidDev, pdevDesc);
  94.164 +
  94.165 +    ::CloseHandle(hidDev);
  94.166 +    return true;
  94.167 +}
  94.168 +
  94.169 +OVR::HIDDevice* HIDDeviceManager::Open(const String& path)
  94.170 +{
  94.171 +
  94.172 +    Ptr<Win32::HIDDevice> device = *new Win32::HIDDevice(this);
  94.173 +
  94.174 +    if (device->HIDInitialize(path))
  94.175 +    {
  94.176 +        device->AddRef();        
  94.177 +        return device;
  94.178 +    }
  94.179 +
  94.180 +    return NULL;
  94.181 +}
  94.182 +
  94.183 +bool HIDDeviceManager::getFullDesc(HANDLE hidDev, HIDDeviceDesc* desc) const
  94.184 +{
  94.185 +
  94.186 +    if (!initVendorProductVersion(hidDev, desc))
  94.187 +    {
  94.188 +        return false;
  94.189 +    }
  94.190 +
  94.191 +    if (!initUsage(hidDev, desc))
  94.192 +    {
  94.193 +        return false;
  94.194 +    }
  94.195 +
  94.196 +    initStrings(hidDev, desc);
  94.197 +
  94.198 +    return true;
  94.199 +}
  94.200 +
  94.201 +bool HIDDeviceManager::initVendorProductVersion(HANDLE hidDev, HIDDeviceDesc* desc) const
  94.202 +{
  94.203 +    HIDD_ATTRIBUTES attr;
  94.204 +    attr.Size = sizeof(attr);
  94.205 +    if (!HidD_GetAttributes(hidDev, &attr))
  94.206 +        return false;
  94.207 +    desc->VendorId      = attr.VendorID;
  94.208 +    desc->ProductId     = attr.ProductID;
  94.209 +    desc->VersionNumber = attr.VersionNumber;
  94.210 +    return true;
  94.211 +}
  94.212 +
  94.213 +bool HIDDeviceManager::initUsage(HANDLE hidDev, HIDDeviceDesc* desc) const
  94.214 +{
  94.215 +    bool                 result = false;
  94.216 +    HIDP_CAPS            caps;
  94.217 +    HIDP_PREPARSED_DATA* preparsedData = 0;
  94.218 +
  94.219 +    if (!HidD_GetPreparsedData(hidDev, &preparsedData))
  94.220 +        return false;
  94.221 +
  94.222 +    if (HidP_GetCaps(preparsedData, &caps) == HIDP_STATUS_SUCCESS)
  94.223 +    {
  94.224 +        desc->Usage                  = caps.Usage;
  94.225 +        desc->UsagePage              = caps.UsagePage;
  94.226 +        result = true;
  94.227 +    }
  94.228 +    HidD_FreePreparsedData(preparsedData);
  94.229 +    return result;
  94.230 +}
  94.231 +
  94.232 +void HIDDeviceManager::initStrings(HANDLE hidDev, HIDDeviceDesc* desc) const
  94.233 +{
  94.234 +    // Documentation mentions 126 as being the max for USB.
  94.235 +    wchar_t strBuffer[196];
  94.236 +
  94.237 +    // HidD_Get*String functions return nothing in buffer on failure,
  94.238 +    // so it's ok to do this without further error checking.
  94.239 +    strBuffer[0] = 0;
  94.240 +    HidD_GetManufacturerString(hidDev, strBuffer, sizeof(strBuffer));
  94.241 +    desc->Manufacturer = strBuffer;
  94.242 +
  94.243 +    strBuffer[0] = 0;
  94.244 +    HidD_GetProductString(hidDev, strBuffer, sizeof(strBuffer));
  94.245 +    desc->Product = strBuffer;
  94.246 +
  94.247 +    strBuffer[0] = 0;
  94.248 +    HidD_GetSerialNumberString(hidDev, strBuffer, sizeof(strBuffer));
  94.249 +    desc->SerialNumber = strBuffer;
  94.250 +}
  94.251 +
  94.252 +//-------------------------------------------------------------------------------------
  94.253 +// **** Win32::HIDDevice
  94.254 +
  94.255 +HIDDevice::HIDDevice(HIDDeviceManager* manager)
  94.256 + : HIDManager(manager), inMinimalMode(false), Device(0), ReadRequested(false)
  94.257 +{
  94.258 +    memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
  94.259 +}
  94.260 +
  94.261 +// This is a minimal constructor used during enumeration for us to pass
  94.262 +// a HIDDevice to the visit function (so that it can query feature reports). 
  94.263 +HIDDevice::HIDDevice(HIDDeviceManager* manager, HANDLE device)
  94.264 + : HIDManager(manager), inMinimalMode(true), Device(device), ReadRequested(true)
  94.265 +{
  94.266 +    memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
  94.267 +}
  94.268 +
  94.269 +HIDDevice::~HIDDevice()
  94.270 +{
  94.271 +    if (!inMinimalMode)
  94.272 +    {
  94.273 +        HIDShutdown();
  94.274 +    }
  94.275 +}
  94.276 +
  94.277 +bool HIDDevice::HIDInitialize(const String& path)
  94.278 +{
  94.279 +
  94.280 +    DevDesc.Path = path;
  94.281 +
  94.282 +    if (!openDevice())
  94.283 +    {
  94.284 +        LogText("OVR::Win32::HIDDevice - Failed to open HIDDevice: ", path);
  94.285 +        return false;
  94.286 +    }
  94.287 +
  94.288 +
  94.289 +    HIDManager->Manager->pThread->AddTicksNotifier(this);
  94.290 +    HIDManager->Manager->pThread->AddMessageNotifier(this);
  94.291 +
  94.292 +    LogText("OVR::Win32::HIDDevice - Opened '%s'\n"
  94.293 +        "                    Manufacturer:'%s'  Product:'%s'  Serial#:'%s'\n",
  94.294 +        DevDesc.Path.ToCStr(),
  94.295 +        DevDesc.Manufacturer.ToCStr(), DevDesc.Product.ToCStr(),
  94.296 +        DevDesc.SerialNumber.ToCStr());
  94.297 +
  94.298 +    return true;
  94.299 +}
  94.300 +
  94.301 +bool HIDDevice::initInfo()
  94.302 +{
  94.303 +    // Device must have been successfully opened.
  94.304 +    OVR_ASSERT(Device);
  94.305 +
  94.306 +    // Get report lengths.
  94.307 +    HIDP_PREPARSED_DATA* preparsedData = 0;
  94.308 +    if (!HIDManager->HidD_GetPreparsedData(Device, &preparsedData))
  94.309 +    {
  94.310 +        return false;
  94.311 +    }
  94.312 +
  94.313 +    HIDP_CAPS caps;
  94.314 +    if (HIDManager->HidP_GetCaps(preparsedData, &caps) != HIDP_STATUS_SUCCESS)
  94.315 +    {
  94.316 +        HIDManager->HidD_FreePreparsedData(preparsedData);
  94.317 +        return false;
  94.318 +    }
  94.319 +
  94.320 +    InputReportBufferLength  = caps.InputReportByteLength;
  94.321 +    OutputReportBufferLength = caps.OutputReportByteLength;
  94.322 +    FeatureReportBufferLength= caps.FeatureReportByteLength;
  94.323 +    HIDManager->HidD_FreePreparsedData(preparsedData);
  94.324 +
  94.325 +    if (ReadBufferSize < InputReportBufferLength)
  94.326 +    {
  94.327 +        OVR_ASSERT_LOG(false, ("Input report buffer length is bigger than read buffer."));
  94.328 +        return false;
  94.329 +    }
  94.330 +
  94.331 +    // Get device desc.
  94.332 +    if (!HIDManager->getFullDesc(Device, &DevDesc))
  94.333 +    {
  94.334 +        OVR_ASSERT_LOG(false, ("Failed to get device desc while initializing device."));
  94.335 +        return false;
  94.336 +    }
  94.337 +
  94.338 +    return true;
  94.339 +}
  94.340 +
  94.341 +bool HIDDevice::openDevice()
  94.342 +{
  94.343 +    memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
  94.344 +
  94.345 +    Device = HIDManager->CreateHIDFile(DevDesc.Path.ToCStr());
  94.346 +    if (Device == INVALID_HANDLE_VALUE)
  94.347 +    {
  94.348 +        OVR_DEBUG_LOG(("Failed 'CreateHIDFile' while opening device, error = 0x%X.", 
  94.349 +			::GetLastError()));
  94.350 +        Device = 0;
  94.351 +        return false;
  94.352 +    }
  94.353 +
  94.354 +    if (!HIDManager->HidD_SetNumInputBuffers(Device, 128))
  94.355 +    {
  94.356 +        OVR_ASSERT_LOG(false, ("Failed 'HidD_SetNumInputBuffers' while initializing device."));
  94.357 +        ::CloseHandle(Device);
  94.358 +        Device = 0;
  94.359 +        return false;
  94.360 +    }
  94.361 +
  94.362 +
  94.363 +    // Create a manual-reset non-signaled event.
  94.364 +    ReadOverlapped.hEvent = ::CreateEvent(0, TRUE, FALSE, 0);
  94.365 +
  94.366 +    if (!ReadOverlapped.hEvent)
  94.367 +    {
  94.368 +        OVR_ASSERT_LOG(false, ("Failed to create event."));
  94.369 +        ::CloseHandle(Device);
  94.370 +        Device = 0;
  94.371 +        return false;
  94.372 +    }
  94.373 +
  94.374 +    if (!initInfo())
  94.375 +    {
  94.376 +        OVR_ASSERT_LOG(false, ("Failed to get HIDDevice info."));
  94.377 +
  94.378 +        ::CloseHandle(ReadOverlapped.hEvent);
  94.379 +        memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
  94.380 +
  94.381 +        ::CloseHandle(Device);
  94.382 +        Device = 0;
  94.383 +        return false;
  94.384 +    }
  94.385 +
  94.386 +    if (!initializeRead())
  94.387 +    {
  94.388 +        OVR_ASSERT_LOG(false, ("Failed to get intialize read for HIDDevice."));
  94.389 +
  94.390 +        ::CloseHandle(ReadOverlapped.hEvent);
  94.391 +        memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
  94.392 +
  94.393 +        ::CloseHandle(Device);
  94.394 +        Device = 0;
  94.395 +        return false;
  94.396 +    }
  94.397 +
  94.398 +    return true;
  94.399 +}
  94.400 +
  94.401 +void HIDDevice::HIDShutdown()
  94.402 +{   
  94.403 +
  94.404 +    HIDManager->Manager->pThread->RemoveTicksNotifier(this);
  94.405 +    HIDManager->Manager->pThread->RemoveMessageNotifier(this);
  94.406 +
  94.407 +    closeDevice();
  94.408 +    LogText("OVR::Win32::HIDDevice - Closed '%s'\n", DevDesc.Path.ToCStr());
  94.409 +}
  94.410 +
  94.411 +bool HIDDevice::initializeRead()
  94.412 +{
  94.413 +
  94.414 +    if (!ReadRequested)
  94.415 +    {        
  94.416 +        HIDManager->Manager->pThread->AddOverlappedEvent(this, ReadOverlapped.hEvent);
  94.417 +        ReadRequested = true;
  94.418 +    }
  94.419 +
  94.420 +    // Read resets the event...
  94.421 +    while(::ReadFile(Device, ReadBuffer, InputReportBufferLength, 0, &ReadOverlapped))
  94.422 +    {
  94.423 +        processReadResult();
  94.424 +    }
  94.425 +
  94.426 +    if (GetLastError() != ERROR_IO_PENDING)
  94.427 +    {
  94.428 +        // Some other error (such as unplugged).
  94.429 +        closeDeviceOnIOError();
  94.430 +        return false;
  94.431 +    }
  94.432 +
  94.433 +    return true;
  94.434 +}
  94.435 +
  94.436 +bool HIDDevice::processReadResult()
  94.437 +{
  94.438 +
  94.439 +    OVR_ASSERT(ReadRequested);
  94.440 +
  94.441 +    DWORD bytesRead = 0;
  94.442 +
  94.443 +    if (GetOverlappedResult(Device, &ReadOverlapped, &bytesRead, FALSE))
  94.444 +    {
  94.445 +        // We've got data.
  94.446 +        if (Handler)
  94.447 +        {
  94.448 +            Handler->OnInputReport(ReadBuffer, bytesRead);
  94.449 +        }
  94.450 +
  94.451 +        // TBD: Not needed?
  94.452 +        // Event should be reset by Read call...
  94.453 +        ReadOverlapped.Pointer = 0;
  94.454 +        ReadOverlapped.Internal = 0;
  94.455 +        ReadOverlapped.InternalHigh = 0;
  94.456 +        return true;
  94.457 +    }
  94.458 +    else
  94.459 +    {
  94.460 +        if (GetLastError() != ERROR_IO_PENDING)
  94.461 +        {
  94.462 +            closeDeviceOnIOError();
  94.463 +            return false;
  94.464 +        }
  94.465 +    }
  94.466 +
  94.467 +    return false;
  94.468 +}
  94.469 +
  94.470 +void HIDDevice::closeDevice()
  94.471 +{
  94.472 +    if (ReadRequested)
  94.473 +    {
  94.474 +        HIDManager->Manager->pThread->RemoveOverlappedEvent(this, ReadOverlapped.hEvent);
  94.475 +        ReadRequested = false;
  94.476 +        // Must call this to avoid Win32 assertion; CloseHandle is not enough.
  94.477 +        ::CancelIo(Device);
  94.478 +    }
  94.479 +
  94.480 +    ::CloseHandle(ReadOverlapped.hEvent);
  94.481 +    memset(&ReadOverlapped, 0, sizeof(OVERLAPPED));
  94.482 +
  94.483 +    ::CloseHandle(Device);
  94.484 +    Device = 0;
  94.485 +}
  94.486 +
  94.487 +void HIDDevice::closeDeviceOnIOError()
  94.488 +{
  94.489 +    LogText("OVR::Win32::HIDDevice - Lost connection to '%s'\n", DevDesc.Path.ToCStr());
  94.490 +    closeDevice();
  94.491 +}
  94.492 +
  94.493 +bool HIDDevice::SetFeatureReport(UByte* data, UInt32 length)
  94.494 +{
  94.495 +    if (!ReadRequested)
  94.496 +        return false;
  94.497 +
  94.498 +    return HIDManager->HidD_SetFeature(Device, data, (ULONG) length) != FALSE;
  94.499 +}
  94.500 +
  94.501 +bool HIDDevice::GetFeatureReport(UByte* data, UInt32 length)
  94.502 +{
  94.503 +    if (!ReadRequested)
  94.504 +        return false;
  94.505 +
  94.506 +	return HIDManager->HidD_GetFeature(Device, data, (ULONG) length) != FALSE;
  94.507 +}
  94.508 +
  94.509 +void HIDDevice::OnOverlappedEvent(HANDLE hevent)
  94.510 +{
  94.511 +    OVR_UNUSED(hevent);
  94.512 +    OVR_ASSERT(hevent == ReadOverlapped.hEvent);
  94.513 +
  94.514 +    if (processReadResult()) 
  94.515 +    {
  94.516 +        // Proceed to read again.
  94.517 +        initializeRead();
  94.518 +    }
  94.519 +}
  94.520 +
  94.521 +UInt64 HIDDevice::OnTicks(UInt64 ticksMks)
  94.522 +{
  94.523 +    if (Handler)
  94.524 +    {
  94.525 +        return Handler->OnTicks(ticksMks);
  94.526 +    }
  94.527 +
  94.528 +    return DeviceManagerThread::Notifier::OnTicks(ticksMks);
  94.529 +}
  94.530 +
  94.531 +bool HIDDevice::OnDeviceMessage(DeviceMessageType messageType, 
  94.532 +								const String& devicePath,
  94.533 +								bool* error)
  94.534 +{
  94.535 +
  94.536 +    // Is this the correct device?
  94.537 +    if (DevDesc.Path.CompareNoCase(devicePath) != 0)
  94.538 +    {
  94.539 +        return false;
  94.540 +    }
  94.541 +
  94.542 +    if (messageType == DeviceMessage_DeviceAdded && !Device)
  94.543 +    {
  94.544 +        // A closed device has been re-added. Try to reopen.
  94.545 +        if (!openDevice())
  94.546 +        {
  94.547 +            LogError("OVR::Win32::HIDDevice - Failed to reopen a device '%s' that was re-added.\n", devicePath.ToCStr());
  94.548 +			*error = true;
  94.549 +            return true;
  94.550 +        }
  94.551 +
  94.552 +        LogText("OVR::Win32::HIDDevice - Reopened device '%s'\n", devicePath.ToCStr());
  94.553 +    }
  94.554 +
  94.555 +    HIDHandler::HIDDeviceMessageType handlerMessageType = HIDHandler::HIDDeviceMessage_DeviceAdded;
  94.556 +    if (messageType == DeviceMessage_DeviceAdded)
  94.557 +    {
  94.558 +    }
  94.559 +    else if (messageType == DeviceMessage_DeviceRemoved)
  94.560 +    {
  94.561 +        handlerMessageType = HIDHandler::HIDDeviceMessage_DeviceRemoved;
  94.562 +    }
  94.563 +    else
  94.564 +    {
  94.565 +        OVR_ASSERT(0);		
  94.566 +    }
  94.567 +
  94.568 +    if (Handler)
  94.569 +    {
  94.570 +        Handler->OnDeviceMessage(handlerMessageType);
  94.571 +    }
  94.572 +
  94.573 +	*error = false;
  94.574 +    return true;
  94.575 +}
  94.576 +
  94.577 +HIDDeviceManager* HIDDeviceManager::CreateInternal(Win32::DeviceManager* devManager)
  94.578 +{
  94.579 +
  94.580 +    if (!System::IsInitialized())
  94.581 +    {
  94.582 +        // Use custom message, since Log is not yet installed.
  94.583 +        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
  94.584 +            LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
  94.585 +        return 0;
  94.586 +    }
  94.587 +
  94.588 +    Ptr<Win32::HIDDeviceManager> manager = *new Win32::HIDDeviceManager(devManager);
  94.589 +
  94.590 +    if (manager)
  94.591 +    {
  94.592 +        if (manager->Initialize())
  94.593 +        {
  94.594 +            manager->AddRef();
  94.595 +        }
  94.596 +        else
  94.597 +        {
  94.598 +            manager.Clear();
  94.599 +        }
  94.600 +    }
  94.601 +
  94.602 +    return manager.GetPtr();
  94.603 +}
  94.604 +
  94.605 +} // namespace Win32
  94.606 +
  94.607 +//-------------------------------------------------------------------------------------
  94.608 +// ***** Creation
  94.609 +
  94.610 +// Creates a new HIDDeviceManager and initializes OVR.
  94.611 +HIDDeviceManager* HIDDeviceManager::Create()
  94.612 +{
  94.613 +    OVR_ASSERT_LOG(false, ("Standalone mode not implemented yet."));
  94.614 +
  94.615 +    if (!System::IsInitialized())
  94.616 +    {
  94.617 +        // Use custom message, since Log is not yet installed.
  94.618 +        OVR_DEBUG_STATEMENT(Log::GetDefaultLog()->
  94.619 +            LogMessage(Log_Debug, "HIDDeviceManager::Create failed - OVR::System not initialized"); );
  94.620 +        return 0;
  94.621 +    }
  94.622 +
  94.623 +    Ptr<Win32::HIDDeviceManager> manager = *new Win32::HIDDeviceManager(NULL);
  94.624 +
  94.625 +    if (manager)
  94.626 +    {
  94.627 +        if (manager->Initialize())
  94.628 +        {
  94.629 +            manager->AddRef();
  94.630 +        }
  94.631 +        else
  94.632 +        {
  94.633 +            manager.Clear();
  94.634 +        }
  94.635 +    }
  94.636 +
  94.637 +    return manager.GetPtr();
  94.638 +}
  94.639 +
  94.640 +} // namespace OVR
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/libovr/Src/win32/OVR_Win32_HIDDevice.h	Sat Sep 14 16:14:59 2013 +0300
    95.3 @@ -0,0 +1,194 @@
    95.4 +/************************************************************************************
    95.5 +
    95.6 +Filename    :   OVR_Win32_HIDDevice.h
    95.7 +Content     :   Win32 HID device implementation.
    95.8 +Created     :   February 22, 2013
    95.9 +Authors     :   Lee Cooper
   95.10 +
   95.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   95.12 +
   95.13 +Use of this software is subject to the terms of the Oculus license
   95.14 +agreement provided at the time of installation or download, or which
   95.15 +otherwise accompanies this software in either electronic or hard copy form.
   95.16 +
   95.17 +*************************************************************************************/
   95.18 +
   95.19 +#ifndef OVR_Win32_HIDDevice_h
   95.20 +#define OVR_Win32_HIDDevice_h
   95.21 +
   95.22 +#include "OVR_HIDDevice.h"
   95.23 +#include "OVR_Win32_DeviceManager.h"
   95.24 +
   95.25 +#include <windows.h>
   95.26 +#include <setupapi.h>
   95.27 +
   95.28 +//-------------------------------------------------------------------------------------
   95.29 +// Define needed "hidsdi.h" functionality to avoid requiring DDK installation.
   95.30 +// #include "hidsdi.h"
   95.31 +
   95.32 +#ifndef _HIDSDI_H
   95.33 +#define _HIDSDI_H
   95.34 +#include <pshpack4.h>
   95.35 +
   95.36 +#define HIDP_STATUS_SUCCESS (0x11 << 16)
   95.37 +struct HIDP_PREPARSED_DATA;
   95.38 +
   95.39 +struct HIDD_ATTRIBUTES
   95.40 +{
   95.41 +    ULONG   Size; // = sizeof (struct _HIDD_ATTRIBUTES)
   95.42 +    USHORT  VendorID;
   95.43 +    USHORT  ProductID;
   95.44 +    USHORT  VersionNumber;
   95.45 +};
   95.46 +
   95.47 +struct HIDP_CAPS
   95.48 +{
   95.49 +    USHORT   Usage;
   95.50 +    USHORT   UsagePage;
   95.51 +    USHORT   InputReportByteLength;
   95.52 +    USHORT   OutputReportByteLength;
   95.53 +    USHORT   FeatureReportByteLength;
   95.54 +    USHORT   Reserved[17];
   95.55 +
   95.56 +    USHORT   NumberLinkCollectionNodes;
   95.57 +    USHORT   NumberInputButtonCaps;
   95.58 +    USHORT   NumberInputValueCaps;
   95.59 +    USHORT   NumberInputDataIndices;
   95.60 +    USHORT   NumberOutputButtonCaps;
   95.61 +    USHORT   NumberOutputValueCaps;
   95.62 +    USHORT   NumberOutputDataIndices;
   95.63 +    USHORT   NumberFeatureButtonCaps;
   95.64 +    USHORT   NumberFeatureValueCaps;
   95.65 +    USHORT   NumberFeatureDataIndices;
   95.66 +};
   95.67 +
   95.68 +#include <poppack.h>
   95.69 +#endif
   95.70 +
   95.71 +
   95.72 +namespace OVR { namespace Win32 { 
   95.73 +
   95.74 +class HIDDeviceManager;
   95.75 +class DeviceManager;
   95.76 +
   95.77 +//-------------------------------------------------------------------------------------
   95.78 +// ***** Win32 HIDDevice
   95.79 +
   95.80 +class HIDDevice : public OVR::HIDDevice, public DeviceManagerThread::Notifier
   95.81 +{
   95.82 +public:
   95.83 +
   95.84 +    HIDDevice(HIDDeviceManager* manager);
   95.85 +
   95.86 +    // This is a minimal constructor used during enumeration for us to pass
   95.87 +    // a HIDDevice to the visit function (so that it can query feature reports). 
   95.88 +    HIDDevice(HIDDeviceManager* manager, HANDLE device);
   95.89 +
   95.90 +    ~HIDDevice();
   95.91 +
   95.92 +    bool HIDInitialize(const String& path);
   95.93 +    void HIDShutdown();
   95.94 +
   95.95 +    // OVR::HIDDevice
   95.96 +	bool SetFeatureReport(UByte* data, UInt32 length);
   95.97 +	bool GetFeatureReport(UByte* data, UInt32 length);
   95.98 +    
   95.99 +
  95.100 +    // DeviceManagerThread::Notifier
  95.101 +    void OnOverlappedEvent(HANDLE hevent);
  95.102 +    UInt64 OnTicks(UInt64 ticksMks);
  95.103 +    bool OnDeviceMessage(DeviceMessageType messageType, const String& devicePath, bool* error);
  95.104 +
  95.105 +private:
  95.106 +    bool openDevice();
  95.107 +    bool initInfo();
  95.108 +    bool initializeRead();
  95.109 +    bool processReadResult();
  95.110 +    void closeDevice();
  95.111 +    void closeDeviceOnIOError();
  95.112 +
  95.113 +    bool                inMinimalMode;
  95.114 +    HIDDeviceManager*   HIDManager;
  95.115 +	HANDLE              Device;
  95.116 +    HIDDeviceDesc       DevDesc; 
  95.117 +
  95.118 +    OVERLAPPED          ReadOverlapped;
  95.119 +    bool                ReadRequested;
  95.120 +
  95.121 +    enum { ReadBufferSize = 96 };
  95.122 +    UByte               ReadBuffer[ReadBufferSize];
  95.123 +
  95.124 +    UInt16              InputReportBufferLength;
  95.125 +    UInt16              OutputReportBufferLength;
  95.126 +    UInt16              FeatureReportBufferLength;
  95.127 +};
  95.128 +
  95.129 +//-------------------------------------------------------------------------------------
  95.130 +// ***** Win32 HIDDeviceManager
  95.131 +
  95.132 +class HIDDeviceManager : public OVR::HIDDeviceManager
  95.133 +{
  95.134 +	friend class HIDDevice;
  95.135 +public:
  95.136 +
  95.137 +	HIDDeviceManager(DeviceManager* manager);
  95.138 +    virtual ~HIDDeviceManager();
  95.139 +
  95.140 +    virtual bool Initialize();
  95.141 +    virtual void Shutdown();
  95.142 +
  95.143 +    virtual bool Enumerate(HIDEnumerateVisitor* enumVisitor);
  95.144 +    virtual OVR::HIDDevice* Open(const String& path);
  95.145 +
  95.146 +    // Fills HIDDeviceDesc by using the path.
  95.147 +    // Returns 'true' if successful, 'false' otherwise.
  95.148 +    bool GetHIDDeviceDesc(const String& path, HIDDeviceDesc* pdevDesc) const;
  95.149 +
  95.150 +    GUID GetHIDGuid() { return HidGuid; }
  95.151 +    
  95.152 +    static HIDDeviceManager* CreateInternal(DeviceManager* manager);
  95.153 +
  95.154 +private:
  95.155 +
  95.156 +    DeviceManager* Manager;     // Back pointer can just be a raw pointer.
  95.157 +
  95.158 +    HMODULE hHidLib;
  95.159 +    GUID    HidGuid;
  95.160 +
  95.161 +    // Macros to declare and resolve needed functions from library.
  95.162 +#define OVR_DECLARE_HIDFUNC(func, rettype, args)   \
  95.163 +typedef rettype (__stdcall *PFn_##func) args;  \
  95.164 +PFn_##func      func;
  95.165 +#define OVR_RESOLVE_HIDFUNC(func) \
  95.166 +func = (PFn_##func)::GetProcAddress(hHidLib, #func)
  95.167 +
  95.168 +    OVR_DECLARE_HIDFUNC(HidD_GetHidGuid,            void,    (GUID *hidGuid));
  95.169 +    OVR_DECLARE_HIDFUNC(HidD_SetNumInputBuffers,    BOOLEAN, (HANDLE hidDev, ULONG numberBuffers));
  95.170 +    OVR_DECLARE_HIDFUNC(HidD_GetFeature,            BOOLEAN, (HANDLE hidDev, PVOID buffer, ULONG bufferLength));
  95.171 +    OVR_DECLARE_HIDFUNC(HidD_SetFeature,            BOOLEAN, (HANDLE hidDev, PVOID buffer, ULONG bufferLength));
  95.172 +    OVR_DECLARE_HIDFUNC(HidD_GetAttributes,         BOOLEAN, (HANDLE hidDev, HIDD_ATTRIBUTES *attributes));
  95.173 +    OVR_DECLARE_HIDFUNC(HidD_GetManufacturerString, BOOLEAN, (HANDLE hidDev, PVOID buffer, ULONG bufferLength));
  95.174 +    OVR_DECLARE_HIDFUNC(HidD_GetProductString,      BOOLEAN, (HANDLE hidDev, PVOID buffer, ULONG bufferLength));
  95.175 +    OVR_DECLARE_HIDFUNC(HidD_GetSerialNumberString, BOOLEAN, (HANDLE hidDev, PVOID buffer, ULONG bufferLength));
  95.176 +    OVR_DECLARE_HIDFUNC(HidD_GetPreparsedData,      BOOLEAN, (HANDLE hidDev, HIDP_PREPARSED_DATA **preparsedData));
  95.177 +    OVR_DECLARE_HIDFUNC(HidD_FreePreparsedData,     BOOLEAN, (HIDP_PREPARSED_DATA *preparsedData));
  95.178 +    OVR_DECLARE_HIDFUNC(HidP_GetCaps,               NTSTATUS,(HIDP_PREPARSED_DATA *preparsedData, HIDP_CAPS* caps));
  95.179 +
  95.180 +    HANDLE CreateHIDFile(const char* path, bool exclusiveAccess = true) const
  95.181 +    {
  95.182 +        return ::CreateFileA(path, GENERIC_WRITE|GENERIC_READ,
  95.183 +            (!exclusiveAccess) ? (FILE_SHARE_READ|FILE_SHARE_WRITE) : 0x0, 
  95.184 +            NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
  95.185 +    }
  95.186 +
  95.187 +    // Helper functions to fill in HIDDeviceDesc from open device handle.
  95.188 +    bool initVendorProductVersion(HANDLE hidDev, HIDDeviceDesc* desc) const;
  95.189 +    bool initUsage(HANDLE hidDev, HIDDeviceDesc* desc) const;
  95.190 +    void initStrings(HANDLE hidDev, HIDDeviceDesc* desc) const;
  95.191 +
  95.192 +    bool getFullDesc(HANDLE hidDev, HIDDeviceDesc* desc) const;
  95.193 +};
  95.194 +
  95.195 +}} // namespace OVR::Win32
  95.196 +
  95.197 +#endif // OVR_Win32_HIDDevice_h
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/libovr/Src/win32/OVR_Win32_HMDDevice.cpp	Sat Sep 14 16:14:59 2013 +0300
    96.3 @@ -0,0 +1,498 @@
    96.4 +/************************************************************************************
    96.5 +
    96.6 +Filename    :   OVR_Win32_HMDDevice.cpp
    96.7 +Content     :   Win32 Interface to HMD - detects HMD display
    96.8 +Created     :   September 21, 2012
    96.9 +Authors     :   Michael Antonov
   96.10 +
   96.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   96.12 +
   96.13 +Use of this software is subject to the terms of the Oculus license
   96.14 +agreement provided at the time of installation or download, or which
   96.15 +otherwise accompanies this software in either electronic or hard copy form.
   96.16 +
   96.17 +*************************************************************************************/
   96.18 +
   96.19 +#include "OVR_Win32_HMDDevice.h"
   96.20 +
   96.21 +#include "OVR_Win32_DeviceManager.h"
   96.22 +
   96.23 +#include <tchar.h>
   96.24 +
   96.25 +namespace OVR { namespace Win32 {
   96.26 +
   96.27 +//-------------------------------------------------------------------------------------
   96.28 +
   96.29 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(DeviceFactory* factory, 
   96.30 +                                         const String& deviceId, const String& displayDeviceName)
   96.31 +        : DeviceCreateDesc(factory, Device_HMD),
   96.32 +          DeviceId(deviceId), DisplayDeviceName(displayDeviceName),
   96.33 +          DesktopX(0), DesktopY(0), Contents(0),
   96.34 +          HResolution(0), VResolution(0), HScreenSize(0), VScreenSize(0)
   96.35 +{
   96.36 +}
   96.37 +HMDDeviceCreateDesc::HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other)
   96.38 +        : DeviceCreateDesc(other.pFactory, Device_HMD),
   96.39 +          DeviceId(other.DeviceId), DisplayDeviceName(other.DisplayDeviceName),
   96.40 +          DesktopX(other.DesktopX), DesktopY(other.DesktopY), Contents(other.Contents),
   96.41 +          HResolution(other.HResolution), VResolution(other.VResolution),
   96.42 +          HScreenSize(other.HScreenSize), VScreenSize(other.VScreenSize)
   96.43 +{
   96.44 +}
   96.45 +
   96.46 +HMDDeviceCreateDesc::MatchResult HMDDeviceCreateDesc::MatchDevice(const DeviceCreateDesc& other,
   96.47 +                                                                  DeviceCreateDesc** pcandidate) const
   96.48 +{
   96.49 +    if ((other.Type != Device_HMD) || (other.pFactory != pFactory))
   96.50 +        return Match_None;
   96.51 +
   96.52 +    // There are several reasons we can come in here:
   96.53 +    //   a) Matching this HMD Monitor created desc to OTHER HMD Monitor desc
   96.54 +    //          - Require exact device DeviceId/DeviceName match
   96.55 +    //   b) Matching SensorDisplayInfo created desc to OTHER HMD Monitor desc
   96.56 +    //          - This DeviceId is empty; becomes candidate
   96.57 +    //   c) Matching this HMD Monitor created desc to SensorDisplayInfo desc
   96.58 +    //          - This other.DeviceId is empty; becomes candidate
   96.59 +
   96.60 +    const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
   96.61 +
   96.62 +    if ((DeviceId == s2.DeviceId) &&
   96.63 +        (DisplayDeviceName == s2.DisplayDeviceName))
   96.64 +    {
   96.65 +        // Non-null DeviceId may match while size is different if screen size was overwritten
   96.66 +        // by SensorDisplayInfo in prior iteration.
   96.67 +        if (!DeviceId.IsEmpty() ||
   96.68 +             ((HScreenSize == s2.HScreenSize) &&
   96.69 +              (VScreenSize == s2.VScreenSize)) )
   96.70 +        {            
   96.71 +            *pcandidate = 0;
   96.72 +            return Match_Found;
   96.73 +        }
   96.74 +    }
   96.75 +
   96.76 +
   96.77 +    // DisplayInfo takes precedence, although we try to match it first.
   96.78 +    if ((HResolution == s2.HResolution) &&
   96.79 +        (VResolution == s2.VResolution) &&
   96.80 +        (HScreenSize == s2.HScreenSize) &&
   96.81 +        (VScreenSize == s2.VScreenSize))
   96.82 +    {
   96.83 +        if (DeviceId.IsEmpty() && !s2.DeviceId.IsEmpty())
   96.84 +        {
   96.85 +            *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
   96.86 +            return Match_Candidate;
   96.87 +        }
   96.88 +
   96.89 +        *pcandidate = 0;
   96.90 +        return Match_Found;
   96.91 +    }
   96.92 +    
   96.93 +    // SensorDisplayInfo may override resolution settings, so store as candidate.
   96.94 +    if (s2.DeviceId.IsEmpty())
   96.95 +    {        
   96.96 +        *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
   96.97 +        return Match_Candidate;
   96.98 +    }
   96.99 +    // OTHER HMD Monitor desc may initialize DeviceName/Id
  96.100 +    else if (DeviceId.IsEmpty())
  96.101 +    {
  96.102 +        *pcandidate = const_cast<DeviceCreateDesc*>((const DeviceCreateDesc*)this);
  96.103 +        return Match_Candidate;
  96.104 +    }
  96.105 +    
  96.106 +    return Match_None;
  96.107 +}
  96.108 +
  96.109 +
  96.110 +bool HMDDeviceCreateDesc::UpdateMatchedCandidate(const DeviceCreateDesc& other, 
  96.111 +                                                 bool* newDeviceFlag)
  96.112 +{
  96.113 +    // This candidate was the the "best fit" to apply sensor DisplayInfo to.
  96.114 +    OVR_ASSERT(other.Type == Device_HMD);
  96.115 +    
  96.116 +    const HMDDeviceCreateDesc& s2 = (const HMDDeviceCreateDesc&) other;
  96.117 +
  96.118 +    // Force screen size on resolution from SensorDisplayInfo.
  96.119 +    // We do this because USB detection is more reliable as compared to HDMI EDID,
  96.120 +    // which may be corrupted by splitter reporting wrong monitor 
  96.121 +    if (s2.DeviceId.IsEmpty())
  96.122 +    {
  96.123 +        HScreenSize = s2.HScreenSize;
  96.124 +        VScreenSize = s2.VScreenSize;
  96.125 +        Contents |= Contents_Screen;
  96.126 +
  96.127 +        if (s2.Contents & HMDDeviceCreateDesc::Contents_Distortion)
  96.128 +        {
  96.129 +            memcpy(DistortionK, s2.DistortionK, sizeof(float)*4);
  96.130 +            Contents |= Contents_Distortion;
  96.131 +        }
  96.132 +        DeviceId          = s2.DeviceId;
  96.133 +        DisplayDeviceName = s2.DisplayDeviceName;
  96.134 +        DesktopX          = s2.DesktopX;
  96.135 +        DesktopY          = s2.DesktopY;
  96.136 +        if (newDeviceFlag) *newDeviceFlag = true;
  96.137 +    }
  96.138 +    else if (DeviceId.IsEmpty())
  96.139 +    {
  96.140 +        DeviceId          = s2.DeviceId;
  96.141 +        DisplayDeviceName = s2.DisplayDeviceName;
  96.142 +        DesktopX          = s2.DesktopX;
  96.143 +        DesktopY          = s2.DesktopY;
  96.144 +
  96.145 +		// ScreenSize and Resolution are NOT assigned here, since they may have
  96.146 +		// come from a sensor DisplayInfo (which has precedence over HDMI).
  96.147 +
  96.148 +        if (newDeviceFlag) *newDeviceFlag = true;
  96.149 +    }
  96.150 +    else
  96.151 +    {
  96.152 +        if (newDeviceFlag) *newDeviceFlag = false;
  96.153 +    }
  96.154 +
  96.155 +    return true;
  96.156 +}
  96.157 +
  96.158 +bool HMDDeviceCreateDesc::MatchDevice(const String& path)
  96.159 +{
  96.160 +    return DeviceId.CompareNoCase(path) == 0;
  96.161 +}
  96.162 +    
  96.163 +//-------------------------------------------------------------------------------------
  96.164 +
  96.165 +
  96.166 +const wchar_t* FormatDisplayStateFlags(wchar_t* buff, int length, DWORD flags)
  96.167 +{
  96.168 +    buff[0] = 0;
  96.169 +    if (flags & DISPLAY_DEVICE_ACTIVE)
  96.170 +        wcscat_s(buff, length, L"Active ");
  96.171 +    if (flags & DISPLAY_DEVICE_MIRRORING_DRIVER)
  96.172 +        wcscat_s(buff, length, L"Mirroring_Driver ");
  96.173 +    if (flags & DISPLAY_DEVICE_MODESPRUNED)
  96.174 +        wcscat_s(buff, length, L"ModesPruned ");
  96.175 +    if (flags & DISPLAY_DEVICE_PRIMARY_DEVICE)
  96.176 +        wcscat_s(buff, length, L"Primary ");
  96.177 +    if (flags & DISPLAY_DEVICE_REMOVABLE)
  96.178 +        wcscat_s(buff, length, L"Removable ");
  96.179 +    if (flags & DISPLAY_DEVICE_VGA_COMPATIBLE)
  96.180 +        wcscat_s(buff, length, L"VGA_Compatible ");
  96.181 +    return buff;
  96.182 +}
  96.183 +
  96.184 +
  96.185 +//-------------------------------------------------------------------------------------
  96.186 +// Callback for monitor enumeration to store all the monitor handles
  96.187 +
  96.188 +// Used to capture all the active monitor handles
  96.189 +struct MonitorSet
  96.190 +{
  96.191 +    enum { MaxMonitors = 8 };
  96.192 +    HMONITOR Monitors[MaxMonitors];
  96.193 +    int      MonitorCount;
  96.194 +};
  96.195 +
  96.196 +BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
  96.197 +{
  96.198 +    MonitorSet* monitorSet = (MonitorSet*)dwData;
  96.199 +    if (monitorSet->MonitorCount > MonitorSet::MaxMonitors)
  96.200 +        return FALSE;
  96.201 +
  96.202 +    monitorSet->Monitors[monitorSet->MonitorCount] = hMonitor;
  96.203 +    monitorSet->MonitorCount++;
  96.204 +    return TRUE;
  96.205 +};
  96.206 +
  96.207 +//-------------------------------------------------------------------------------------
  96.208 +// ***** HMDDeviceFactory
  96.209 +
  96.210 +HMDDeviceFactory HMDDeviceFactory::Instance;
  96.211 +
  96.212 +void HMDDeviceFactory::EnumerateDevices(EnumerateVisitor& visitor)
  96.213 +{
  96.214 +    MonitorSet monitors;
  96.215 +    monitors.MonitorCount = 0;
  96.216 +    // Get all the monitor handles 
  96.217 +    EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors);
  96.218 +
  96.219 +    bool foundHMD = false;
  96.220 +    
  96.221 +   // DeviceManager* manager = getManager();
  96.222 +    DISPLAY_DEVICE dd, ddm;
  96.223 +    UINT           i, j;    
  96.224 +
  96.225 +    for (i = 0; 
  96.226 +        (ZeroMemory(&dd, sizeof(dd)), dd.cb = sizeof(dd),
  96.227 +        EnumDisplayDevices(0, i, &dd, 0)) != 0;  i++)
  96.228 +    {
  96.229 +        
  96.230 +        /*
  96.231 +        wchar_t buff[500], flagsBuff[200];
  96.232 +        
  96.233 +        swprintf_s(buff, 500, L"\nDEV: \"%s\" \"%s\" 0x%08x=%s\n     \"%s\" \"%s\"\n",
  96.234 +            dd.DeviceName, dd.DeviceString,
  96.235 +            dd.StateFlags, FormatDisplayStateFlags(flagsBuff, 200, dd.StateFlags),
  96.236 +            dd.DeviceID, dd.DeviceKey);
  96.237 +        ::OutputDebugString(buff);
  96.238 +        */
  96.239 +
  96.240 +        for (j = 0; 
  96.241 +            (ZeroMemory(&ddm, sizeof(ddm)), ddm.cb = sizeof(ddm),
  96.242 +            EnumDisplayDevices(dd.DeviceName, j, &ddm, 0)) != 0;  j++)
  96.243 +        {
  96.244 +            /*
  96.245 +            wchar_t mbuff[500];
  96.246 +            swprintf_s(mbuff, 500, L"MON: \"%s\" \"%s\" 0x%08x=%s\n     \"%s\" \"%s\"\n",
  96.247 +                ddm.DeviceName, ddm.DeviceString,
  96.248 +                ddm.StateFlags, FormatDisplayStateFlags(flagsBuff, 200, ddm.StateFlags),
  96.249 +                ddm.DeviceID, ddm.DeviceKey);
  96.250 +            ::OutputDebugString(mbuff);
  96.251 +            */
  96.252 +
  96.253 +            // Our monitor hardware has string "RTD2205" in it
  96.254 +            // Nate's device "CVT0003"
  96.255 +            if (wcsstr(ddm.DeviceID, L"RTD2205") || 
  96.256 +                wcsstr(ddm.DeviceID, L"CVT0003") || 
  96.257 +                wcsstr(ddm.DeviceID, L"MST0030") ||
  96.258 +                wcsstr(ddm.DeviceID, L"OVR00") ) // Part of Oculus EDID.
  96.259 +            {
  96.260 +                String deviceId(ddm.DeviceID);
  96.261 +                String displayDeviceName(ddm.DeviceName);
  96.262 +
  96.263 +                // The default monitor coordinates
  96.264 +                int mx      = 0;
  96.265 +                int my      = 0;
  96.266 +                int mwidth  = 1280;
  96.267 +                int mheight = 800;
  96.268 +
  96.269 +                // Find the matching MONITORINFOEX for this device so we can get the 
  96.270 +                // screen coordinates
  96.271 +                MONITORINFOEX info;
  96.272 +                for (int m=0; m < monitors.MonitorCount; m++)
  96.273 +                {
  96.274 +                    info.cbSize = sizeof(MONITORINFOEX);
  96.275 +                    GetMonitorInfo(monitors.Monitors[m], &info);
  96.276 +                    if (_tcsstr(ddm.DeviceName, info.szDevice) == ddm.DeviceName)
  96.277 +                    {   // If the device name starts with the monitor name
  96.278 +                        // then we found the matching DISPLAY_DEVICE and MONITORINFO
  96.279 +                        // so we can gather the monitor coordinates
  96.280 +                        mx = info.rcMonitor.left;
  96.281 +                        my = info.rcMonitor.top;
  96.282 +                        //mwidth = info.rcMonitor.right - info.rcMonitor.left;
  96.283 +                        //mheight = info.rcMonitor.bottom - info.rcMonitor.top;
  96.284 +                        break;
  96.285 +                    }
  96.286 +                }
  96.287 +
  96.288 +                HMDDeviceCreateDesc hmdCreateDesc(this, deviceId, displayDeviceName);
  96.289 +				
  96.290 +				if (wcsstr(ddm.DeviceID, L"OVR0002"))
  96.291 +				{
  96.292 +					hmdCreateDesc.SetScreenParameters(mx, my, 1920, 1080, 0.12096f, 0.06804f);
  96.293 +				}
  96.294 +				else
  96.295 +				{
  96.296 +					if (hmdCreateDesc.Is7Inch())
  96.297 +					{
  96.298 +						// Physical dimension of SLA screen.
  96.299 +						hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.14976f, 0.0936f);
  96.300 +					}
  96.301 +					else
  96.302 +					{
  96.303 +						hmdCreateDesc.SetScreenParameters(mx, my, mwidth, mheight, 0.12096f, 0.0756f);
  96.304 +					}
  96.305 +				}
  96.306 +
  96.307 +
  96.308 +                OVR_DEBUG_LOG_TEXT(("DeviceManager - HMD Found %s - %s\n",
  96.309 +                                    deviceId.ToCStr(), displayDeviceName.ToCStr()));
  96.310 +
  96.311 +                // Notify caller about detected device. This will call EnumerateAddDevice
  96.312 +                // if the this is the first time device was detected.
  96.313 +                visitor.Visit(hmdCreateDesc);
  96.314 +                foundHMD = true;
  96.315 +                break;
  96.316 +            }
  96.317 +        }
  96.318 +    }
  96.319 +
  96.320 +    // Real HMD device is not found; however, we still may have a 'fake' HMD
  96.321 +    // device created via SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo.
  96.322 +    // Need to find it and set 'Enumerated' to true to avoid Removal notification.
  96.323 +    if (!foundHMD)
  96.324 +    {
  96.325 +        Ptr<DeviceCreateDesc> hmdDevDesc = getManager()->FindDevice("", Device_HMD);
  96.326 +        if (hmdDevDesc)
  96.327 +            hmdDevDesc->Enumerated = true;
  96.328 +    }
  96.329 +}
  96.330 +
  96.331 +DeviceBase* HMDDeviceCreateDesc::NewDeviceInstance()
  96.332 +{
  96.333 +    return new HMDDevice(this);
  96.334 +}
  96.335 +
  96.336 +bool HMDDeviceCreateDesc::Is7Inch() const
  96.337 +{
  96.338 +    return (strstr(DeviceId.ToCStr(), "OVR0001") != 0) || (Contents & Contents_7Inch);
  96.339 +}
  96.340 +
  96.341 +Profile* HMDDeviceCreateDesc::GetProfileAddRef() const
  96.342 +{
  96.343 +    // Create device may override profile name, so get it from there is possible.
  96.344 +    ProfileManager* profileManager = GetManagerImpl()->GetProfileManager();
  96.345 +    ProfileType     profileType    = GetProfileType();
  96.346 +    const char *    profileName    = pDevice ?
  96.347 +                        ((HMDDevice*)pDevice)->GetProfileName() :
  96.348 +                        profileManager->GetDefaultProfileName(profileType);
  96.349 +    
  96.350 +    return profileName ? 
  96.351 +        profileManager->LoadProfile(profileType, profileName) :
  96.352 +        profileManager->GetDeviceDefaultProfile(profileType);
  96.353 +}
  96.354 +
  96.355 +
  96.356 +bool HMDDeviceCreateDesc::GetDeviceInfo(DeviceInfo* info) const
  96.357 +{
  96.358 +    if ((info->InfoClassType != Device_HMD) &&
  96.359 +        (info->InfoClassType != Device_None))
  96.360 +        return false;
  96.361 +
  96.362 +    bool is7Inch = Is7Inch();
  96.363 +
  96.364 +    OVR_strcpy(info->ProductName,  DeviceInfo::MaxNameLength,
  96.365 +               is7Inch ? "Oculus Rift DK1" :
  96.366 +			   ((HResolution >= 1920) ? "Oculus Rift DK HD" : "Oculus Rift DK1-Prototype") );
  96.367 +    OVR_strcpy(info->Manufacturer, DeviceInfo::MaxNameLength, "Oculus VR");
  96.368 +    info->Type    = Device_HMD;
  96.369 +    info->Version = 0;
  96.370 +
  96.371 +    // Display detection.
  96.372 +    if (info->InfoClassType == Device_HMD)
  96.373 +    {
  96.374 +        HMDInfo* hmdInfo = static_cast<HMDInfo*>(info);
  96.375 +
  96.376 +        hmdInfo->DesktopX               = DesktopX;
  96.377 +        hmdInfo->DesktopY               = DesktopY;
  96.378 +        hmdInfo->HResolution            = HResolution;
  96.379 +        hmdInfo->VResolution            = VResolution;
  96.380 +        hmdInfo->HScreenSize            = HScreenSize;
  96.381 +        hmdInfo->VScreenSize            = VScreenSize;
  96.382 +        hmdInfo->VScreenCenter          = VScreenSize * 0.5f;
  96.383 +        hmdInfo->InterpupillaryDistance = 0.064f;  // Default IPD; should be configurable.
  96.384 +        hmdInfo->LensSeparationDistance = 0.0635f;
  96.385 +
  96.386 +        // Obtain IPD from profile.
  96.387 +        Ptr<Profile> profile = *GetProfileAddRef();
  96.388 +
  96.389 +        if (profile)
  96.390 +        {
  96.391 +            hmdInfo->InterpupillaryDistance = profile->GetIPD();
  96.392 +            // TBD: Switch on EyeCup type.
  96.393 +        }
  96.394 +
  96.395 +        if (Contents & Contents_Distortion)
  96.396 +        {
  96.397 +            memcpy(hmdInfo->DistortionK, DistortionK, sizeof(float)*4);
  96.398 +        }
  96.399 +        else
  96.400 +        {						
  96.401 +			if (is7Inch)
  96.402 +            {
  96.403 +                // 7" screen.
  96.404 +                hmdInfo->DistortionK[0]      = 1.0f;
  96.405 +                hmdInfo->DistortionK[1]      = 0.22f;
  96.406 +                hmdInfo->DistortionK[2]      = 0.24f;
  96.407 +                hmdInfo->EyeToScreenDistance = 0.041f;
  96.408 +            }
  96.409 +            else
  96.410 +            {
  96.411 +                hmdInfo->DistortionK[0]      = 1.0f;
  96.412 +                hmdInfo->DistortionK[1]      = 0.18f;
  96.413 +                hmdInfo->DistortionK[2]      = 0.115f;
  96.414 +
  96.415 +				if (HResolution == 1920)
  96.416 +					hmdInfo->EyeToScreenDistance = 0.040f;
  96.417 +				else
  96.418 +					hmdInfo->EyeToScreenDistance = 0.0387f;
  96.419 +            }
  96.420 +
  96.421 +			hmdInfo->ChromaAbCorrection[0] = 0.996f;
  96.422 +			hmdInfo->ChromaAbCorrection[1] = -0.004f;
  96.423 +			hmdInfo->ChromaAbCorrection[2] = 1.014f;
  96.424 +			hmdInfo->ChromaAbCorrection[3] = 0.0f;
  96.425 +        }
  96.426 +
  96.427 +        OVR_strcpy(hmdInfo->DisplayDeviceName, sizeof(hmdInfo->DisplayDeviceName),
  96.428 +                   DisplayDeviceName.ToCStr());
  96.429 +    }
  96.430 +
  96.431 +    return true;
  96.432 +}
  96.433 +
  96.434 +//-------------------------------------------------------------------------------------
  96.435 +// ***** HMDDevice
  96.436 +
  96.437 +HMDDevice::HMDDevice(HMDDeviceCreateDesc* createDesc)
  96.438 +    : OVR::DeviceImpl<OVR::HMDDevice>(createDesc, 0)
  96.439 +{
  96.440 +}
  96.441 +HMDDevice::~HMDDevice()
  96.442 +{
  96.443 +}
  96.444 +
  96.445 +bool HMDDevice::Initialize(DeviceBase* parent)
  96.446 +{
  96.447 +    pParent = parent;
  96.448 +
  96.449 +    // Initialize user profile to default for device.
  96.450 +    ProfileManager* profileManager = GetManager()->GetProfileManager();    
  96.451 +    ProfileName = profileManager->GetDefaultProfileName(getDesc()->GetProfileType());
  96.452 +
  96.453 +    return true;
  96.454 +}
  96.455 +void HMDDevice::Shutdown()
  96.456 +{
  96.457 +    ProfileName.Clear();
  96.458 +    pCachedProfile.Clear();
  96.459 +    pParent.Clear();
  96.460 +}
  96.461 +
  96.462 +Profile* HMDDevice::GetProfile() const
  96.463 +{    
  96.464 +    if (!pCachedProfile)
  96.465 +        pCachedProfile = *getDesc()->GetProfileAddRef();
  96.466 +    return pCachedProfile.GetPtr();
  96.467 +}
  96.468 +
  96.469 +const char* HMDDevice::GetProfileName() const
  96.470 +{
  96.471 +    return ProfileName.ToCStr();
  96.472 +}
  96.473 +
  96.474 +bool HMDDevice::SetProfileName(const char* name)
  96.475 +{
  96.476 +    pCachedProfile.Clear();
  96.477 +    if (!name)
  96.478 +    {
  96.479 +        ProfileName.Clear();
  96.480 +        return 0;
  96.481 +    }
  96.482 +    if (GetManager()->GetProfileManager()->HasProfile(getDesc()->GetProfileType(), name))
  96.483 +    {
  96.484 +        ProfileName = name;
  96.485 +        return true;
  96.486 +    }
  96.487 +    return false;
  96.488 +}
  96.489 +
  96.490 +OVR::SensorDevice* HMDDevice::GetSensor()
  96.491 +{
  96.492 +    // Just return first sensor found since we have no way to match it yet.
  96.493 +    OVR::SensorDevice* sensor = GetManager()->EnumerateDevices<SensorDevice>().CreateDevice();
  96.494 +    if (sensor)
  96.495 +        sensor->SetCoordinateFrame(SensorDevice::Coord_HMD);
  96.496 +    return sensor;
  96.497 +}
  96.498 +
  96.499 +}} // namespace OVR::Win32
  96.500 +
  96.501 +
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/libovr/Src/win32/OVR_Win32_HMDDevice.h	Sat Sep 14 16:14:59 2013 +0300
    97.3 @@ -0,0 +1,157 @@
    97.4 +/************************************************************************************
    97.5 +
    97.6 +Filename    :   OVR_Win32_HMDDevice.h
    97.7 +Content     :   Win32 HMDDevice implementation
    97.8 +Created     :   September 21, 2012
    97.9 +Authors     :   Michael Antonov
   97.10 +
   97.11 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   97.12 +
   97.13 +Use of this software is subject to the terms of the Oculus license
   97.14 +agreement provided at the time of installation or download, or which
   97.15 +otherwise accompanies this software in either electronic or hard copy form.
   97.16 +
   97.17 +*************************************************************************************/
   97.18 +
   97.19 +#ifndef OVR_Win32_HMDDevice_h
   97.20 +#define OVR_Win32_HMDDevice_h
   97.21 +
   97.22 +#include "OVR_Win32_DeviceManager.h"
   97.23 +#include "OVR_Profile.h"
   97.24 +
   97.25 +namespace OVR { namespace Win32 {
   97.26 +
   97.27 +class HMDDevice;
   97.28 +
   97.29 +
   97.30 +//-------------------------------------------------------------------------------------
   97.31 +
   97.32 +// HMDDeviceFactory enumerates attached Oculus HMD devices.
   97.33 +//
   97.34 +// This is currently done by matching monitor device strings.
   97.35 +
   97.36 +class HMDDeviceFactory : public DeviceFactory
   97.37 +{
   97.38 +public:
   97.39 +    static HMDDeviceFactory Instance;
   97.40 +
   97.41 +    // Enumerates devices, creating and destroying relevant objects in manager.
   97.42 +    virtual void EnumerateDevices(EnumerateVisitor& visitor);
   97.43 +
   97.44 +protected:
   97.45 +    DeviceManager* getManager() const { return (DeviceManager*) pManager; }
   97.46 +};
   97.47 +
   97.48 +
   97.49 +class HMDDeviceCreateDesc : public DeviceCreateDesc
   97.50 +{
   97.51 +    friend class HMDDevice;
   97.52 +
   97.53 +protected:
   97.54 +    enum
   97.55 +    {
   97.56 +        Contents_Screen     = 1,
   97.57 +        Contents_Distortion = 2,
   97.58 +        Contents_7Inch      = 4,
   97.59 +    };
   97.60 +    String      DeviceId;
   97.61 +    String      DisplayDeviceName;
   97.62 +    int         DesktopX, DesktopY;
   97.63 +    unsigned    Contents;
   97.64 +    unsigned    HResolution, VResolution;
   97.65 +    float       HScreenSize, VScreenSize;
   97.66 +    float       DistortionK[4];
   97.67 +
   97.68 +public:
   97.69 +    HMDDeviceCreateDesc(DeviceFactory* factory, 
   97.70 +                        const String& deviceId, const String& displayDeviceName);
   97.71 +    HMDDeviceCreateDesc(const HMDDeviceCreateDesc& other);
   97.72 +
   97.73 +    virtual DeviceCreateDesc* Clone() const
   97.74 +    {
   97.75 +        return new HMDDeviceCreateDesc(*this);
   97.76 +    }
   97.77 +
   97.78 +    virtual DeviceBase* NewDeviceInstance();
   97.79 +
   97.80 +    virtual MatchResult MatchDevice(const DeviceCreateDesc& other,
   97.81 +                                    DeviceCreateDesc**) const;
   97.82 +
   97.83 +    // Matches device by path.
   97.84 +    virtual bool        MatchDevice(const String& path);
   97.85 +
   97.86 +    virtual bool        UpdateMatchedCandidate(const DeviceCreateDesc&, bool* newDeviceFlag = NULL);
   97.87 +
   97.88 +    virtual bool GetDeviceInfo(DeviceInfo* info) const;
   97.89 +
   97.90 +    // Requests the currently used default profile. This profile affects the
   97.91 +    // settings reported by HMDInfo. 
   97.92 +    Profile* GetProfileAddRef() const;
   97.93 +
   97.94 +    ProfileType GetProfileType() const
   97.95 +    {
   97.96 +        return (HResolution >= 1920) ? Profile_RiftDKHD : Profile_RiftDK1;
   97.97 +    }
   97.98 +
   97.99 +
  97.100 +    void  SetScreenParameters(int x, int y, unsigned hres, unsigned vres, float hsize, float vsize)
  97.101 +    {
  97.102 +        DesktopX = x;
  97.103 +        DesktopY = y;
  97.104 +        HResolution = hres;
  97.105 +        VResolution = vres;
  97.106 +        HScreenSize = hsize;
  97.107 +        VScreenSize = vsize;
  97.108 +        Contents |= Contents_Screen;
  97.109 +    }
  97.110 +    void SetDistortion(const float* dks)
  97.111 +    {
  97.112 +        for (int i = 0; i < 4; i++)
  97.113 +            DistortionK[i] = dks[i];
  97.114 +        Contents |= Contents_Distortion;
  97.115 +    }
  97.116 +
  97.117 +    void Set7Inch() { Contents |= Contents_7Inch; }
  97.118 +
  97.119 +    bool Is7Inch() const;
  97.120 +};
  97.121 +
  97.122 +
  97.123 +//-------------------------------------------------------------------------------------
  97.124 +
  97.125 +// HMDDevice represents an Oculus HMD device unit. An instance of this class
  97.126 +// is typically created from the DeviceManager.
  97.127 +//  After HMD device is created, we its sensor data can be obtained by 
  97.128 +//  first creating a Sensor object and then wrappig it in SensorFusion.
  97.129 +
  97.130 +class HMDDevice : public DeviceImpl<OVR::HMDDevice>
  97.131 +{
  97.132 +public:
  97.133 +    HMDDevice(HMDDeviceCreateDesc* createDesc);
  97.134 +    ~HMDDevice();    
  97.135 +
  97.136 +    virtual bool Initialize(DeviceBase* parent);
  97.137 +    virtual void Shutdown();
  97.138 +
  97.139 +    // Requests the currently used default profile. This profile affects the
  97.140 +    // settings reported by HMDInfo. 
  97.141 +    virtual Profile*    GetProfile() const;
  97.142 +    virtual const char* GetProfileName() const;
  97.143 +    virtual bool        SetProfileName(const char* name);
  97.144 +
  97.145 +    // Query associated sensor.
  97.146 +    virtual OVR::SensorDevice* GetSensor();  
  97.147 +
  97.148 +protected:
  97.149 +    HMDDeviceCreateDesc* getDesc() const { return (HMDDeviceCreateDesc*)pCreateDesc.GetPtr(); }
  97.150 +
  97.151 +    // User name for the profile used with this device.
  97.152 +    String               ProfileName;
  97.153 +    mutable Ptr<Profile> pCachedProfile;
  97.154 +};
  97.155 +
  97.156 +
  97.157 +}} // namespace OVR::Win32
  97.158 +
  97.159 +#endif // OVR_Win32_HMDDevice_h
  97.160 +
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/libovr/Src/win32/OVR_Win32_SensorDevice.cpp	Sat Sep 14 16:14:59 2013 +0300
    98.3 @@ -0,0 +1,47 @@
    98.4 +/************************************************************************************
    98.5 +
    98.6 +Filename    :   OVR_Win32_SensorDevice.cpp
    98.7 +Content     :   Win32 SensorDevice implementation
    98.8 +Created     :   March 12, 2013
    98.9 +Authors     :   Lee Cooper
   98.10 +
   98.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   98.12 +
   98.13 +Use of this software is subject to the terms of the Oculus license
   98.14 +agreement provided at the time of installation or download, or which
   98.15 +otherwise accompanies this software in either electronic or hard copy form.
   98.16 +
   98.17 +*************************************************************************************/
   98.18 +
   98.19 +#include "OVR_Win32_SensorDevice.h"
   98.20 +
   98.21 +#include "OVR_Win32_HMDDevice.h"
   98.22 +#include "OVR_SensorImpl.h"
   98.23 +#include "OVR_DeviceImpl.h"
   98.24 +
   98.25 +namespace OVR { namespace Win32 {
   98.26 +
   98.27 +} // namespace Win32
   98.28 +
   98.29 +//-------------------------------------------------------------------------------------
   98.30 +void SensorDeviceImpl::EnumerateHMDFromSensorDisplayInfo
   98.31 +    (const SensorDisplayInfoImpl& displayInfo, 
   98.32 +     DeviceFactory::EnumerateVisitor& visitor)
   98.33 +{
   98.34 +
   98.35 +    Win32::HMDDeviceCreateDesc hmdCreateDesc(&Win32::HMDDeviceFactory::Instance, String(), String());
   98.36 +    hmdCreateDesc.SetScreenParameters(  0, 0,
   98.37 +                                        displayInfo.HResolution, displayInfo.VResolution,
   98.38 +                                        displayInfo.HScreenSize, displayInfo.VScreenSize);
   98.39 +
   98.40 +    if ((displayInfo.DistortionType & SensorDisplayInfoImpl::Mask_BaseFmt) == SensorDisplayInfoImpl::Base_Distortion)
   98.41 +        hmdCreateDesc.SetDistortion(displayInfo.DistortionK);
   98.42 +    if (displayInfo.HScreenSize > 0.14f)
   98.43 +        hmdCreateDesc.Set7Inch();
   98.44 +
   98.45 +    visitor.Visit(hmdCreateDesc);
   98.46 +}
   98.47 +
   98.48 +} // namespace OVR
   98.49 +
   98.50 +
    99.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    99.2 +++ b/libovr/Src/win32/OVR_Win32_SensorDevice.h	Sat Sep 14 16:14:59 2013 +0300
    99.3 @@ -0,0 +1,24 @@
    99.4 +/************************************************************************************
    99.5 +
    99.6 +Filename    :   OVR_Win32_SensorDevice.h
    99.7 +Content     :   Win32 SensorDevice implementation
    99.8 +Created     :   March 12, 2013
    99.9 +Authors     :   Lee Cooper
   99.10 +
   99.11 +Copyright   :   Copyright 2013 Oculus VR, Inc. All Rights reserved.
   99.12 +
   99.13 +Use of this software is subject to the terms of the Oculus license
   99.14 +agreement provided at the time of installation or download, or which
   99.15 +otherwise accompanies this software in either electronic or hard copy form.
   99.16 +
   99.17 +*************************************************************************************/
   99.18 +
   99.19 +#ifndef OVR_Win32_SensorDevice_h
   99.20 +#define OVR_Win32_SensorDevice_h
   99.21 +
   99.22 +namespace OVR { namespace Win32 {
   99.23 +
   99.24 +}} // namespace OVR::Win32
   99.25 +
   99.26 +#endif // OVR_Win32_SensorDevice_h
   99.27 +
   100.1 --- a/src/main.cc	Fri Aug 30 06:08:34 2013 +0300
   100.2 +++ b/src/main.cc	Sat Sep 14 16:14:59 2013 +0300
   100.3 @@ -1,5 +1,6 @@
   100.4  #include <stdio.h>
   100.5  #include <stdlib.h>
   100.6 +#include <string.h>
   100.7  #include <assert.h>
   100.8  #include <GL/glew.h>
   100.9  #ifdef __APPLE__
  100.10 @@ -7,7 +8,7 @@
  100.11  #else
  100.12  #include <GL/glut.h>
  100.13  #endif
  100.14 -#include <OVR.h>
  100.15 +#include "vr.h"
  100.16  #include "camera.h"
  100.17  
  100.18  static bool init();
  100.19 @@ -17,14 +18,20 @@
  100.20  static void reshape(int x, int y);
  100.21  static void keyb(unsigned char key, int x, int y);
  100.22  static void sball_rotate(int rx, int ry, int rz);
  100.23 +static bool parse_args(int argc, char **argv);
  100.24  
  100.25  static Camera cam;
  100.26  static int width, height;
  100.27 -static OVR::DeviceManager *ovr_devman;
  100.28 +static bool use_vr = false;
  100.29  
  100.30  int main(int argc, char **argv)
  100.31  {
  100.32  	glutInit(&argc, argv);
  100.33 +
  100.34 +	if(!parse_args(argc, argv)) {
  100.35 +		return 1;
  100.36 +	}
  100.37 +
  100.38  	glutInitWindowSize(1280, 800);
  100.39  	glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
  100.40  	glutCreateWindow("oculus test 01");
  100.41 @@ -55,18 +62,15 @@
  100.42  	glEnable(GL_LIGHT0);
  100.43  	glEnable(GL_LIGHTING);
  100.44  
  100.45 -	// initialize Oculus SDK
  100.46 -	OVR::System::Init();
  100.47 -	if(!(ovr_devman = OVR::DeviceManager::Create())) {
  100.48 -		fprintf(stderr, "failed to create OVR device manager\n");
  100.49 +	if(vr_init(VR_INIT_OCULUS) == -1) {
  100.50  		return false;
  100.51  	}
  100.52 -
  100.53  	return true;
  100.54  }
  100.55  
  100.56  static void cleanup()
  100.57  {
  100.58 +	vr_shutdown();
  100.59  }
  100.60  
  100.61  static void disp()
  100.62 @@ -115,3 +119,23 @@
  100.63  static void sball_rotate(int rx, int ry, int rz)
  100.64  {
  100.65  }
  100.66 +
  100.67 +static bool parse_args(int argc, char **argv)
  100.68 +{
  100.69 +	for(int i=1; i<argc; i++) {
  100.70 +		if(argv[i][0] == '-') {
  100.71 +			if(strcmp(argv[i], "-vr") == 0) {
  100.72 +				use_vr = true;
  100.73 +			} else if(strcmp(argv[i], "-novr") == 0) {
  100.74 +				use_vr = false;
  100.75 +			} else {
  100.76 +				fprintf(stderr, "invalid option: %s\n", argv[i]);
  100.77 +				return false;
  100.78 +			}
  100.79 +		} else {
  100.80 +			fprintf(stderr, "unexpected argument: %s\n", argv[i]);
  100.81 +			return false;
  100.82 +		}
  100.83 +	}
  100.84 +	return true;
  100.85 +}
   101.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   101.2 +++ b/src/vr.cc	Sat Sep 14 16:14:59 2013 +0300
   101.3 @@ -0,0 +1,61 @@
   101.4 +#include <stdio.h>
   101.5 +#include "vr.h"
   101.6 +#include "vr_impl.h"
   101.7 +
   101.8 +static bool init_ovr();
   101.9 +
  101.10 +VRData vr_data;
  101.11 +
  101.12 +extern "C" int vr_init(enum vr_init_mode mode)
  101.13 +{
  101.14 +	if(!init_ovr()) {
  101.15 +		return -1;
  101.16 +	}
  101.17 +	return 0;
  101.18 +}
  101.19 +
  101.20 +extern "C" void vr_shutdown(void)
  101.21 +{
  101.22 +	System::Destroy();
  101.23 +}
  101.24 +
  101.25 +
  101.26 +
  101.27 +static bool init_ovr()
  101.28 +{
  101.29 +	// initialize Oculus SDK
  101.30 +	System::Init();
  101.31 +	if(!(vr_data.ovr_devman = DeviceManager::Create())) {
  101.32 +		fprintf(stderr, "failed to create OVR device manager\n");
  101.33 +		return false;
  101.34 +	}
  101.35 +
  101.36 +	// create the display device
  101.37 +	if(!(vr_data.ovr_hmd_dev = vr_data.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
  101.38 +		fprintf(stderr, "no oculus rift devices found\n");
  101.39 +		return false;
  101.40 +	}
  101.41 +
  101.42 +	HMDInfo info;
  101.43 +	if(vr_data.ovr_hmd_dev->GetDeviceInfo(&info)) {
  101.44 +		printf("oculus device info:\n");
  101.45 +		printf("  name: %s\n", info.DisplayDeviceName);
  101.46 +		printf("  ipd: %f\n", info.InterpupillaryDistance);
  101.47 +		printf("  distortion: %f %f %f %f\n", info.DistortionK[0],
  101.48 +				info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
  101.49 +	}
  101.50 +
  101.51 +	// get the sensor device
  101.52 +	if(!(vr_data.ovr_sensor_dev = vr_data.ovr_hmd_dev->GetSensor())) {
  101.53 +		fprintf(stderr, "failed to get oculus sensor device\n");
  101.54 +		return false;
  101.55 +	}
  101.56 +
  101.57 +	SensorInfo sinfo;
  101.58 +	if(vr_data.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
  101.59 +		printf("oculus sensor device info:\n");
  101.60 +		printf("  name: %s\n", sinfo.ProductName);
  101.61 +	}
  101.62 +
  101.63 +	return true;
  101.64 +}
   102.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   102.2 +++ b/src/vr.h	Sat Sep 14 16:14:59 2013 +0300
   102.3 @@ -0,0 +1,57 @@
   102.4 +#ifndef VR_H_
   102.5 +#define VR_H_
   102.6 +
   102.7 +/* VR mode init options */
   102.8 +enum vr_init_mode {
   102.9 +	VR_INIT_NONE,
  102.10 +	VR_INIT_OCULUS,
  102.11 +	VR_INIT_STEREO
  102.12 +};
  102.13 +
  102.14 +/* possible eye values */
  102.15 +enum {
  102.16 +	VR_EYE_CENTER,
  102.17 +	VR_EYE_LEFT,
  102.18 +	VR_EYE_RIGHT
  102.19 +};
  102.20 +
  102.21 +#ifdef __cplusplus
  102.22 +extern "C" {
  102.23 +#endif
  102.24 +
  102.25 +int vr_init(enum vr_init_mode mode);
  102.26 +void vr_shutdown(void);
  102.27 +
  102.28 +void vr_set_fov(float fov);
  102.29 +float vr_get_fov(void);
  102.30 +
  102.31 +void vr_set_aspect(float aspect);
  102.32 +float vr_get_aspect(void);
  102.33 +
  102.34 +void vr_set_eyedist(float ipd);
  102.35 +float vr_get_eyedist(void);
  102.36 +
  102.37 +/* expects an array of 4 barrel distortion coefficients:
  102.38 + * polar scale: k_0 + k_1 r^2 + k_2 r^4 + k_3 r^6
  102.39 + */
  102.40 +void vr_set_distort(const float *coef);
  102.41 +void vr_get_distort(float *coef);
  102.42 +
  102.43 +void vr_get_view_matrix(float *res, int eye);
  102.44 +void vr_get_proj_matrix(float *res, int eye);
  102.45 +
  102.46 +/* expects an array of at least 3 floats (x, y, z, offset). */
  102.47 +void vr_get_translation(float *offs);
  102.48 +/* expects an array of at least 4 floats (x, y, z, w, quaternion). */
  102.49 +void vr_get_rotation(float *quat);
  102.50 +/* expects an array of at least 3 floats (pitch, yaw, roll, angles). */
  102.51 +void vr_get_rotation_euler(float *euler);
  102.52 +
  102.53 +/* OpenGL stuff */
  102.54 +void vr_draw_eye(unsigned int tex, int eye);
  102.55 +
  102.56 +#ifdef __cplusplus
  102.57 +}
  102.58 +#endif
  102.59 +
  102.60 +#endif	/* VR_H_ */
   103.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.2 +++ b/src/vr_impl.h	Sat Sep 14 16:14:59 2013 +0300
   103.3 @@ -0,0 +1,21 @@
   103.4 +#ifndef VR_IMPL_H_
   103.5 +#define VR_IMPL_H_
   103.6 +
   103.7 +#include <OVR.h>
   103.8 +
   103.9 +using namespace OVR;
  103.10 +
  103.11 +struct VRData {
  103.12 +	DeviceManager *ovr_devman;
  103.13 +	HMDDevice *ovr_hmd_dev;
  103.14 +	SensorDevice *ovr_sensor_dev;
  103.15 +
  103.16 +	float fov;
  103.17 +	float aspect;
  103.18 +	float ipd;
  103.19 +	float distort[4];
  103.20 +};
  103.21 +
  103.22 +extern VRData vr_data;
  103.23 +
  103.24 +#endif	// VR_IMPL_H_