oculus1
changeset 1:e2f9e4603129
added LibOVR and started a simple vr wrapper.
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(¬ificationFilter, 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 + ¬ificationFilter, 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_