diff options
Diffstat (limited to 'LibOVR')
80 files changed, 3217 insertions, 2059 deletions
diff --git a/LibOVR/Include/OVR_Version.h b/LibOVR/Include/OVR_Version.h index 314c8b5..49dd301 100644 --- a/LibOVR/Include/OVR_Version.h +++ b/LibOVR/Include/OVR_Version.h @@ -1,20 +1,20 @@ /************************************************************************************ Filename : OVRVersion.h -Content : +Content : Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); -you may not use the Oculus VR Rift SDK except in compliance with the License, -which is provided at the time of installation or download, or which +Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); +you may not use the Oculus VR Rift SDK except in compliance with the License, +which is provided at the time of installation or download, or which otherwise accompanies this software in either electronic or hard copy form. You may obtain a copy of the License at -http://www.oculusvr.com/licenses/LICENSE-3.1 +http://www.oculusvr.com/licenses/LICENSE-3.1 -Unless required by applicable law or agreed to in writing, the Oculus VR SDK +Unless required by applicable law or agreed to in writing, the Oculus VR SDK distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and @@ -27,7 +27,7 @@ limitations under the License. #define OVR_MAJOR_VERSION 0 #define OVR_MINOR_VERSION 4 -#define OVR_BUILD_VERSION 1 -#define OVR_VERSION_STRING "0.4.1" +#define OVR_BUILD_VERSION 2 +#define OVR_VERSION_STRING "0.4.2" #endif diff --git a/LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp index 217310c..f335675 100644 --- a/LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp +++ b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.cpp @@ -99,7 +99,6 @@ double DistortionRenderer::WaitTillTime(double absTime) return 0.0; double newTime = initialTime; - volatile int i; while (newTime < absTime) { @@ -124,7 +123,7 @@ double DistortionRenderer::WaitTillTime(double absTime) if (sleptTime > remainingWaitTime) { OVR_DEBUG_LOG_TEXT( - ("[DistortionRenderer::FlushGpuAndWaitTillTime] Sleep interval too long: %f\n", sleptTime)); + ("[DistortionRenderer::WaitTillTime] Sleep interval too long: %f\n", sleptTime)); } else { @@ -135,9 +134,9 @@ double DistortionRenderer::WaitTillTime(double absTime) else #endif { - for (int j = 0; j < 50; j++) - i = 0; - } + for (int j = 0; j < 5; j++) + OVR_PROCESSOR_PAUSE(); + } newTime = ovr_GetTimeInSeconds(); } diff --git a/LibOVR/Src/CAPI/CAPI_DistortionRenderer.h b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.h index 601cbc2..c9a86fa 100644 --- a/LibOVR/Src/CAPI/CAPI_DistortionRenderer.h +++ b/LibOVR/Src/CAPI/CAPI_DistortionRenderer.h @@ -50,14 +50,15 @@ public: DistortionRenderer(ovrRenderAPIType api, ovrHmd hmd, FrameTimeManager& timeManager, const HMDRenderState& renderState) : + LastUsedOverdriveTextureIndex(-1), + LatencyTestActive(false), + LatencyTest2Active(false), RenderAPI(api), HMD(hmd), TimeManager(timeManager), RState(renderState), - RegisteredPostDistortionCallback(NULL), - LastUsedOverdriveTextureIndex(-1), - LatencyTestActive(false), - LatencyTest2Active(false) + GfxState(), + RegisteredPostDistortionCallback(NULL) { #ifdef OVR_OS_WIN32 timer = CreateWaitableTimer(NULL, TRUE, NULL); diff --git a/LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp index 2823658..9c192e3 100644 --- a/LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp +++ b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.cpp @@ -219,20 +219,40 @@ void FrameLatencyTracker::GetLatencyTimings(float latencies[3]) latencies[2] = (float)FrameDeltas.GetMedianTimeDelta(); } } - - + + //------------------------------------------------------------------------------------- -FrameTimeManager::FrameTimeManager(bool vsyncEnabled) - : VsyncEnabled(vsyncEnabled), DynamicPrediction(true), SdkRender(false), - FrameTiming() +FrameTimeManager::FrameTimeManager(bool vsyncEnabled) : + VsyncEnabled(vsyncEnabled), + DynamicPrediction(true), + SdkRender(false), + DirectToRift(false), +#ifndef NO_SCREEN_TEAR_HEALING + ScreenTearing(false), + TearingFrameCount(0), +#endif // NO_SCREEN_TEAR_HEALING + FrameTiming() { RenderIMUTimeSeconds = 0.0; TimewarpIMUTimeSeconds = 0.0; - - // HACK: SyncToScanoutDelay observed close to 1 frame in video cards. - // Overwritten by dynamic latency measurement on DK2. - VSyncToScanoutDelay = 0.013f; + + // If driver is in use, + DirectToRift = !Display::InCompatibilityMode(false); + if (DirectToRift) + { + // The latest driver provides a post-present vsync-to-scan-out delay + // that is roughly zero. The latency tester will provide real numbers + // but when it is unavailable for some reason, we should default to + // an expected value. + VSyncToScanoutDelay = 0.0001f; + } + else + { + // HACK: SyncToScanoutDelay observed close to 1 frame in video cards. + // Overwritten by dynamic latency measurement on DK2. + VSyncToScanoutDelay = 0.013f; + } NoVSyncToScanoutDelay = 0.004f; } @@ -302,6 +322,10 @@ double FrameTimeManager::calcScreenDelay() const double screenDelay = ScreenSwitchingDelay; double measuredVSyncToScanout; +#ifndef NO_SCREEN_TEAR_HEALING + bool tearing = false; +#endif // NO_SCREEN_TEAR_HEALING + // Use real-time DK2 latency tester HW for prediction if its is working. // Do sanity check under 60 ms if (!VsyncEnabled) @@ -311,8 +335,14 @@ double FrameTimeManager::calcScreenDelay() const else if ( DynamicPrediction && (ScreenLatencyTracker.FrameDeltas.GetCount() > 3) && (measuredVSyncToScanout = ScreenLatencyTracker.FrameDeltas.GetMedianTimeDelta(), - (measuredVSyncToScanout > 0.0001) && (measuredVSyncToScanout < 0.06)) ) + (measuredVSyncToScanout > -0.0001) && (measuredVSyncToScanout < 0.06)) ) { +#ifndef NO_SCREEN_TEAR_HEALING + if (DirectToRift && measuredVSyncToScanout > 0.010 && measuredVSyncToScanout < 0.030) + { + tearing = true; + } +#endif // NO_SCREEN_TEAR_HEALING screenDelay += measuredVSyncToScanout; } else @@ -320,11 +350,51 @@ double FrameTimeManager::calcScreenDelay() const screenDelay += VSyncToScanoutDelay; } +#ifndef NO_SCREEN_TEAR_HEALING + if (tearing) + { + if (TearingFrameCount > 75) + { + if (!ScreenTearing) + { + ScreenTearing = true; + HealingFrameCount = 0; + } + } + else + { + TearingFrameCount++; + } + } + else + { + TearingFrameCount = 0; + ScreenTearing = false; + } +#endif // NO_SCREEN_TEAR_HEALING + return screenDelay; } +#ifndef NO_SCREEN_TEAR_HEALING + +bool FrameTimeManager::ScreenTearingReaction() +{ + if (ScreenTearing) + { + if (HealingFrameCount < 75) + { + ++HealingFrameCount; + return true; + } + } + + return false; +} + +#endif // NO_SCREEN_TEAR_HEALING -double FrameTimeManager::calcTimewarpWaitDelta() const +double FrameTimeManager::calcTimewarpWaitDelta() const { // If timewarp timing hasn't been calculated, we should wait. if (!VsyncEnabled) @@ -842,11 +912,11 @@ double TimeDeltaCollector::GetMedianTimeDelta() const SortedList[i] = smallestDelta; } + // FIRMWARE HACK: Don't take the actual median, but err on the low time side Median = SortedList[Count/4]; ReCalcMedian = false; } - // FIRMWARE HACK: Don't take the actual median, but err on the low time side return Median; } diff --git a/LibOVR/Src/CAPI/CAPI_FrameTimeManager.h b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.h index 5522668..2af5388 100644 --- a/LibOVR/Src/CAPI/CAPI_FrameTimeManager.h +++ b/LibOVR/Src/CAPI/CAPI_FrameTimeManager.h @@ -40,7 +40,7 @@ namespace OVR { namespace CAPI { // how long to wait. struct TimeDeltaCollector { - TimeDeltaCollector() : Count(0), ReCalcMedian(true), Median(-1.0) { } + TimeDeltaCollector() : Median(-1.0), Count(0), ReCalcMedian(true) { } void AddTimeDelta(double timeSeconds); void Clear() { Count = 0; } @@ -132,7 +132,7 @@ public: class FrameTimeManager { public: - FrameTimeManager(bool vsyncEnabled = true); + FrameTimeManager(bool vsyncEnabled); // Data that affects frame timing computation. struct TimingInputs @@ -222,11 +222,14 @@ public: void GetLatencyTimings(float latencies[3]) { return ScreenLatencyTracker.GetLatencyTimings(latencies); } - const Timing& GetFrameTiming() const { return FrameTiming; } -private: +#ifndef NO_SCREEN_TEAR_HEALING + bool IsScreenTearing() const { return ScreenTearing; }; + bool ScreenTearingReaction(); +#endif // NO_SCREEN_TEAR_HEALING +private: double calcFrameDelta() const; double calcScreenDelay() const; double calcTimewarpWaitDelta() const; @@ -292,8 +295,18 @@ private: bool VsyncEnabled; // Set if we are rendering via the SDK, so DistortionRenderTimes is valid. bool DynamicPrediction; - // Set if SDk is doing teh rendering. + // Set if SDk is doing the rendering. bool SdkRender; + // Direct to rift. + bool DirectToRift; +#ifndef NO_SCREEN_TEAR_HEALING + // Screen tearing detection + mutable bool ScreenTearing; + // Number of frames tearing has been observed + mutable int TearingFrameCount; + // Number of frames of reaction + mutable int HealingFrameCount; +#endif // NO_SCREEN_TEAR_HEALING // Total frame delay due to VsyncToFirstScanline, persistence and settle time. // Computed from RenderInfor.Shutter. diff --git a/LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp b/LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp index d77542b..fd3d667 100644 --- a/LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp +++ b/LibOVR/Src/CAPI/CAPI_HMDRenderState.cpp @@ -62,7 +62,8 @@ ovrHmdDesc HMDRenderState::GetDesc() const d.TrackingCaps = ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Orientation; d.DistortionCaps = ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp | ovrDistortionCap_Vignette | ovrDistortionCap_SRGB | - ovrDistortionCap_FlipInput | ovrDistortionCap_ProfileNoTimewarpSpinWaits; + ovrDistortionCap_FlipInput | ovrDistortionCap_ProfileNoTimewarpSpinWaits | + ovrDistortionCap_HqDistortion; if( OurHMDInfo.InCompatibilityMode ) d.HmdCaps |= ovrHmdCap_ExtendDesktop; diff --git a/LibOVR/Src/CAPI/CAPI_HMDState.cpp b/LibOVR/Src/CAPI/CAPI_HMDState.cpp index 6d6162d..720857d 100644 --- a/LibOVR/Src/CAPI/CAPI_HMDState.cpp +++ b/LibOVR/Src/CAPI/CAPI_HMDState.cpp @@ -42,31 +42,70 @@ HMDState::HMDState(const OVR::Service::HMDNetworkInfo& netInfo, const OVR::HMDInfo& hmdInfo, Profile* profile, Service::NetClient* client) : - pClient(client), pProfile(profile), pHmdDesc(0), pWindow(0), - NetInfo(netInfo), + pClient(client), NetId(netInfo.NetId), + NetInfo(netInfo), OurHMDInfo(hmdInfo), + pLastError(NULL), EnabledHmdCaps(0), - LastFrameTimeSeconds(0.f), - LastGetFrameTimeSeconds(0.), + EnabledServiceHmdCaps(0), + SharedStateReader(), + TheSensorStateReader(), + TheLatencyTestStateReader(), LatencyTestActive(false), - LatencyTest2Active(false) + //LatencyTestDrawColor(), + LatencyTest2Active(false), + //LatencyTest2DrawColor(), + TimeManager(true), + RenderState(), + pRenderer(), + pHSWDisplay(), + LastFrameTimeSeconds(0.), + LastGetFrameTimeSeconds(0.), + //LastGetStringValue(), + RenderingConfigured(false), + BeginFrameCalled(false), + BeginFrameThreadId(), + RenderAPIThreadChecker(), + BeginFrameTimingCalled(false) { sharedInit(profile); } + HMDState::HMDState(const OVR::HMDInfo& hmdInfo, Profile* profile) : - pClient(0), + pProfile(profile), pHmdDesc(0), + pWindow(0), + pClient(0), NetId(InvalidVirtualHmdId), - pProfile(profile), + NetInfo(), OurHMDInfo(hmdInfo), + pLastError(NULL), EnabledHmdCaps(0), + EnabledServiceHmdCaps(0), + SharedStateReader(), + TheSensorStateReader(), + TheLatencyTestStateReader(), + LatencyTestActive(false), + //LatencyTestDrawColor(), + LatencyTest2Active(false), + //LatencyTest2DrawColor(), + TimeManager(true), + RenderState(), + pRenderer(), + pHSWDisplay(), LastFrameTimeSeconds(0.), - LastGetFrameTimeSeconds(0.) + LastGetFrameTimeSeconds(0.), + //LastGetStringValue(), + RenderingConfigured(false), + BeginFrameCalled(false), + BeginFrameThreadId(), + RenderAPIThreadChecker(), + BeginFrameTimingCalled(false) { sharedInit(profile); } @@ -82,7 +121,10 @@ HMDState::~HMDState() ConfigureRendering(0,0,0,0); if (pHmdDesc) - delete pHmdDesc; + { + OVR_FREE(pHmdDesc); + pHmdDesc = NULL; + } } void HMDState::sharedInit(Profile* profile) @@ -96,7 +138,7 @@ void HMDState::sharedInit(Profile* profile) UpdateRenderProfile(profile); OVR_ASSERT(!pHmdDesc); - pHmdDesc = new ovrHmdDesc; + pHmdDesc = (ovrHmdDesc*)OVR_ALLOC(sizeof(ovrHmdDesc)); *pHmdDesc = RenderState.GetDesc(); pHmdDesc->Handle = this; @@ -120,6 +162,8 @@ void HMDState::sharedInit(Profile* profile) BeginFrameThreadId = 0; BeginFrameTimingCalled = false; + TheSensorStateReader.LoadProfileCenteredFromWorld(profile); + // Construct the HSWDisplay. We will later reconstruct it with a specific ovrRenderAPI type if the application starts using SDK-based rendering. if(!pHSWDisplay) pHSWDisplay = *OVR::CAPI::HSWDisplay::Factory(ovrRenderAPI_None, pHmdDesc, RenderState); @@ -264,7 +308,7 @@ ovrTrackingState HMDState::PredictedTrackingState(double absTime) TheSensorStateReader.GetSensorStateAtTime(absTime, ss); // Zero out the status flags - if (!pClient || !pClient->IsConnected()) + if (!pClient || !pClient->IsConnected(false, false)) { ss.StatusFlags = 0; } @@ -360,8 +404,7 @@ bool HMDState::getBoolValue(const char* propertyName, bool defaultVal) bool HMDState::setBoolValue(const char* propertyName, bool value) { - NetClient::GetInstance()->SetBoolValue(GetNetId(), propertyName, value); - return true; + return NetClient::GetInstance()->SetBoolValue(GetNetId(), propertyName, value); } int HMDState::getIntValue(const char* propertyName, int defaultVal) @@ -379,8 +422,7 @@ int HMDState::getIntValue(const char* propertyName, int defaultVal) bool HMDState::setIntValue(const char* propertyName, int value) { - NetClient::GetInstance()->SetIntValue(GetNetId(), propertyName, value); - return true; + return NetClient::GetInstance()->SetIntValue(GetNetId(), propertyName, value); } float HMDState::getFloatValue(const char* propertyName, float defaultVal) @@ -411,8 +453,7 @@ float HMDState::getFloatValue(const char* propertyName, float defaultVal) bool HMDState::setFloatValue(const char* propertyName, float value) { - NetClient::GetInstance()->SetNumberValue(GetNetId(), propertyName, value); - return true; + return NetClient::GetInstance()->SetNumberValue(GetNetId(), propertyName, value); } static unsigned CopyFloatArrayWithLimit(float dest[], unsigned destSize, @@ -501,11 +542,11 @@ bool HMDState::setFloatArray(const char* propertyName, float values[], unsigned da[i] = values[i]; } - NetClient::GetInstance()->SetNumberValues(GetNetId(), propertyName, da, arraySize); + bool result = NetClient::GetInstance()->SetNumberValues(GetNetId(), propertyName, da, arraySize); delete[] da; - return true; + return result; } const char* HMDState::getString(const char* propertyName, const char* defaultVal) @@ -529,8 +570,7 @@ const char* HMDState::getString(const char* propertyName, const char* defaultVal bool HMDState::setString(const char* propertyName, const char* value) { - NetClient::GetInstance()->SetStringValue(GetNetId(), propertyName, value); - return true; + return NetClient::GetInstance()->SetStringValue(GetNetId(), propertyName, value); } @@ -539,93 +579,7 @@ bool HMDState::setString(const char* propertyName, const char* value) bool HMDState::ProcessLatencyTest(unsigned char rgbColorOut[3]) { - bool result = false; - - result = NetClient::GetInstance()->LatencyUtil_ProcessInputs(Timer::GetSeconds(), rgbColorOut); - -#if 0 //def ENABLE_LATENCY_TESTER - // Check create. - if (pLatencyTester) - { - if (pLatencyTester->IsConnected()) - { - Color colorToDisplay; - - LatencyUtil.ProcessInputs(); - result = LatencyUtil.DisplayScreenColor(colorToDisplay); - rgbColorOut[0] = colorToDisplay.R; - rgbColorOut[1] = colorToDisplay.G; - rgbColorOut[2] = colorToDisplay.B; - } - else - { - // Disconnect. - LatencyUtil.SetDevice(NULL); - pLatencyTester = 0; - LogText("LATENCY SENSOR disconnected.\n"); - } - } - else if (AddLatencyTestCount > 0) - { - // This might have some unlikely race condition issue which could cause us to miss a device... - AddLatencyTestCount = 0; - - pLatencyTester = *GlobalState::pInstance->GetManager()->EnumerateDevices<LatencyTestDevice>().CreateDevice(); - if (pLatencyTester) - { - LatencyUtil.SetDevice(pLatencyTester); - LogText("LATENCY TESTER connected\n"); - } - } -#endif - - return result; -} - -void HMDState::ProcessLatencyTest2(unsigned char rgbColorOut[3], double startTime) -{ - OVR_UNUSED2(rgbColorOut, startTime); - /* - // Check create. - if (!(EnabledHmdCaps & ovrHmdCap_LatencyTest)) - return; - - if (pLatencyTesterDisplay && !LatencyUtil2.HasDisplayDevice()) - { - if (!pLatencyTesterDisplay->IsConnected()) - { - LatencyUtil2.SetDisplayDevice(NULL); - } - } - else if (AddLatencyTestDisplayCount > 0) - { - // This might have some unlikely race condition issue - // which could cause us to miss a device... - AddLatencyTestDisplayCount = 0; - - pLatencyTesterDisplay = *GlobalState::pInstance->GetManager()-> - EnumerateDevices<LatencyTestDevice>().CreateDevice(); - if (pLatencyTesterDisplay) - { - LatencyUtil2.SetDisplayDevice(pLatencyTesterDisplay); - } - } - - if (LatencyUtil2.HasDevice() && pSensor && pSensor->IsConnected()) - { - LatencyUtil2.BeginTest(startTime); - - Color colorToDisplay; - LatencyTest2Active = LatencyUtil2.DisplayScreenColor(colorToDisplay); - rgbColorOut[0] = colorToDisplay.R; - rgbColorOut[1] = colorToDisplay.G; - rgbColorOut[2] = colorToDisplay.B; - } - else - { - LatencyTest2Active = false; - } - */ + return NetClient::GetInstance()->LatencyUtil_ProcessInputs(Timer::GetSeconds(), rgbColorOut); } //------------------------------------------------------------------------------------- diff --git a/LibOVR/Src/CAPI/CAPI_HMDState.h b/LibOVR/Src/CAPI/CAPI_HMDState.h index 863c5c5..40f4738 100644 --- a/LibOVR/Src/CAPI/CAPI_HMDState.h +++ b/LibOVR/Src/CAPI/CAPI_HMDState.h @@ -156,8 +156,7 @@ public: unsigned SetEnabledHmdCaps(); bool ProcessLatencyTest(unsigned char rgbColorOut[3]); - void ProcessLatencyTest2(unsigned char rgbColorOut[3], double startTime); - + // *** Rendering Setup bool ConfigureRendering(ovrEyeRenderDesc eyeRenderDescOut[2], const ovrFovPort eyeFovIn[2], diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp index 18ad298..b2f8547 100644 --- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp @@ -340,6 +340,12 @@ void DistortionRenderer::EndFrame(bool swapBuffers) if (RParams.pSwapChain) { UINT swapInterval = (RState.EnabledHmdCaps & ovrHmdCap_NoVSync) ? 0 : 1; +#ifndef NO_SCREEN_TEAR_HEALING + if (TimeManager.ScreenTearingReaction()) + { + swapInterval = 0; + } +#endif // NO_SCREEN_TEAR_HEALING RParams.pSwapChain->Present(swapInterval, 0); // Force GPU to flush the scene, resulting in the lowest possible latency. @@ -491,26 +497,33 @@ void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* righ for(int eyeNum = 0; eyeNum < 2; eyeNum++) - { + { ShaderFill distortionShaderFill(DistortionShader); distortionShaderFill.SetTexture(0, eyeNum == 0 ? leftEyeTexture : rightEyeTexture); + if(RState.DistortionCaps & ovrDistortionCap_HqDistortion) + { + static float aaDerivMult = 0.5f; + DistortionShader->SetUniform1f("AaDerivativeMult", aaDerivMult); + } + else + { + // 0.0 disables high quality anti-aliasing + DistortionShader->SetUniform1f("AaDerivativeMultOffset", -1.0f); + } + if(overdriveActive) { distortionShaderFill.SetTexture(1, pOverdriveTextures[LastUsedOverdriveTextureIndex]); - - float invRtWidth = 1.0f / (float)RParams.RTSize.w; - float invRtHeight = 1.0f / (float)RParams.RTSize.h; - DistortionShader->SetUniform2f("OverdriveInvRTSize", invRtWidth, invRtHeight); - + static float overdriveScaleRegularRise = 0.1f; - static float overdriveScaleRegularFall = 0.05f; // falling issues are hardly visible + static float overdriveScaleRegularFall = 0.05f; // falling issues are hardly visible DistortionShader->SetUniform2f("OverdriveScales", overdriveScaleRegularRise, overdriveScaleRegularFall); } else { // -1.0f disables PLO - DistortionShader->SetUniform2f("OverdriveInvRTSize", -1.0f, -1.0f); + DistortionShader->SetUniform2f("OverdriveScales", -1.0f, -1.0f); } distortionShaderFill.SetInputLayout(DistortionVertexIL); @@ -524,7 +537,7 @@ void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* righ ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum, RState.EyeRenderPoses[eyeNum], timeWarpMatrices); - // Feed identity like matrices in until we get proper timewarp calculation going on + // Can feed identity like matrices incase of concern over timewarp calculations DistortionShader->SetUniform4x4f("EyeRotationStart", Matrix4f(timeWarpMatrices[0])); DistortionShader->SetUniform4x4f("EyeRotationEnd", Matrix4f(timeWarpMatrices[1])); diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp index a685191..5ede0b8 100644 --- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp @@ -156,9 +156,6 @@ void DistortionRenderer::EndFrame(bool swapBuffers) renderEndFrame(); } - if(RegisteredPostDistortionCallback) - RegisteredPostDistortionCallback(device); - if(LatencyTestDrawColor) { // TODO: Support latency tester quad diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h index be5aa5f..c35bf43 100644 --- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h +++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h @@ -26,8 +26,6 @@ limitations under the License. #include "../../Kernel/OVR_Types.h" -#undef new - #if defined (OVR_OS_WIN32) #define WIN32_LEAN_AND_MEAN #if _MSC_VER < 1700 diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp index bb52d98..2c903b6 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.cpp @@ -98,6 +98,9 @@ DistortionRenderer::DistortionRenderer(ovrHmd hmd, FrameTimeManager& timeManager { DistortionMeshVAOs[0] = 0; DistortionMeshVAOs[1] = 0; + + // Initialize render params. + memset(&RParams, 0, sizeof(RParams)); } DistortionRenderer::~DistortionRenderer() @@ -155,7 +158,6 @@ bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig, RParams.Win = config->OGL.Win; if (!RParams.Win) { - int unused; RParams.Win = glXGetCurrentDrawable(); } if (!RParams.Win) @@ -270,9 +272,16 @@ void DistortionRenderer::EndFrame(bool swapBuffers) if (swapBuffers) { bool useVsync = ((RState.EnabledHmdCaps & ovrHmdCap_NoVSync) == 0); - int swapInterval = (useVsync) ? 1 : 0; + int swapInterval = (useVsync) ? 1 : 0; #if defined(OVR_OS_WIN32) - if (wglGetSwapIntervalEXT() != swapInterval) +#ifndef NO_SCREEN_TEAR_HEALING + if (TimeManager.ScreenTearingReaction()) + { + swapInterval = 0; + useVsync = false; + } +#endif // NO_SCREEN_TEAR_HEALING + if (wglGetSwapIntervalEXT() != swapInterval) wglSwapIntervalEXT(swapInterval); HDC dc = (RParams.DC != NULL) ? RParams.DC : GetDC(RParams.Window); @@ -297,7 +306,7 @@ void DistortionRenderer::EndFrame(bool swapBuffers) { GLuint currentSwapInterval = 0; glXQueryDrawable(RParams.Disp, RParams.Win, GLX_SWAP_INTERVAL_EXT, ¤tSwapInterval); - if (currentSwapInterval != swapInterval) + if (currentSwapInterval != (GLuint)swapInterval) glXSwapIntervalEXT(RParams.Disp, RParams.Win, swapInterval); } @@ -332,58 +341,17 @@ double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime) return WaitTillTime(absTime); } - - + + DistortionRenderer::GraphicsState::GraphicsState() { - bool foundVersion = false; - const char* glVersionString = (const char*)glGetString(GL_VERSION); - if (glVersionString) - { - OVR_DEBUG_LOG(("GL_VERSION STRING: %s", (const char*)glVersionString)); - char prefix[64]; + GetGLVersionAndExtensions(GLVersionInfo); +} - for (int i = 10; i < 30; ++i) - { - int major = i / 10; - int minor = i % 10; - OVR_sprintf(prefix, 64, "%d.%d", major, minor); - if (strstr(glVersionString, prefix) == glVersionString) - { - GlMajorVersion = major; - GlMinorVersion = minor; - foundVersion = true; - break; - } - } - } - - if (!foundVersion) - { - glGetIntegerv(GL_MAJOR_VERSION, &GlMajorVersion); - glGetIntegerv(GL_MAJOR_VERSION, &GlMinorVersion); - } - OVR_ASSERT(GlMajorVersion >= 2); - - if (GlMajorVersion >= 3) - { - SupportsVao = true; - SupportsDrawBuffers = true; - } - else - { - const char* extensions = (const char*)glGetString(GL_EXTENSIONS); - SupportsVao = (strstr(extensions, "GL_ARB_vertex_array_object") != NULL - || strstr(extensions, "GL_APPLE_vertex_array_object") != NULL); - SupportsDrawBuffers = (strstr(extensions, "GL_EXT_draw_buffers2") != NULL); - } -} - - void DistortionRenderer::GraphicsState::ApplyBool(GLenum Name, GLint Value, GLint index) { - if (SupportsDrawBuffers && index != -1) + if (GLVersionInfo.SupportsDrawBuffers && index != -1) { if (Value != 0) glEnablei(Name, index); @@ -410,7 +378,7 @@ void DistortionRenderer::GraphicsState::Save() glGetIntegerv(GL_CURRENT_PROGRAM, &Program); glGetIntegerv(GL_ACTIVE_TEXTURE, &ActiveTexture); glGetIntegerv(GL_TEXTURE_BINDING_2D, &TextureBinding); - if (SupportsVao) + if (GLVersionInfo.SupportsVAO) { glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &VertexArrayBinding); } @@ -420,7 +388,7 @@ void DistortionRenderer::GraphicsState::Save() glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &ArrayBufferBinding); } glGetIntegerv(GL_FRAMEBUFFER_BINDING, &FrameBufferBinding); - if (SupportsDrawBuffers) + if (GLVersionInfo.SupportsDrawBuffers) { glGetIntegeri_v(GL_BLEND, 0, &Blend); glGetIntegeri_v(GL_COLOR_WRITEMASK, 0, ColorWritemask); @@ -432,8 +400,10 @@ void DistortionRenderer::GraphicsState::Save() } glGetIntegerv(GL_DITHER, &Dither); glGetIntegerv(GL_RASTERIZER_DISCARD, &RasterizerDiscard); - if ((GlMajorVersion == 3 && GlMinorVersion >= 2) || GlMajorVersion >= 4) + if ((GLVersionInfo.MajorVersion == 3 && GLVersionInfo.MinorVersion >= 2) || GLVersionInfo.MajorVersion >= 4) + { glGetIntegerv(GL_SAMPLE_MASK, &SampleMask); + } IsValid = true; } @@ -441,7 +411,7 @@ void DistortionRenderer::GraphicsState::Save() #ifdef OVR_OS_MAC bool DistortionRenderer::GraphicsState::isAtLeastOpenGL3() { - return !(GlMajorVersion < 3|| (GlMajorVersion == 3 && GlMinorVersion < 2)); + return (((GLVersionInfo.MajorVersion * 100) + GLVersionInfo.MinorVersion) >= 302); // OpenGL 3.2 or later } #endif @@ -461,7 +431,7 @@ void DistortionRenderer::GraphicsState::Restore() glUseProgram(Program); glActiveTexture(ActiveTexture); glBindTexture(GL_TEXTURE_2D, TextureBinding); - if (SupportsVao) + if (GLVersionInfo.SupportsVAO) { #ifdef OVR_OS_MAC if (isAtLeastOpenGL3()) @@ -485,15 +455,22 @@ void DistortionRenderer::GraphicsState::Restore() ApplyBool(GL_BLEND, Blend, 0); - if (SupportsDrawBuffers) + if (GLVersionInfo.SupportsDrawBuffers) + { glColorMaski(0, (GLboolean)ColorWritemask[0], (GLboolean)ColorWritemask[1], (GLboolean)ColorWritemask[2], (GLboolean)ColorWritemask[3]); + } else + { glColorMask((GLboolean)ColorWritemask[0], (GLboolean)ColorWritemask[1], (GLboolean)ColorWritemask[2], (GLboolean)ColorWritemask[3]); + } ApplyBool(GL_DITHER, Dither); ApplyBool(GL_RASTERIZER_DISCARD, RasterizerDiscard); - if ((GlMajorVersion == 3 && GlMinorVersion >= 2) || GlMajorVersion >= 4) + if ((GLVersionInfo.MajorVersion == 3 && GLVersionInfo.MinorVersion >= 2) || + GLVersionInfo.MajorVersion >= 4) + { ApplyBool(GL_SAMPLE_MASK, SampleMask); + } } @@ -525,9 +502,13 @@ void DistortionRenderer::initBuffersAndShaders() { pCurVBVert->ScreenPosNDC.x = pCurOvrVert->ScreenPosNDC.x; pCurVBVert->ScreenPosNDC.y = pCurOvrVert->ScreenPosNDC.y; - pCurVBVert->TanEyeAnglesR = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesR); - pCurVBVert->TanEyeAnglesG = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesG); - pCurVBVert->TanEyeAnglesB = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesB); + + // Previous code here did this: pCurVBVert->TanEyeAnglesR = (*(Vector2f*)&pCurOvrVert->TanEyeAnglesR); However that's an usafe + // cast of unrelated types which can result in undefined behavior by a conforming compiler. A safe equivalent is simply memcpy. + static_assert(sizeof(OVR::Vector2f) == sizeof(ovrVector2f), "Mismatch of structs that are presumed binary equivalents."); + memcpy(&pCurVBVert->TanEyeAnglesR, &pCurOvrVert->TanEyeAnglesR, sizeof(pCurVBVert->TanEyeAnglesR)); + memcpy(&pCurVBVert->TanEyeAnglesG, &pCurOvrVert->TanEyeAnglesG, sizeof(pCurVBVert->TanEyeAnglesG)); + memcpy(&pCurVBVert->TanEyeAnglesB, &pCurOvrVert->TanEyeAnglesB, sizeof(pCurVBVert->TanEyeAnglesB)); // Convert [0.0f,1.0f] to [0,255] if (DistortionCaps & ovrDistortionCap_Vignette) @@ -569,7 +550,7 @@ void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* righ glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); - if (glState->SupportsDrawBuffers) + if (glState->GLVersionInfo.SupportsDrawBuffers) { glDisablei(GL_BLEND, 0); glColorMaski(0, GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); @@ -582,8 +563,10 @@ void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* righ glDisable(GL_DITHER); glDisable(GL_RASTERIZER_DISCARD); - if ((glState->GlMajorVersion >= 3 && glState->GlMinorVersion >= 2) || glState->GlMajorVersion >= 4) + if ((glState->GLVersionInfo.MajorVersion >= 3 && glState->GLVersionInfo.MinorVersion >= 2) || glState->GLVersionInfo.MajorVersion >= 4) + { glDisable(GL_SAMPLE_MASK); + } glClearColor( RState.ClearColor[0], @@ -780,7 +763,7 @@ void DistortionRenderer::renderPrimitives( } else { - if (glState->SupportsVao) + if (glState->GLVersionInfo.SupportsVAO) { #ifdef OVR_OS_MAC if (glState->isAtLeastOpenGL3()) @@ -836,7 +819,7 @@ void DistortionRenderer::renderPrimitives( glDrawArrays(prim, 0, count); - if (!glState->SupportsVao) + if (!glState->GLVersionInfo.SupportsVAO) { for (int i = 0; i < attributeCount; ++i) glDisableVertexAttribArray(locs[i]); @@ -844,7 +827,7 @@ void DistortionRenderer::renderPrimitives( delete[] locs; - if (glState->SupportsVao) + if (glState->GLVersionInfo.SupportsVAO) { #ifdef OVR_OS_MAC if (glState->isAtLeastOpenGL3()) @@ -874,7 +857,8 @@ void DistortionRenderer::initShaders() GraphicsState* glState = (GraphicsState*)GfxState.GetPtr(); const char* shaderPrefix = - (glState->GlMajorVersion < 3 || (glState->GlMajorVersion == 3 && glState->GlMinorVersion < 2)) ? + (glState->GLVersionInfo.MajorVersion < 3 || + (glState->GLVersionInfo.MajorVersion == 3 && glState->GLVersionInfo.MinorVersion < 2)) ? glsl2Prefix : glsl3Prefix; { @@ -979,11 +963,13 @@ void DistortionRenderer::destroy() SaveGraphicsState(); GraphicsState* glState = (GraphicsState*)GfxState.GetPtr(); - + for(int eyeNum = 0; eyeNum < 2; eyeNum++) { - if (glState->SupportsVao) + if (glState->GLVersionInfo.SupportsVAO) + { glDeleteVertexArrays(1, &DistortionMeshVAOs[eyeNum]); + } DistortionMeshVAOs[eyeNum] = 0; diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h index 9189ae6..1017c6e 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionRenderer.h @@ -77,10 +77,7 @@ protected: void ApplyBool(GLenum Name, GLint Value, GLint index = -1); public: - GLint GlMajorVersion; - GLint GlMinorVersion; - bool SupportsVao; - bool SupportsDrawBuffers; + GLVersionAndExtensions GLVersionInfo; GLint Viewport[4]; GLfloat ClearColor[4]; diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h index 5c68c50..76e8c81 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_DistortionShaders.h @@ -30,6 +30,7 @@ namespace OVR { namespace CAPI { namespace GL { "#define _VS_OUT varying\n" "#define _FS_IN varying\n" "#define _TEXTURELOD texture2DLod\n" + "#define _TEXTURE texture2D\n" "#define _FRAGCOLOR gl_FragColor\n"; static const char glsl3Prefix[] = @@ -39,6 +40,7 @@ namespace OVR { namespace CAPI { namespace GL { "#define _VS_OUT out\n" "#define _FS_IN in\n" "#define _TEXTURELOD textureLod\n" + "#define _TEXTURE texture\n" "#define _FRAGCOLOR FragColor\n"; static const char SimpleQuad_vs[] = @@ -127,7 +129,7 @@ namespace OVR { namespace CAPI { namespace GL { "void main()\n" "{\n" - " _FRAGCOLOR = oColor * texture2D(Texture0, oTexCoord);\n" + " _FRAGCOLOR = oColor * _TEXTURE(Texture0, oTexCoord);\n" "}\n"; // The following is copied from the generated D3D SimpleTexturedQuad_ps_refl.h file, with D3D_NS renamed to GL. diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp index 6c0106d..f024ac5 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.cpp @@ -232,9 +232,6 @@ Texture* LoadTextureTga(RenderParams& rParams, int samplerMode, const uint8_t* p HSWDisplay::HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState) : OVR::CAPI::HSWDisplay(api, hmd, renderState) , RenderParams() - , GLMajorVersion(0) - , GLMinorVersion(0) - , SupportsVao(false) , FrameBuffer(0) , pTexture() , pShaderSet() @@ -276,10 +273,8 @@ bool HSWDisplay::Initialize(const ovrRenderAPIConfig* apiConfig) if (config->OGL.Win) RenderParams.Win= config->OGL.Win; if (!RenderParams.Win) - { - int unused; RenderParams.Win = glXGetCurrentDrawable(); - } + if (!RenderParams.Win) { OVR_DEBUG_LOG(("XGetInputFocus failed.")); @@ -332,17 +327,14 @@ void HSWDisplay::UnloadGraphics() if(VAO) { #ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { - glDeleteVertexArrays(1, &VAO); - } - else - { - glDeleteVertexArraysAPPLE(1, &VAO); - } - #else + if(GLVersionInfo.WholeVersion >= 302) + glDeleteVertexArrays(1, &VAO); + else + glDeleteVertexArraysAPPLE(1, &VAO); + #else glDeleteVertexArrays(1, &VAO); #endif + VAO = 0; VAOInitialized = false; } @@ -352,31 +344,10 @@ void HSWDisplay::UnloadGraphics() void HSWDisplay::LoadGraphics() { - const char* glVersionString = (const char*)glGetString(GL_VERSION); - - OVR_ASSERT(glVersionString); - if (glVersionString) - { - int fieldCount = sscanf(glVersionString, isdigit(*glVersionString) ? "%d.%d" : "%*[^0-9]%d.%d", &GLMajorVersion, &GLMinorVersion); // Skip all leading non-digits before reading %d. Example glVersionStrings: "1.5 ATI-1.4.18", "OpenGL ES-CM 3.2" - - if(fieldCount != 2) - { - static_assert(sizeof(GLMajorVersion) == sizeof(GLint), "type mis-match"); - glGetIntegerv(GL_MAJOR_VERSION, &GLMajorVersion); - } - } - - // SupportsVao - if(GLMajorVersion >= 3) - SupportsVao = true; - else - { - const char* extensions = (const char*)glGetString(GL_EXTENSIONS); - SupportsVao = (strstr(extensions, "GL_ARB_vertex_array_object") || strstr(extensions, "GL_APPLE_vertex_array_object")); - } - if (FrameBuffer == 0) + { glGenFramebuffers(1, &FrameBuffer); + } if (!pTexture) // To do: Add support for .dds files, which would be significantly smaller than the size of the tga. { @@ -385,12 +356,14 @@ void HSWDisplay::LoadGraphics() pTexture = *LoadTextureTga(RenderParams, Sample_Linear | Sample_Clamp, TextureData, (int)textureSize, 255); } - if(!pShaderSet) + if (!pShaderSet) + { pShaderSet = *new ShaderSet(); + } if(!pVertexShader) { - OVR::String strShader((GLMajorVersion >= 3) ? glsl3Prefix : glsl2Prefix); + OVR::String strShader((GLVersionInfo.MajorVersion >= 3) ? glsl3Prefix : glsl2Prefix); strShader += SimpleTexturedQuad_vs; pVertexShader = *new VertexShader(&RenderParams, const_cast<char*>(strShader.ToCStr()), strShader.GetLength(), SimpleTexturedQuad_vs_refl, OVR_ARRAY_COUNT(SimpleTexturedQuad_vs_refl)); @@ -399,7 +372,7 @@ void HSWDisplay::LoadGraphics() if(!pFragmentShader) { - OVR::String strShader((GLMajorVersion >= 3) ? glsl3Prefix : glsl2Prefix); + OVR::String strShader((GLVersionInfo.MajorVersion >= 3) ? glsl3Prefix : glsl2Prefix); strShader += SimpleTexturedQuad_ps; pFragmentShader = *new FragmentShader(&RenderParams, const_cast<char*>(strShader.ToCStr()), strShader.GetLength(), SimpleTexturedQuad_ps_refl, OVR_ARRAY_COUNT(SimpleTexturedQuad_ps_refl)); @@ -432,18 +405,15 @@ void HSWDisplay::LoadGraphics() } // We don't generate the vertex arrays here - if(!VAO && SupportsVao) + if (!VAO && GLVersionInfo.SupportsVAO) { OVR_ASSERT(!VAOInitialized); + #ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { - glGenVertexArrays(1, &VAO); - } - else - { - glGenVertexArraysAPPLE(1, &VAO); - } + if(GLVersionInfo.WholeVersion >= 302) + glGenVertexArrays(1, &VAO); + else + glGenVertexArraysAPPLE(1, &VAO); #else glGenVertexArrays(1, &VAO); #endif @@ -455,9 +425,13 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) { if(RenderEnabled && eyeTexture) { - // Hack - Clear previous errors. + // glGetError clears any previous error state. We call it here in order to start with + // a clean slate, as we are asserting below that our calls do not generate errors. glGetError(); + if(GLVersionInfo.MajorVersion == 0) // If not yet initialized... + GetGLVersionAndExtensions(GLVersionInfo); + // We need to render to the eyeTexture with the texture viewport. // Setup rendering to the texture. ovrGLTexture* eyeTextureGL = const_cast<ovrGLTexture*>(reinterpret_cast<const ovrGLTexture*>(eyeTexture)); @@ -468,15 +442,19 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) // Save state // To do: Converge this with the state setting/restoring functionality present in the distortion renderer. + // Consider usage of the EXT_direct_state_access (http://www.opengl.org/registry/specs/EXT/direct_state_access.txt) extension. // Note that the glGet functions below will block until command buffer has completed. // glPushAttrib is deprecated, so we use glGet* to save/restore fixed-function settings. // https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glGet.xml // - GLint RenderModeSaved; - glGetIntegerv(GL_RENDER_MODE, &RenderModeSaved); - OVR_ASSERT(glGetError() == 0); - OVR_ASSERT(RenderModeSaved == GL_RENDER); // Make sure it's not GL_SELECT or GL_FEEDBACK. - + GLint RenderModeSaved = 0; + if(!GLVersionInfo.IsCoreProfile) // glGetIntegerv can fail if an OpenGL 3.x+ core profile is enabled due to GL_RENDER_MODE being no longer supported. + { + glGetIntegerv(GL_RENDER_MODE, &RenderModeSaved); + OVR_ASSERT(glGetError() == 0); + OVR_ASSERT(RenderModeSaved == GL_RENDER); // Make sure it's not GL_SELECT or GL_FEEDBACK. + } + GLint FrameBufferBindingSaved; // OpenGL renamed GL_FRAMEBUFFER_BINDING to GL_DRAW_FRAMEBUFFER_BINDING and adds GL_READ_FRAMEBUFFER_BINDING. glGetIntegerv(GL_FRAMEBUFFER_BINDING, &FrameBufferBindingSaved); OVR_ASSERT(glGetError() == 0); @@ -494,8 +472,8 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) OVR_ASSERT(glGetError() == 0); GLdouble DepthRangeSaved[2]; - #if defined(OVR_OS_MAC) - // Using glDepthRange as a conditional will always evaluate to true on Mac. + #if defined(OVR_OS_MAC) || defined(OVR_OS_LINUX) + // Using glDepthRange as a conditional will always evaluate to true on Mac/Linux. glGetDoublev(GL_DEPTH_RANGE, DepthRangeSaved); #else GLfloat DepthRangefSaved[2]; @@ -547,7 +525,7 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) OVR_ASSERT(glGetError() == 0); GLint SampleMaskSaved = 0; - if(((GLMajorVersion * 100) + GLMinorVersion) >= 302) // OpenGL 3.2 or later + if (GLVersionInfo.WholeVersion >= 302) // OpenGL 3.2 or later { glGetIntegerv(GL_SAMPLE_MASK, &SampleMaskSaved); OVR_ASSERT(glGetError() == 0); @@ -572,37 +550,46 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glGetIntegerv(GL_TEXTURE_BINDING_2D, &TextureBindingSaved); OVR_ASSERT(glGetError() == 0); - // https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glVertexAttribPointer.xml + GLint VertexArrayBindingSaved = 0; + if (GLVersionInfo.SupportsVAO) + glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &VertexArrayBindingSaved); + + // If the core profile is enabled then we can't get the vertex attributes unless there is + // an active VAO. Otherwise there can be an error with some OpenGL implementations (notably Apple's). + // If the core profile is not enabled then pre-OpenGL 3.0 behavior is possible in which the + // application may not be using VAOs and thus there may be active vertex attributes. GLint VertexAttribEnabledSaved[kSavedVertexAttribCount]; GLint VertexAttribSizeSaved[kSavedVertexAttribCount]; GLint VertexAttribTypeSaved[kSavedVertexAttribCount]; GLint VertexAttribNormalizedSaved[kSavedVertexAttribCount]; GLint VertexAttribStrideSaved[kSavedVertexAttribCount]; GLvoid* VertexAttribPointerSaved[kSavedVertexAttribCount]; - for(GLuint i = 0; i < kSavedVertexAttribCount; i++) + + if(VertexArrayBindingSaved || !GLVersionInfo.IsCoreProfile) { - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &VertexAttribEnabledSaved[i]); + for(GLuint i = 0; i < kSavedVertexAttribCount; i++) + { + // https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glVertexAttribPointer.xml + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &VertexAttribEnabledSaved[i]); - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &VertexAttribSizeSaved[i]); - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &VertexAttribTypeSaved[i]); - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &VertexAttribNormalizedSaved[i]); - glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &VertexAttribStrideSaved[i]); - glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &VertexAttribPointerSaved[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &VertexAttribSizeSaved[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &VertexAttribTypeSaved[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &VertexAttribNormalizedSaved[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &VertexAttribStrideSaved[i]); + glGetVertexAttribPointerv(i, GL_VERTEX_ATTRIB_ARRAY_POINTER, &VertexAttribPointerSaved[i]); - OVR_ASSERT(glGetError() == 0); + OVR_ASSERT(glGetError() == 0); + } } - - GLint VertexArrayBindingSaved = 0; - if (SupportsVao) - glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &VertexArrayBindingSaved); - // // End of save state // Load the graphics if not loaded already. if (!pTexture) + { LoadGraphics(); + } // Calculate ortho projection. GetOrthoProjection(RenderState, OrthoProjection); @@ -628,10 +615,10 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) // Set fixed-function render states glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); OVR_ASSERT(glGetError() == 0); - #if defined(OVR_OS_MAC) // On Mac we are directly using OpenGL functions instead of function pointers. + #if defined(OVR_OS_MAC) || defined(OVR_OS_LINUX) // On Mac/Linux we are directly using OpenGL functions instead of function pointers. glDepthRange(0.0, 1.0); #else - if(glDepthRange) // If we can use the double version (glDepthRangef may not be available)... + if(glDepthRange) // If we can use the double version (glDepthRangef isn't available with older OpenGL, glDepthRange isn't available with OpenGL ES)... glDepthRange(0.0, 1.0); else glDepthRangef(0.f, 1.f); @@ -645,8 +632,10 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glDisable(GL_DITHER); glDisable(GL_RASTERIZER_DISCARD); glDisable(GL_SCISSOR_TEST); - if(((GLMajorVersion * 100) + GLMinorVersion) >= 302) // OpenGL 3.2 or later + if (GLVersionInfo.WholeVersion >= 302) // OpenGL 3.2 or later + { glDisable(GL_SAMPLE_MASK); + } glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); OVR_ASSERT(glGetError() == 0); @@ -668,18 +657,15 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) // To do: We must add support for vertext array objects (VAOs) here. When using an OpenGL 3.2+ core profile, // the application is required to use vertex array objects and glVertexAttribPointer will fail otherwise. - if(SupportsVao) + if (GLVersionInfo.SupportsVAO) { OVR_ASSERT(VAO != 0); + #ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { - glBindVertexArray(VAO); - } - else - { - glBindVertexArrayAPPLE(VAO); - } + if(GLVersionInfo.WholeVersion >= 302) + glBindVertexArray(VAO); + else + glBindVertexArrayAPPLE(VAO); #else glBindVertexArray(VAO); #endif @@ -718,19 +704,15 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); OVR_ASSERT(glGetError() == 0); - if(SupportsVao) + if (GLVersionInfo.SupportsVAO) { VAOInitialized = true; #ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { - glBindVertexArray(0); - } - else - { + if(GLVersionInfo.WholeVersion >= 302) + glBindVertexArray(0); + else glBindVertexArrayAPPLE(0); - } #else glBindVertexArray(0); #endif @@ -740,31 +722,21 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) // We restore the state in the reverse order that we saved it. // To do: Make the code below avoid changes that are effectively no-ops. // - if (SupportsVao) + if (GLVersionInfo.SupportsVAO) { -#ifdef OVR_OS_MAC - if(GLMajorVersion >= 3) - { + #ifdef OVR_OS_MAC + if(GLVersionInfo.WholeVersion >= 302) + glBindVertexArray(VertexArrayBindingSaved); + else + glBindVertexArrayAPPLE(VertexArrayBindingSaved); + #else glBindVertexArray(VertexArrayBindingSaved); - } - else - { - glBindVertexArrayAPPLE(VertexArrayBindingSaved); - } -#else - glBindVertexArray(VertexArrayBindingSaved); -#endif + #endif } - for (GLuint i = 0; i < kSavedVertexAttribCount; i++) + if(VertexArrayBindingSaved || !GLVersionInfo.IsCoreProfile) // If the OpenGL version is older or in core profile compatibility mode, or if there's a VAO currently installed... { - // We have a problem here: if the GL context was initialized with a core profile version 3.x or later, calls to glVertexAttribPointer can fail when there is no Vertex Array Object - // in place. That case is possible here, and we don't have an easy means to detect that a core profile was specified and thus that the glVertexAttribPointer call below could fail. - // Our current solution is to call glVertexAttribPointer only if vertex array objects are not supported. We cannot simply decide based on whether the given vertex attrib was enabled - // or if there was a vertex array object installed. With our solution below a problem can occur when using OpenGL 3.x+ which supports VAOs, the user has vertex attrib pointers installed, - // the currently installed VAO is 0, and the user is somehow dependent on us returning to the user with those vertex attrib pointers reinstalled. - - if (!SupportsVao || (VertexArrayBindingSaved != 0)) // If the OpenGL version is older or in core profile compatibility mode, or if there's a VAO currently installed... + for (GLuint i = 0; i < kSavedVertexAttribCount; i++) { glVertexAttribPointer(i, VertexAttribSizeSaved[i], VertexAttribTypeSaved[i], (GLboolean)VertexAttribNormalizedSaved[i], VertexAttribStrideSaved[i], VertexAttribPointerSaved[i]); @@ -776,14 +748,14 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) OVR_ASSERT(glGetError() == 0); } } - + glBindTexture(GL_TEXTURE_2D, TextureBindingSaved); glActiveTexture(ActiveTextureSaved); glUseProgram(ProgramSaved); glBindBuffer(GL_ARRAY_BUFFER, ArrayBufferBindingSaved); glColorMask((GLboolean)ColorWriteMaskSaved[0], (GLboolean)ColorWriteMaskSaved[1], (GLboolean)ColorWriteMaskSaved[2], (GLboolean)ColorWriteMaskSaved[3]); - if(((GLMajorVersion * 100) + GLMinorVersion) >= 302) // OpenGL 3.2 or later + if (GLVersionInfo.WholeVersion >= 302) // OpenGL 3.2 or later { if(SampleMaskSaved) glEnable(GL_SAMPLE_MASK); @@ -806,7 +778,8 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) else glDisable(GL_DITHER); - glBlendFunc(BlendSrcRGBSaved, BlendDstRGBSaved); // What about BlendSrcAlphaSaved / BlendDstAlphaSaved? + // With OpenGL 4.0+, we may need to be aware of glBlendFuncSeparatei. + glBlendFuncSeparate(BlendSrcRGBSaved, BlendDstRGBSaved, BlendSrcAlphaSaved, BlendDstAlphaSaved); if(BlendSaved) glEnable(GL_BLEND); @@ -826,7 +799,7 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glDisable(GL_DEPTH_TEST); glDepthMask(DepthWriteMaskSaved ? GL_TRUE : GL_FALSE); - #if defined(OVR_OS_MAC) // On Mac we are directly using OpenGL functions instead of function pointers. + #if defined(OVR_OS_MAC) || defined(OVR_OS_LINUX) // On Mac/Linux we are directly using OpenGL functions instead of function pointers. glDepthRange(DepthRangeSaved[0], DepthRangeSaved[1]); #else if(glDepthRange) // If we can use the double version (glDepthRangef may not be available)... @@ -839,7 +812,9 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) glViewport(ViewportSaved[0], ViewportSaved[1], ViewportSaved[2], ViewportSaved[3]); glBindTexture(GL_TEXTURE_2D, TextureBinding2DSaved); glBindFramebuffer(GL_FRAMEBUFFER, FrameBufferBindingSaved); - //glRenderMode(RenderModeSaved); + + if(!GLVersionInfo.IsCoreProfile) + glRenderMode(RenderModeSaved); OVR_ASSERT(glGetError() == 0); // @@ -848,12 +823,4 @@ void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture) } - }}} // namespace OVR::CAPI::GL - - - - - - - diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h index 3517157..4b110d5 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_HSWDisplay.h @@ -55,9 +55,7 @@ namespace OVR { namespace CAPI { namespace GL { void LoadGraphics(); OVR::CAPI::GL::RenderParams RenderParams; - int GLMajorVersion; // Derived from glGetString(GL_VERSION). To consider: Move this into GL::RenderParams. - int GLMinorVersion; // - bool SupportsVao; // True if Vertex Array Objects are supported by the OpenGL version. + GLVersionAndExtensions GLVersionInfo; GLuint FrameBuffer; // This is a container for a texture, depth buffer, stencil buffer to be rendered to. To consider: Make a wrapper class, like the OculusWorldDemo RBuffer class. Ptr<OVR::CAPI::GL::Texture> pTexture; Ptr<OVR::CAPI::GL::ShaderSet> pShaderSet; diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp index 22482d8..ed9e654 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.cpp @@ -28,7 +28,6 @@ limitations under the License. namespace OVR { namespace CAPI { namespace GL { - // GL Hooks for non-Mac. #if !defined(OVR_OS_MAC) @@ -78,6 +77,7 @@ PFNGLENABLEIPROC glEnablei; PFNGLDISABLEIPROC glDisablei; PFNGLCOLORMASKIPROC glColorMaski; PFNGLGETINTEGERI_VPROC glGetIntegeri_v; +PFNGLGETSTRINGIPROC glGetStringi; PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; PFNGLDELETESHADERPROC glDeleteShader; @@ -124,7 +124,7 @@ PFNGLUNIFORM1FVPROC glUniform1fv; PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; PFNGLBINDVERTEXARRAYPROC glBindVertexArray; -PFNGLFEEDBACKBUFFERPROC glFeedbackBuffer; +PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate; #if defined(OVR_OS_WIN32) @@ -191,6 +191,7 @@ void InitGLExtensions() glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) GetFunction("glXSwapIntervalEXT"); #endif + glGetStringi = (PFNGLGETSTRINGIPROC) GetFunction("glGetStringi"); glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) GetFunction("glGenFramebuffersEXT"); glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) GetFunction("glDeleteFramebuffersEXT"); glEnablei = (PFNGLENABLEIPROC) GetFunction("glEnableIndexedEXT"); @@ -242,7 +243,7 @@ void InitGLExtensions() glDetachShader = (PFNGLDETACHSHADERPROC) GetFunction("glDetachShader"); glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) GetFunction("glBindAttribLocation"); glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) GetFunction("glGetAttribLocation"); - glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC) GetFunction("glFeedbackBuffer"); + glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) GetFunction("glBlendFuncSeparate"); } #endif @@ -499,7 +500,7 @@ void ShaderBase::InitUniforms(const Uniform* refl, size_t reflSize) UniformData = (unsigned char*)OVR_ALLOC(UniformsSize); } -Texture::Texture(RenderParams* rp, int w, int h) : IsUserAllocated(true), pParams(rp), TexId(0), Width(w), Height(h) +Texture::Texture(RenderParams* rp, int w, int h) : IsUserAllocated(false), pParams(rp), TexId(0), Width(w), Height(h) { if (w && h) glGenTextures(1, &TexId); @@ -573,6 +574,160 @@ void Texture::UpdatePlaceholderTexture(GLuint texId, const Sizei& textureSize) } -}}} +//// GLVersion + +void GLVersionAndExtensions::ParseGLVersion() +{ + const char* version = (const char*)glGetString(GL_VERSION); + int fields = 0, major = 0, minor = 0; + bool isGLES = false; + + OVR_ASSERT(version); + if (version) + { + OVR_DEBUG_LOG(("GL_VERSION: %s", (const char*)version)); + + // Skip all leading non-digits before reading %d. + // Example GL_VERSION strings: + // "1.5 ATI-1.4.18" + // "OpenGL ES-CM 3.2" + OVR_DISABLE_MSVC_WARNING(4996) // "scanf may be unsafe" + fields = sscanf(version, isdigit(*version) ? "%d.%d" : "%*[^0-9]%d.%d", &major, &minor); + isGLES = (strstr(version, "OpenGL ES") != NULL); + OVR_RESTORE_MSVC_WARNING() + } + else + { + LogText("Warning: GL_VERSION was NULL\n"); + } + + // If two fields were not found, + if (fields != 2) + { + static_assert(sizeof(major) == sizeof(GLint), "type mis-match"); + + glGetIntegerv(GL_MAJOR_VERSION, &major); + glGetIntegerv(GL_MINOR_VERSION, &minor); + } + + // Write version data + MajorVersion = major; + MinorVersion = minor; + WholeVersion = (major * 100) + minor; + IsGLES = isGLES; + IsCoreProfile = (MajorVersion >= 3); // Until we get a better way to detect core profiles, we err on the conservative side and set to true if the version is >= 3. +} + + +bool GLVersionAndExtensions::HasGLExtension(const char* searchKey) const +{ + if(Extensions && Extensions[0]) // If we have an extension string to search for individual extensions... + { + const int searchKeyLen = (int)strlen(searchKey); + const char* p = Extensions; + + for (;;) + { + p = strstr(p, searchKey); + + // If not found, + if (p == NULL) + { + break; + } + + // Only match full string + if ((p == Extensions || p[-1] == ' ') && + (p[searchKeyLen] == '\0' || p[searchKeyLen] == ' ')) + { + return true; + } + + // Skip ahead + p += searchKeyLen; + } + } + else + { + if(MajorVersion >= 3) // If glGetIntegerv(GL_NUM_EXTENSIONS, ...) is supported... + { + GLint extensionCount = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); + GLenum err = glGetError(); + + if(err == 0) + { + for(GLint i = 0; i != extensionCount; ++i) + { + const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, (GLuint)i); + + if(extension) // glGetStringi returns NULL upon error. + { + if(strcmp(extension, searchKey) == 0) + return true; + } + else + break; + } + } + } + } + + return false; +} + +void GLVersionAndExtensions::ParseGLExtensions() +{ + if(MajorVersion >= 3) + { + // Set to empty because we need to use glGetStringi to read extensions on recent OpenGL. + Extensions = ""; + } + else + { + const char* extensions = (const char*)glGetString(GL_EXTENSIONS); + + OVR_ASSERT(extensions); + if (!extensions) + { + extensions = ""; // Note: glGetString() can return null + LogText("Warning: GL_EXTENSIONS was NULL\n"); + } + else + { + // Cannot print this to debug log: It's too long! + //OVR_DEBUG_LOG(("GL_EXTENSIONS: %s", (const char*)extensions)); + } + + Extensions = extensions; + } + + // To do: revise the code below to loop through calls to glGetStringi(GL_EXTENSIONS, ...) so that all extensions below + // can be searched with a single pass over the extensions instead of a full loop per HasGLExtensionCall. + + if (MajorVersion >= 3) + { + SupportsVAO = true; + } + else + { + SupportsVAO = + HasGLExtension("GL_ARB_vertex_array_object") || + HasGLExtension("GL_APPLE_vertex_array_object"); + } + + SupportsDrawBuffers = HasGLExtension("GL_EXT_draw_buffers2"); + + // Add more extension checks here... +} + +void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo) +{ + versionInfo.ParseGLVersion(); + // GL Version must be parsed before parsing extensions: + versionInfo.ParseGLExtensions(); + // To consider: Call to glGetStringi(GL_SHADING_LANGUAGE_VERSION, ...) check/validate the GLSL support. +} +}}} // namespace OVR::CAPI::GL diff --git a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h index bc7c8ab..aa6a26b 100644 --- a/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h +++ b/LibOVR/Src/CAPI/GL/CAPI_GL_Util.h @@ -58,6 +58,7 @@ limitations under the License. namespace OVR { namespace CAPI { namespace GL { + // GL extension Hooks for Non-Mac. #if !defined(OVR_OS_MAC) @@ -69,7 +70,8 @@ typedef void (__stdcall *PFNGLENABLEPROC) (GLenum); typedef void (__stdcall *PFNGLDISABLEPROC) (GLenum); typedef void (__stdcall *PFNGLGETFLOATVPROC) (GLenum, GLfloat*); typedef const GLubyte * (__stdcall *PFNGLGETSTRINGPROC) (GLenum); -typedef void (__stdcall *PFNGLGETINTEGERVPROC) (GLenum, GLint*); +typedef const GLubyte * (__stdcall *PFNGLGETSTRINGIPROC) (GLenum, GLuint); +typedef void(__stdcall *PFNGLGETINTEGERVPROC) (GLenum, GLint*); typedef void (__stdcall *PFNGLGETDOUBLEVPROC) (GLenum, GLdouble*); typedef PROC (__stdcall *PFNWGLGETPROCADDRESS) (LPCSTR); typedef void (__stdcall *PFNGLFLUSHPROC) (); @@ -91,7 +93,6 @@ typedef void (__stdcall *PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, G typedef void (__stdcall *PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); typedef void (__stdcall *PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor); typedef void (__stdcall *PFNGLFRONTFACEPROC) (GLenum mode); -typedef void (__stdcall *PFNGLFEEDBACKBUFFERPROC) (GLsizei size, GLenum type, GLfloat *buffer); typedef GLint (__stdcall *PFNGLRENDERMODEPROC) (GLenum mode); typedef void (__stdcall *PFNGLPOLYGONMODEPROC) (GLenum face, GLenum mode); @@ -138,6 +139,7 @@ extern PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT; #endif // defined(OVR_OS_WIN32) +extern PFNGLGETSTRINGIPROC glGetStringi; extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; extern PFNGLDELETESHADERPROC glDeleteShader; @@ -183,7 +185,7 @@ extern PFNGLUNIFORM1FVPROC glUniform1fv; extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; -extern PFNGLFEEDBACKBUFFERPROC glFeedbackBuffer; +extern PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate; extern void InitGLExtensions(); @@ -527,6 +529,7 @@ public: OVR_UNUSED(size); success = Compile((const char*) s); OVR_ASSERT(success); + OVR_UNUSED(success); InitUniforms(refl, reflSize); } ~ShaderImpl() @@ -571,7 +574,56 @@ typedef ShaderImpl<Shader_Vertex, GL_VERTEX_SHADER> VertexShader; typedef ShaderImpl<Shader_Fragment, GL_FRAGMENT_SHADER> FragmentShader; -}}} +//// GLVersionAndExtensions +// +// FIXME: CODE DUPLICATION WARNING +// Right now we have this same code in CommonSrc and in CAPI::GL. +// At some point we need to consolidate these, in Kernel or Util. +// Be sure to update both locations for now! +// +// This class needs to be initialized at runtime with GetGLVersionAndExtensions, +// after an OpenGL context has been created. It must be re-initialized any time +// a new OpenGL context is created, as the new context may differ in version or +// supported functionality. +struct GLVersionAndExtensions +{ + // Version information + int MajorVersion; // Best guess at major version + int MinorVersion; // Best guess at minor version + int WholeVersion; // Equals ((MajorVersion * 100) + MinorVersion). Example usage: if(glv.WholeVersion >= 302) // If OpenGL v3.02+ ... + bool IsGLES; // Open GL ES? + bool IsCoreProfile; // Is the current OpenGL context a core profile context? Its trueness may be a false positive but will never be a false negative. + + // Extension information + bool SupportsVAO; // Supports Vertex Array Objects? + bool SupportsDrawBuffers; // Supports Draw Buffers? + const char* Extensions; // Other extensions string (will not be null) + + GLVersionAndExtensions() + : MajorVersion(0), + MinorVersion(0), + WholeVersion(0), + IsGLES(false), + IsCoreProfile(false), + SupportsDrawBuffers(false), + SupportsVAO(false), + Extensions("") + { + } + + bool HasGLExtension(const char* searchKey) const; + +protected: + friend void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo); + + void ParseGLVersion(); + void ParseGLExtensions(); +}; + +void GetGLVersionAndExtensions(GLVersionAndExtensions& versionInfo); + + +}}} // namespace OVR::CAPI::GL #endif // INC_OVR_CAPI_GL_Util_h diff --git a/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps.h b/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps.h index 9dfd8f6..c18f365 100644 --- a/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps.h +++ b/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps.h @@ -2,14 +2,14 @@ #define DISTORTIONCHROMA_PS_H static const unsigned char DistortionChroma_ps[] = { - 0x44, 0x58, 0x42, 0x43, 0x2b, 0x0d, 0x42, 0xef, 0x6d, 0xea, 0x8e, 0x3c, - 0xe8, 0x90, 0x79, 0x04, 0xfe, 0x42, 0xcf, 0xba, 0x01, 0x00, 0x00, 0x00, - 0x10, 0x06, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0xac, 0x01, 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x9c, 0x02, 0x00, 0x00, - 0x94, 0x05, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x70, 0x01, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0x8b, 0xb5, 0x62, 0xd4, 0xa4, 0xf3, 0xee, 0xa6, + 0x11, 0x95, 0x03, 0x4f, 0xaa, 0x21, 0xa6, 0x42, 0x01, 0x00, 0x00, 0x00, + 0x74, 0x0b, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0xbc, 0x01, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0xac, 0x02, 0x00, 0x00, + 0xf8, 0x0a, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x80, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, - 0x3c, 0x01, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x4c, 0x01, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, @@ -26,109 +26,224 @@ static const unsigned char DistortionChroma_ps[] = { 0xb7, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2c, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x1c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x76, 0x65, 0x72, 0x64, 0x72, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x76, - 0x52, 0x54, 0x53, 0x69, 0x7a, 0x65, 0x00, 0xab, 0x01, 0x00, 0x03, 0x00, - 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x01, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x76, 0x65, 0x72, 0x64, 0x72, 0x69, 0x76, 0x65, 0x53, 0x63, 0x61, - 0x6c, 0x65, 0x73, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, - 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, - 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, - 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, - 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, - 0x9c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x03, 0x00, 0x00, - 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, - 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, - 0x92, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, - 0x92, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, - 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, - 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, - 0x52, 0x44, 0x00, 0xab, 0x4f, 0x53, 0x47, 0x4e, 0x44, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0xab, 0xab, 0x53, 0x48, 0x44, 0x52, - 0xf0, 0x02, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, - 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x00, 0x60, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, - 0x00, 0x70, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, - 0x64, 0x20, 0x00, 0x04, 0x32, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0x12, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0x62, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0xc2, 0x10, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x96, 0x15, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, + 0x6c, 0x65, 0x73, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x61, 0x44, 0x65, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x76, 0x65, 0x4d, 0x75, 0x6c, 0x74, + 0x00, 0xab, 0xab, 0xab, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, + 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, + 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, 0x2e, 0x33, 0x2e, 0x39, + 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, 0x34, 0x00, 0xab, 0xab, + 0x49, 0x53, 0x47, 0x4e, 0x9c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x03, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x06, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0c, 0x0c, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, + 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, 0x4f, 0x53, 0x47, 0x4e, + 0x44, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0xab, 0xab, + 0x53, 0x48, 0x44, 0x52, 0x44, 0x08, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, + 0x11, 0x02, 0x00, 0x00, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x03, + 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, + 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, + 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x55, 0x55, 0x00, 0x00, 0x64, 0x20, 0x00, 0x04, 0x32, 0x10, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, + 0x12, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, + 0x62, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, + 0x32, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, + 0xc2, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, + 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, + 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, + 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x96, 0x15, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, - 0xf2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, + 0xf2, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0xe6, 0x1a, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x0b, 0x62, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa6, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0x00, 0x04, 0x03, 0x1a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x0a, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x05, + 0x22, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1a, 0x10, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x08, 0x32, 0x00, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xa6, 0x8a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x06, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x42, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xa2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x08, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x56, 0x19, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xd6, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xf2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x86, 0x08, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x46, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, + 0xf2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0xe6, 0x0a, 0x10, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x22, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, + 0xd2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x09, 0x10, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x06, 0x09, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x42, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xf2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x86, 0x06, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x96, 0x19, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x46, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xf2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0x86, 0x08, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x46, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, + 0xf2, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0xe6, 0x0a, 0x10, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x22, 0x00, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, + 0xf2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe6, 0x0a, 0x10, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf2, 0x00, 0x10, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x66, 0x06, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x46, 0x1e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, + 0xf2, 0x00, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xe6, 0x1a, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xe6, 0x0a, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, - 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x08, 0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, - 0x3a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x08, - 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x46, 0x7e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, + 0x22, 0x00, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x06, 0x82, 0x00, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xa2, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa6, 0x0e, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x56, 0x19, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, + 0xf2, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0xd6, 0x05, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0c, 0xf2, 0x00, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x66, 0x06, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0xbf, + 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0xbf, 0x46, 0x1e, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x07, 0x72, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x46, 0x02, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x0b, 0x72, 0x00, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0xa6, 0x8a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf6, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x08, 0x72, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x46, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x80, - 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x20, 0x00, 0x09, - 0x72, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, + 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xe6, 0x0a, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, + 0x12, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x22, 0x00, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, + 0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x09, 0xd2, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x09, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x06, 0x09, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x09, 0xd2, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x09, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x09, 0x10, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x09, 0xd2, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x09, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x06, 0x09, 0x10, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x09, 0xd2, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x09, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x09, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x0a, 0xd2, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x40, 0x00, 0x00, 0xcd, 0xcc, 0x4c, 0x3e, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0xcc, 0x4c, 0x3e, 0xcd, 0xcc, 0x4c, 0x3e, 0x4b, 0x00, 0x00, 0x05, + 0x72, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x86, 0x03, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x05, + 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x22, 0x00, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x15, 0x00, 0x00, 0x01, 0x38, 0x00, 0x00, 0x07, 0xb2, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x08, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x06, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x04, 0x03, + 0x2a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x05, + 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, 0xc2, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2d, 0x00, 0x00, 0x07, 0xf2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x07, 0x72, 0x00, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x46, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x0b, + 0x72, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x56, 0x85, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x72, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x46, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, - 0x82, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x3f, 0x12, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x05, - 0x72, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x82, 0x20, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, - 0x15, 0x00, 0x00, 0x01, 0x36, 0x00, 0x00, 0x05, 0x72, 0x20, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x36, 0x00, 0x00, 0x05, 0x82, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x80, + 0x41, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x20, 0x00, 0x09, + 0x72, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x46, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x01, + 0x36, 0x00, 0x00, 0x05, 0x72, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x46, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x01, + 0x36, 0x00, 0x00, 0x05, 0x72, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x03, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, + 0x82, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x00, 0x05, 0x72, 0x20, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x82, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x3e, 0x00, 0x00, 0x01, - 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 diff --git a/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps.psh b/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps.psh index 9886fc3..b19332c 100644 --- a/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps.psh +++ b/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps.psh @@ -2,11 +2,44 @@ Texture2D Texture : register(t0); Texture2D LastTexture : register(t1);
SamplerState Linear : register(s0);
-float2 OverdriveInvRTSize;
float2 OverdriveScales;
+float AaDerivativeMult;
+
+// Fast approximate gamma to linear conversion when averaging colors
+float3 ToLinear(float3 inColor) { return inColor * inColor; }
+float3 ToGamma(float3 inColor) { return sqrt(inColor); }
+
+float3 ApplyHqAa(float3 inColor, float2 oTexCoord0, float2 oTexCoord1, float2 oTexCoord2)
+{
+ float2 uvDeriv = float2(ddx(oTexCoord1.x), ddy(oTexCoord1.y)) * AaDerivativeMult;
+
+ float ResultR = Texture.SampleLevel(Linear, oTexCoord0 + float2(-uvDeriv.x, 0), 0.0).r;
+ float ResultG = Texture.SampleLevel(Linear, oTexCoord1 + float2(-uvDeriv.x, 0), 0.0).g;
+ float ResultB = Texture.SampleLevel(Linear, oTexCoord2 + float2(-uvDeriv.x, 0), 0.0).b;
+ float3 newColor0 = ToLinear(float3(ResultR, ResultG, ResultB));
+
+ ResultR = Texture.SampleLevel(Linear, oTexCoord0 + float2(uvDeriv.x, 0), 0.0).r;
+ ResultG = Texture.SampleLevel(Linear, oTexCoord1 + float2(uvDeriv.x, 0), 0.0).g;
+ ResultB = Texture.SampleLevel(Linear, oTexCoord2 + float2(uvDeriv.x, 0), 0.0).b;
+ float3 newColor1 = ToLinear(float3(ResultR, ResultG, ResultB));
+
+ ResultR = Texture.SampleLevel(Linear, oTexCoord0 + float2(0, uvDeriv.y), 0.0).r;
+ ResultG = Texture.SampleLevel(Linear, oTexCoord1 + float2(0, uvDeriv.y), 0.0).g;
+ ResultB = Texture.SampleLevel(Linear, oTexCoord2 + float2(0, uvDeriv.y), 0.0).b;
+ float3 newColor2 = ToLinear(float3(ResultR, ResultG, ResultB));
+
+ ResultR = Texture.SampleLevel(Linear, oTexCoord0 + float2(0, -uvDeriv.y), 0.0).r;
+ ResultG = Texture.SampleLevel(Linear, oTexCoord1 + float2(0, -uvDeriv.y), 0.0).g;
+ ResultB = Texture.SampleLevel(Linear, oTexCoord2 + float2(0, -uvDeriv.y), 0.0).b;
+ float3 newColor3 = ToLinear(float3(ResultR, ResultG, ResultB));
+
+ float3 outColor = ToLinear(inColor) + newColor0 + newColor1 + newColor2 + newColor3;
+ outColor = ToGamma(outColor * 0.2);
+ return outColor;
+}
void main(in float4 oPosition : SV_Position,
- in float1 oColor : COLOR,
+ in float oColor : COLOR,
in float2 oTexCoord0 : TEXCOORD0,
in float2 oTexCoord1 : TEXCOORD1,
in float2 oTexCoord2 : TEXCOORD2,
@@ -16,15 +49,22 @@ void main(in float4 oPosition : SV_Position, float ResultR = Texture.SampleLevel(Linear, oTexCoord0, 0.0).r;
float ResultG = Texture.SampleLevel(Linear, oTexCoord1, 0.0).g;
float ResultB = Texture.SampleLevel(Linear, oTexCoord2, 0.0).b;
- float3 newColor = float3(ResultR * oColor, ResultG * oColor, ResultB * oColor);
+ float3 newColor = float3(ResultR, ResultG, ResultB);
+
+ // High quality anti-aliasing in distortion
+ if(AaDerivativeMult > 0)
+ {
+ newColor = ApplyHqAa(newColor, oTexCoord0, oTexCoord1, oTexCoord2);
+ }
+ newColor = newColor * oColor.xxx;
outColor0 = float4(newColor, 1.0);
outColor1 = outColor0;
-
+
// pixel luminance overdrive
- if(OverdriveInvRTSize.x > 0)
+ if(OverdriveScales.x > 0)
{
- float3 oldColor = LastTexture.SampleLevel(Linear, oPosition.xy * OverdriveInvRTSize.xy, 0.0).rgb;
+ float3 oldColor = LastTexture.Load(int3(oPosition.xy, 0)).rgb;
float3 adjustedScales;
adjustedScales.x = newColor.x > oldColor.x ? OverdriveScales.x : OverdriveScales.y;
diff --git a/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps_refl.h b/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps_refl.h index 1f09c5e..4c66392 100644 --- a/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps_refl.h +++ b/LibOVR/Src/CAPI/Shaders/DistortionChroma_ps_refl.h @@ -2,8 +2,8 @@ const OVR::CAPI::D3D_NS::ShaderBase::Uniform DistortionChroma_ps_refl[] = { - { "OverdriveInvRTSize", OVR::CAPI::D3D_NS::ShaderBase::VARTYPE_FLOAT, 0, 8 }, - { "OverdriveScales", OVR::CAPI::D3D_NS::ShaderBase::VARTYPE_FLOAT, 8, 8 }, + { "OverdriveScales", OVR::CAPI::D3D_NS::ShaderBase::VARTYPE_FLOAT, 0, 8 }, + { "AaDerivativeMult", OVR::CAPI::D3D_NS::ShaderBase::VARTYPE_FLOAT, 8, 4 }, }; #endif diff --git a/LibOVR/Src/CAPI/Shaders/DistortionChroma_vs.h b/LibOVR/Src/CAPI/Shaders/DistortionChroma_vs.h index aa5003f..72587eb 100644 --- a/LibOVR/Src/CAPI/Shaders/DistortionChroma_vs.h +++ b/LibOVR/Src/CAPI/Shaders/DistortionChroma_vs.h @@ -2,8 +2,8 @@ #define DISTORTIONCHROMA_VS_H static const unsigned char DistortionChroma_vs[] = { - 0x44, 0x58, 0x42, 0x43, 0x8e, 0x20, 0x97, 0xab, 0xce, 0xc8, 0x74, 0x3e, - 0xfe, 0xeb, 0x97, 0xa0, 0xe6, 0xca, 0x72, 0xa1, 0x01, 0x00, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0x0e, 0xfe, 0xef, 0x9e, 0xe4, 0xce, 0x0b, 0xf4, + 0xdc, 0xc4, 0xfc, 0x1d, 0x3a, 0xf6, 0x54, 0x11, 0x01, 0x00, 0x00, 0x00, 0x64, 0x04, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0xd8, 0x01, 0x00, 0x00, 0x7c, 0x02, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xfc, 0x00, 0x00, 0x00, @@ -26,8 +26,8 @@ static const unsigned char DistortionChroma_vs[] = { 0x56, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, - 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, - 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, 0x2e, 0x33, 0x2e, 0x39, + 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, 0x34, 0x00, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x98, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -87,7 +87,7 @@ static const unsigned char DistortionChroma_vs[] = { 0xa6, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/LibOVR/Src/CAPI/Shaders/DistortionTimewarpChroma_vs.h b/LibOVR/Src/CAPI/Shaders/DistortionTimewarpChroma_vs.h index 3344482..c8cd966 100644 --- a/LibOVR/Src/CAPI/Shaders/DistortionTimewarpChroma_vs.h +++ b/LibOVR/Src/CAPI/Shaders/DistortionTimewarpChroma_vs.h @@ -2,11 +2,11 @@ #define DISTORTIONTIMEWARPCHROMA_VS_H static const unsigned char DistortionTimewarpChroma_vs[] = { - 0x44, 0x58, 0x42, 0x43, 0x46, 0xb0, 0x5a, 0x1b, 0xfd, 0x8c, 0xdb, 0xa9, - 0x8d, 0x82, 0x83, 0x1f, 0xd6, 0x4f, 0x4a, 0x8f, 0x01, 0x00, 0x00, 0x00, - 0xac, 0x09, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x98, 0x01, 0x00, 0x00, 0x38, 0x02, 0x00, 0x00, 0xdc, 0x02, 0x00, 0x00, - 0x30, 0x09, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x5c, 0x01, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0x80, 0x9f, 0x5c, 0x4f, 0x89, 0x6f, 0x5a, 0xbf, + 0x65, 0xe8, 0x9a, 0x58, 0x95, 0xd7, 0x18, 0x18, 0x01, 0x00, 0x00, 0x00, + 0xb0, 0x09, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x9c, 0x01, 0x00, 0x00, 0x3c, 0x02, 0x00, 0x00, 0xe0, 0x02, 0x00, 0x00, + 0x34, 0x09, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x60, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x00, 0x01, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -34,181 +34,181 @@ static const unsigned char DistortionTimewarpChroma_vs[] = { 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, - 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, - 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, - 0x49, 0x53, 0x47, 0x4e, 0x98, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0f, 0x09, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x00, 0x00, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, - 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, - 0x4f, 0x52, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x4e, 0x9c, 0x00, 0x00, 0x00, + 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, 0x2e, + 0x33, 0x2e, 0x39, 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, 0x34, + 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x98, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x8f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, - 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, - 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, - 0x53, 0x48, 0x44, 0x52, 0x4c, 0x06, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, - 0x93, 0x01, 0x00, 0x00, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, - 0x32, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, - 0x92, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, - 0x32, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, - 0x32, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, - 0x32, 0x10, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, - 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x65, 0x00, 0x00, 0x03, 0x12, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x65, 0x00, 0x00, 0x03, 0x62, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x65, 0x00, 0x00, 0x03, 0x32, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x65, 0x00, 0x00, 0x03, 0xc2, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x68, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, - 0x32, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, 0xc2, 0x20, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x3f, - 0x36, 0x00, 0x00, 0x05, 0x12, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x06, - 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x80, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x06, - 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x80, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x06, - 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x42, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x80, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x06, - 0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x82, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x10, 0x80, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x09, - 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x1f, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, - 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, 0xc2, 0x00, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, - 0x11, 0x00, 0x00, 0x07, 0x42, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x32, 0x00, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x46, 0x80, 0x20, 0x80, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, - 0x12, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x0a, 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x32, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x16, 0x85, 0x20, 0x80, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x16, 0x85, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, - 0x22, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x0a, 0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x56, 0x84, 0x20, 0x80, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x56, 0x84, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, - 0x42, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x0a, 0x42, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x92, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x56, 0x81, 0x20, 0x80, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x56, 0x81, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, - 0x82, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x0a, 0x82, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x46, 0x0f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, - 0x42, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x46, 0x0f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x07, 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x96, 0x05, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0xa6, 0x0a, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0b, 0x62, 0x20, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x06, 0x81, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa6, 0x8b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x50, 0x4f, 0x53, 0x49, + 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, + 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x4e, + 0x9c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x00, 0x00, + 0x92, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, + 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, + 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, + 0x52, 0x44, 0x00, 0xab, 0x53, 0x48, 0x44, 0x52, 0x4c, 0x06, 0x00, 0x00, + 0x40, 0x00, 0x01, 0x00, 0x93, 0x01, 0x00, 0x00, 0x59, 0x00, 0x00, 0x04, + 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5f, 0x00, 0x00, 0x03, 0x92, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x04, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x12, 0x20, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x62, 0x20, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x32, 0x20, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xc2, 0x20, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x32, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, + 0xc2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x00, 0x05, 0x12, 0x20, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x06, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x06, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x06, 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x42, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x06, 0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x82, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x3a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x09, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf6, 0x1f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x46, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, + 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, 0xc2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, - 0x00, 0x00, 0x80, 0x3f, 0x11, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x46, 0x0f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x80, 0x3f, 0x11, 0x00, 0x00, 0x07, 0x42, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x32, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x80, 0x20, 0x80, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x46, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x0a, 0x12, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x12, 0x00, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x32, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x16, 0x85, 0x20, 0x80, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x16, 0x85, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x0a, 0x22, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x22, 0x00, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x52, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x56, 0x84, 0x20, 0x80, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x56, 0x84, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x0a, 0x42, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x42, 0x00, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x92, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x56, 0x81, 0x20, 0x80, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x56, 0x81, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x0a, 0x82, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x82, 0x00, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x3a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x46, 0x0f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x46, 0x0f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x07, 0x42, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x46, 0x0e, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x07, 0x32, 0x00, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0b, - 0x32, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x46, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe6, 0x8a, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x96, 0x05, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xa6, 0x0a, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0b, + 0x62, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa6, 0x8b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x32, 0x00, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, 0xc2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x11, 0x00, 0x00, 0x07, - 0x42, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x07, 0x82, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x46, 0x0e, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, + 0x12, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x46, 0x0f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x46, 0x0e, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x07, - 0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x0a, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x0b, 0xc2, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x06, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x84, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x8e, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, - 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x00, 0x10, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x0b, 0x32, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x46, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x80, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x8a, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, + 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, 0xc2, 0x00, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, + 0x11, 0x00, 0x00, 0x07, 0x42, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x46, 0x0e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, 0x82, 0x00, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, + 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x07, 0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe6, 0x0a, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0b, 0xc2, 0x20, 0x10, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x06, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x84, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xa6, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, + 0x2e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif diff --git a/LibOVR/Src/CAPI/Shaders/DistortionTimewarp_vs.h b/LibOVR/Src/CAPI/Shaders/DistortionTimewarp_vs.h index f3111a8..6c79c56 100644 --- a/LibOVR/Src/CAPI/Shaders/DistortionTimewarp_vs.h +++ b/LibOVR/Src/CAPI/Shaders/DistortionTimewarp_vs.h @@ -2,11 +2,11 @@ #define DISTORTIONTIMEWARP_VS_H static const unsigned char DistortionTimewarp_vs[] = { - 0x44, 0x58, 0x42, 0x43, 0x96, 0x74, 0x01, 0x0e, 0x69, 0xc5, 0xe0, 0xbd, - 0x73, 0x27, 0xa6, 0x54, 0x7e, 0xee, 0xb9, 0xb6, 0x01, 0x00, 0x00, 0x00, - 0x7c, 0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0x98, 0x01, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x7c, 0x02, 0x00, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x5c, 0x01, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0x91, 0xed, 0x41, 0x60, 0xb0, 0x3e, 0xf0, 0x08, + 0x7a, 0xeb, 0x1b, 0xe6, 0x05, 0x4c, 0x48, 0xd2, 0x01, 0x00, 0x00, 0x00, + 0x80, 0x07, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0x9c, 0x01, 0x00, 0x00, 0x0c, 0x02, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x60, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xfe, 0xff, 0x00, 0x01, 0x00, 0x00, 0x2b, 0x01, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -34,134 +34,135 @@ static const unsigned char DistortionTimewarp_vs[] = { 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x64, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, - 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, - 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, - 0x49, 0x53, 0x47, 0x4e, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0f, 0x09, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x00, 0x00, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, - 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, - 0x4f, 0x52, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x4e, 0x6c, 0x00, 0x00, 0x00, + 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, 0x2e, + 0x33, 0x2e, 0x39, 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, 0x34, + 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, - 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, - 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, - 0x53, 0x48, 0x44, 0x52, 0x7c, 0x04, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, - 0x1f, 0x01, 0x00, 0x00, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, - 0x32, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, - 0x92, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, - 0x32, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, - 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x65, 0x00, 0x00, 0x03, 0x12, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x65, 0x00, 0x00, 0x03, 0x62, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x68, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, - 0x32, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, 0xc2, 0x20, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x3f, - 0x36, 0x00, 0x00, 0x05, 0x12, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x06, - 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x80, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x06, - 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x80, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x06, - 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x42, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x80, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x06, - 0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, - 0x82, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x10, 0x80, - 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x09, - 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x1f, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, - 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, 0xc2, 0x00, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, - 0x11, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x62, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x20, 0x80, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x81, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, - 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x0a, 0x12, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x62, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x56, 0x84, 0x20, 0x80, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x56, 0x84, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, - 0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x0a, 0x22, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x52, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x56, 0x84, 0x20, 0x80, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x56, 0x84, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, - 0x42, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x0a, 0x42, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0f, 0x09, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x50, 0x4f, 0x53, 0x49, + 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, + 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x4f, 0x53, 0x47, 0x4e, + 0x6c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, + 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, + 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x09, 0x00, 0x00, + 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, + 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, + 0x52, 0x44, 0x00, 0xab, 0x53, 0x48, 0x44, 0x52, 0x7c, 0x04, 0x00, 0x00, + 0x40, 0x00, 0x01, 0x00, 0x1f, 0x01, 0x00, 0x00, 0x59, 0x00, 0x00, 0x04, + 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, + 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x5f, 0x00, 0x00, 0x03, 0x92, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x5f, 0x00, 0x00, 0x03, 0x32, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x67, 0x00, 0x00, 0x04, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x12, 0x20, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0x62, 0x20, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x32, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, + 0xc2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x80, 0x3f, 0x36, 0x00, 0x00, 0x05, 0x12, 0x20, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x06, 0x12, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x12, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x06, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x22, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x06, 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x42, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x06, 0x82, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x82, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x3a, 0x00, 0x10, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x09, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xf6, 0x1f, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x36, 0x00, 0x00, 0x05, 0x32, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x08, + 0xc2, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, + 0x00, 0x00, 0x80, 0x3f, 0x11, 0x00, 0x00, 0x07, 0x12, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x62, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x20, 0x80, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x06, 0x81, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x0a, 0x12, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x92, 0x00, 0x10, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x56, 0x81, 0x20, 0x80, 0x41, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x56, 0x81, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, - 0x82, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x11, 0x00, 0x00, 0x07, 0x42, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x0e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x82, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x12, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x3a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, - 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x07, 0x32, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x96, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0b, 0x62, 0x20, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x81, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xa6, 0x8b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x62, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x84, 0x20, 0x80, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x56, 0x84, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x0a, 0x22, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x22, 0x00, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x52, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x56, 0x84, 0x20, 0x80, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x56, 0x84, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x0a, 0x42, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x42, 0x00, 0x10, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x80, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x92, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, 0x56, 0x81, 0x20, 0x80, + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x56, 0x81, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x0a, 0x82, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x3a, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x1a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x07, 0x42, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x46, 0x0e, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, + 0x82, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x0a, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x11, 0x00, 0x00, 0x07, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x46, 0x0e, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x07, 0x32, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x96, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0b, + 0x62, 0x20, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x81, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xa6, 0x8b, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, + 0x74, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; #endif diff --git a/LibOVR/Src/CAPI/Shaders/Distortion_ps.h b/LibOVR/Src/CAPI/Shaders/Distortion_ps.h index a486bba..2463ff4 100644 --- a/LibOVR/Src/CAPI/Shaders/Distortion_ps.h +++ b/LibOVR/Src/CAPI/Shaders/Distortion_ps.h @@ -2,11 +2,11 @@ #define DISTORTION_PS_H static const unsigned char Distortion_ps[] = { - 0x44, 0x58, 0x42, 0x43, 0x7c, 0x85, 0xba, 0x67, 0x3a, 0xd7, 0x3f, 0x92, - 0xa7, 0x4b, 0x33, 0x10, 0x5b, 0x1b, 0x09, 0x5d, 0x01, 0x00, 0x00, 0x00, - 0xb4, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, - 0xd8, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, - 0x38, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x9c, 0x00, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0x43, 0xb8, 0xfc, 0x1d, 0x5b, 0xd5, 0xae, 0xc2, + 0x67, 0xa3, 0x69, 0xc1, 0x8c, 0xb8, 0xbe, 0x9d, 0x01, 0x00, 0x00, 0x00, + 0xb8, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, + 0xdc, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x84, 0x01, 0x00, 0x00, + 0x3c, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x04, 0xff, 0xff, 0x00, 0x01, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, @@ -18,48 +18,49 @@ static const unsigned char Distortion_ps[] = { 0x61, 0x72, 0x00, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, - 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, - 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, - 0x49, 0x53, 0x47, 0x4e, 0x6c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0f, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, 0x2e, + 0x33, 0x2e, 0x39, 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, 0x34, + 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x6c, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, + 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, + 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x00, 0xab, 0xab, 0x53, 0x48, 0x44, 0x52, 0xb0, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x03, + 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, + 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, + 0x62, 0x10, 0x00, 0x03, 0x12, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x62, 0x10, 0x00, 0x03, 0x62, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, + 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x15, 0x10, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0x72, 0x20, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x46, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, + 0x82, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x3f, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, + 0x74, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x01, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x06, 0x06, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, - 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, 0x4f, 0x53, 0x47, 0x4e, - 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, - 0x53, 0x56, 0x5f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x00, 0xab, 0xab, - 0x53, 0x48, 0x44, 0x52, 0xb0, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, - 0x2c, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x03, 0x00, 0x60, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x58, 0x18, 0x00, 0x04, 0x00, 0x70, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, - 0x12, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, - 0x62, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, - 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x02, - 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x0b, 0xf2, 0x00, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x96, 0x15, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x46, 0x7e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x00, 0x00, 0x07, 0x72, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x46, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x10, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0x82, 0x20, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, - 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; #endif diff --git a/LibOVR/Src/CAPI/Shaders/Distortion_vs.h b/LibOVR/Src/CAPI/Shaders/Distortion_vs.h index 8520fd9..3d3552b 100644 --- a/LibOVR/Src/CAPI/Shaders/Distortion_vs.h +++ b/LibOVR/Src/CAPI/Shaders/Distortion_vs.h @@ -2,8 +2,8 @@ #define DISTORTION_VS_H static const unsigned char Distortion_vs[] = { - 0x44, 0x58, 0x42, 0x43, 0xfd, 0x23, 0xd7, 0xc6, 0x1a, 0x85, 0x42, 0xd8, - 0xf1, 0xf2, 0x06, 0x88, 0x86, 0xf0, 0xd9, 0xc7, 0x01, 0x00, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0x77, 0x9d, 0x99, 0x8c, 0xc0, 0xf3, 0x3f, 0xec, + 0xf9, 0x83, 0x0b, 0xe5, 0x85, 0x2b, 0x86, 0xf6, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xfc, 0x00, 0x00, 0x00, @@ -26,8 +26,8 @@ static const unsigned char Distortion_vs[] = { 0x56, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, - 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, - 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, 0x2e, 0x33, 0x2e, 0x39, + 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, 0x34, 0x00, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -68,7 +68,7 @@ static const unsigned char Distortion_vs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/LibOVR/Src/CAPI/Shaders/SimpleQuad_ps.h b/LibOVR/Src/CAPI/Shaders/SimpleQuad_ps.h index 796a880..2c01e6c 100644 --- a/LibOVR/Src/CAPI/Shaders/SimpleQuad_ps.h +++ b/LibOVR/Src/CAPI/Shaders/SimpleQuad_ps.h @@ -2,8 +2,8 @@ #define SIMPLEQUAD_PS_H static const unsigned char SimpleQuad_ps[] = { - 0x44, 0x58, 0x42, 0x43, 0x8c, 0x53, 0x2f, 0x7c, 0x3d, 0xea, 0xa5, 0xb6, - 0x05, 0xb7, 0xe0, 0x83, 0x67, 0x16, 0x9c, 0x93, 0x01, 0x00, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0xc5, 0x64, 0xa2, 0x55, 0x15, 0x24, 0x7d, 0xe6, + 0x27, 0xd2, 0xf4, 0x4e, 0x42, 0xb6, 0xba, 0x78, 0x01, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x8c, 0x01, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xc4, 0x00, 0x00, 0x00, @@ -21,9 +21,9 @@ static const unsigned char SimpleQuad_ps[] = { 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, - 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, - 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, - 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x08, 0x00, 0x00, 0x00, + 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, + 0x2e, 0x33, 0x2e, 0x39, 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, + 0x34, 0x00, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x4f, 0x53, 0x47, 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/LibOVR/Src/CAPI/Shaders/SimpleQuad_vs.h b/LibOVR/Src/CAPI/Shaders/SimpleQuad_vs.h index d3387ce..510c200 100644 --- a/LibOVR/Src/CAPI/Shaders/SimpleQuad_vs.h +++ b/LibOVR/Src/CAPI/Shaders/SimpleQuad_vs.h @@ -2,8 +2,8 @@ #define SIMPLEQUAD_VS_H static const unsigned char SimpleQuad_vs[] = { - 0x44, 0x58, 0x42, 0x43, 0xd5, 0x40, 0x5f, 0xa6, 0x2d, 0x0a, 0xd9, 0x2a, - 0x84, 0x41, 0x9e, 0x1f, 0xab, 0xa5, 0xa9, 0x2c, 0x01, 0x00, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0xb2, 0x87, 0xff, 0xa1, 0x41, 0xd7, 0x0e, 0x94, + 0x59, 0xd6, 0x1b, 0x8c, 0x94, 0x3d, 0xb9, 0x46, 0x01, 0x00, 0x00, 0x00, 0xa8, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x2c, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xfc, 0x00, 0x00, 0x00, @@ -26,8 +26,8 @@ static const unsigned char SimpleQuad_vs[] = { 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, - 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, - 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, 0x2e, 0x33, 0x2e, 0x39, + 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, 0x34, 0x00, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -50,7 +50,7 @@ static const unsigned char SimpleQuad_vs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/LibOVR/Src/CAPI/Shaders/SimpleTexturedQuad_ps.h b/LibOVR/Src/CAPI/Shaders/SimpleTexturedQuad_ps.h index dd5cae3..c8b1a82 100644 --- a/LibOVR/Src/CAPI/Shaders/SimpleTexturedQuad_ps.h +++ b/LibOVR/Src/CAPI/Shaders/SimpleTexturedQuad_ps.h @@ -2,8 +2,8 @@ #define SIMPLETEXTUREDQUAD_PS_H static const unsigned char SimpleTexturedQuad_ps[] = { - 0x44, 0x58, 0x42, 0x43, 0xbe, 0x17, 0xf1, 0xab, 0xc8, 0x62, 0x4c, 0x11, - 0xe8, 0x29, 0xb0, 0x5b, 0x0b, 0xf8, 0x73, 0x38, 0x01, 0x00, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0x28, 0x50, 0xb2, 0x7b, 0x03, 0x55, 0x33, 0xd0, + 0x24, 0xd2, 0xc9, 0x9f, 0x95, 0x9b, 0xa9, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x44, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0xc8, 0x01, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0xc8, 0x02, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0x18, 0x01, 0x00, 0x00, @@ -28,9 +28,9 @@ static const unsigned char SimpleTexturedQuad_ps[] = { 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, - 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, - 0x2e, 0x32, 0x39, 0x2e, 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, - 0x00, 0xab, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x6c, 0x00, 0x00, 0x00, + 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, + 0x2e, 0x33, 0x2e, 0x39, 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, + 0x34, 0x00, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x6c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, diff --git a/LibOVR/Src/CAPI/Shaders/SimpleTexturedQuad_vs.h b/LibOVR/Src/CAPI/Shaders/SimpleTexturedQuad_vs.h index 0375fdc..9f5b45d 100644 --- a/LibOVR/Src/CAPI/Shaders/SimpleTexturedQuad_vs.h +++ b/LibOVR/Src/CAPI/Shaders/SimpleTexturedQuad_vs.h @@ -2,8 +2,8 @@ #define SIMPLETEXTUREDQUAD_VS_H static const unsigned char SimpleTexturedQuad_vs[] = { - 0x44, 0x58, 0x42, 0x43, 0xe3, 0x2d, 0x41, 0xb3, 0xee, 0x4c, 0x7d, 0xb3, - 0x80, 0x0d, 0x3a, 0x0c, 0xb6, 0x80, 0x5e, 0xb1, 0x01, 0x00, 0x00, 0x00, + 0x44, 0x58, 0x42, 0x43, 0x65, 0x25, 0x0c, 0xd1, 0x14, 0xa7, 0xfd, 0xde, + 0xf4, 0x91, 0xf7, 0xf7, 0x9e, 0xd4, 0xa5, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x7c, 0x03, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x38, 0x01, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x52, 0x44, 0x45, 0x46, 0xfc, 0x00, 0x00, 0x00, @@ -26,8 +26,8 @@ static const unsigned char SimpleTexturedQuad_vs[] = { 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x80, 0x3f, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, - 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x39, 0x2e, 0x32, 0x39, 0x2e, - 0x39, 0x35, 0x32, 0x2e, 0x33, 0x31, 0x31, 0x31, 0x00, 0xab, 0xab, 0xab, + 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x36, 0x2e, 0x33, 0x2e, 0x39, + 0x36, 0x30, 0x30, 0x2e, 0x31, 0x36, 0x33, 0x38, 0x34, 0x00, 0xab, 0xab, 0x49, 0x53, 0x47, 0x4e, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -68,7 +68,7 @@ static const unsigned char SimpleTexturedQuad_vs[] = { 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x01, 0x53, 0x54, 0x41, 0x54, 0x74, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/LibOVR/Src/Displays/OVR_Display.cpp b/LibOVR/Src/Displays/OVR_Display.cpp index 65f0b30..c7a624f 100644 --- a/LibOVR/Src/Displays/OVR_Display.cpp +++ b/LibOVR/Src/Displays/OVR_Display.cpp @@ -29,4 +29,8 @@ limitations under the License. namespace OVR { -} + +// Place platform-independent code here + + +} // namespace OVR diff --git a/LibOVR/Src/Displays/OVR_Display.h b/LibOVR/Src/Displays/OVR_Display.h index 3184182..bcba4bc 100644 --- a/LibOVR/Src/Displays/OVR_Display.h +++ b/LibOVR/Src/Displays/OVR_Display.h @@ -189,6 +189,10 @@ public: // Check if right now the current rendering application should be in compatibility mode static bool InCompatibilityMode( bool displaySearch = true ); + // Get/set the mode for all applications + static bool GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode); + static bool SetDriverMode(bool compatMode, bool hideDK1Mode); + static DisplaySearchHandle* GetDisplaySearchHandle(); }; diff --git a/LibOVR/Src/Displays/OVR_Win32_Display.cpp b/LibOVR/Src/Displays/OVR_Win32_Display.cpp index 8300468..6bebc7b 100644 --- a/LibOVR/Src/Displays/OVR_Win32_Display.cpp +++ b/LibOVR/Src/Displays/OVR_Win32_Display.cpp @@ -37,10 +37,14 @@ limitations under the License. #include <SetupAPI.h> #include <Mmsystem.h> #include <conio.h> + +#ifdef OVR_COMPAT_EDID_VIA_WMI # pragma comment(lib, "wbemuuid.lib") #include <wbemidl.h> -#include <AtlBase.h> -#include <AtlConv.h> +#else // OVR_COMPAT_EDID_VIA_WMI +#include <setupapi.h> +#include <initguid.h> +#endif // OVR_COMPAT_EDID_VIA_WMI // WIN32_LEAN_AND_MEAN included in OVR_Atomic.h may break 'byte' declaration. #ifdef WIN32_LEAN_AND_MEAN @@ -56,7 +60,8 @@ typedef struct UINT ExpectedWidth; UINT ExpectedHeight; HWND hWindow; - bool InCompatibilityMode; + bool CompatibilityMode; + bool HideDK1Mode; } ContextStruct; static ContextStruct GlobalDisplayContext = {0}; @@ -89,7 +94,7 @@ ULONG getRift( HANDLE hDevice, int index ) { ULONG riftCount = getRiftCount( hDevice ); DWORD bytesReturned = 0; - BOOL result; + BOOL result; if( riftCount >= (ULONG)index ) { @@ -334,11 +339,10 @@ static BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwDa return TRUE; }; +#ifdef OVR_COMPAT_EDID_VIA_WMI static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, String& userFriendlyNameStr ) { - USES_CONVERSION; - IWbemLocator *pLoc = NULL; IWbemServices *pSvc = NULL; HRESULT hres; @@ -350,8 +354,10 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(("Failed to initialize COM library. Error code = 0x%x\n", hres)); - return false; + + LogError("{ERR-082} [Display] WARNING: Failed to initialize COM library. Error code = 0x%x", hres); + OVR_ASSERT(false); + return false; } hres = CoInitializeSecurity( @@ -368,10 +374,9 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(("Failed to initialize security. Error code = 0x%x\n", hres)); - //CoUninitialize(); - //return false; - selfInitialized = false; + LogError("{ERR-083} [Display] WARNING: Failed to initialize security. Error code = 0x%x", hres); + OVR_ASSERT(false); + selfInitialized = false; } initialized = true; @@ -385,8 +390,9 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(("Failed to create IWbemLocator object. Err code = 0x%x\n", hres)); - return false; + LogError("{ERR-084} [Display] WARNING: Failed to create IWbemLocator object.Err code = 0x%x", hres); + OVR_ASSERT(false); + return false; } BSTR AbackB = SysAllocString(L"root\\WMI"); @@ -407,8 +413,9 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(("Could not connect. Error code = 0x%x\n", hres)); - pLoc->Release(); + LogError("{ERR-085} [Display] WARNING: Could not connect to root\\WMI. Error code = 0x%x", hres); + OVR_ASSERT(false); + pLoc->Release(); return false; } @@ -425,8 +432,9 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(("Could not set proxy blanket. Error code = 0x%x\n", hres)); - pSvc->Release(); + LogError("{ERR-086} [Display] WARNING: Could not set proxy blanket. Error code = 0x%x", hres); + OVR_ASSERT(false); + pSvc->Release(); pLoc->Release(); return false; } @@ -446,12 +454,16 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S if (FAILED(hres)) { - OVR_DEBUG_LOG_TEXT(( "Query for operating system name failed. Error code = 0x%x\n", hres )); - pSvc->Release(); + LogError("{ERR-087} [Display] WARNING: Query for operating system name failed. Error code = 0x%x", hres); + OVR_ASSERT(false); + pSvc->Release(); pLoc->Release(); return false; } + int enumeratedCount = 0; + bool found = false; + IWbemClassObject *pclsObj = 0; while (pEnumerator) { @@ -463,29 +475,31 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S break; } - VARIANT vtProp; - hr = pclsObj->Get(L"InstanceName", 0, &vtProp, 0, 0); + ++enumeratedCount; + + VARIANT vtProp; + hr = pclsObj->Get(L"InstanceName", 0, &vtProp, 0, 0); - WCHAR* instanceName = vtProp.bstrVal; - WCHAR* nextToken = NULL; - if (SUCCEEDED(hr) && + WCHAR* instanceName = vtProp.bstrVal; + WCHAR* nextToken = NULL; + if (SUCCEEDED(hr) && wcstok_s(instanceName, L"\\", &nextToken) != NULL) - { - WCHAR* aToken = wcstok_s(NULL, L"\\", &nextToken); + { + WCHAR* aToken = wcstok_s(NULL, L"\\", &nextToken); - if (aToken != NULL) - { - VariantClear(&vtProp); + if (aToken != NULL) + { + VariantClear(&vtProp); - if (wcscmp(aToken, displayName) != 0) - { + if (wcscmp(aToken, displayName) != 0) + { pclsObj->Release(); continue; - } + } - // Read serial + // Read serial - hr = pclsObj->Get(L"SerialNumberID", 0, &vtProp, 0, 0); + hr = pclsObj->Get(L"SerialNumberID", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { @@ -505,21 +519,21 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Wrong data format for SerialNumberID")); + LogError("{ERR-088} [Display] WARNING: Wrong data format for SerialNumberID"); } VariantClear(&vtProp); } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Failure getting display SerialNumberID: %d", (int)hr)); + LogError("{ERR-089} [Display] WARNING: Failure getting display SerialNumberID: %d", (int)hr); } - // Read length of name + // Read length of name int userFriendlyNameLen = 0; - hr = pclsObj->Get(L"UserFriendlyNameLength", 0, &vtProp, 0, 0); + hr = pclsObj->Get(L"UserFriendlyNameLength", 0, &vtProp, 0, 0); if (SUCCEEDED(hr)) { @@ -531,24 +545,24 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S { userFriendlyNameLen = 0; - OVR_DEBUG_LOG(("[Win32Display] WARNING: UserFriendlyNameLength = 0")); + LogError("{ERR-090} [Display] WARNING: UserFriendlyNameLength = 0"); } } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Wrong data format for UserFriendlyNameLength")); + LogError("{ERR-091} [Display] WARNING: Wrong data format for UserFriendlyNameLength"); } VariantClear(&vtProp); } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Failure getting display UserFriendlyNameLength: %d", (int)hr)); + LogError("{ERR-092} [Display] WARNING: Failure getting display UserFriendlyNameLength: %d", (int)hr); } - // Read name + // Read name - hr = pclsObj->Get(L"UserFriendlyName", 0, &vtProp, 0, 0); + hr = pclsObj->Get(L"UserFriendlyName", 0, &vtProp, 0, 0); if (SUCCEEDED(hr) && userFriendlyNameLen > 0) { @@ -570,20 +584,23 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S { // See: https://developer.oculusvr.com/forums/viewtopic.php?f=34&t=10961 // This can happen if someone has an EDID override in the registry. - OVR_DEBUG_LOG(("[Win32Display] WARNING: Wrong data format for UserFriendlyName")); + LogError("{ERR-093} [Display] WARNING: Wrong data format for UserFriendlyName"); } VariantClear(&vtProp); } else { - OVR_DEBUG_LOG(("[Win32Display] WARNING: Failure getting display UserFriendlyName: %d", (int)hr)); + LogError("{ERR-094} [Display] WARNING: Failure getting display UserFriendlyName: %d", (int)hr); } - } + } + + found = true; + pclsObj->Release(); + break; } - pclsObj->Release(); - break; + pclsObj->Release(); } HMODULE hModule = GetModuleHandleA("wbemuuid"); @@ -596,9 +613,201 @@ static bool getCompatDisplayEDID( WCHAR* displayName, String& serialNumberStr, S pLoc->Release(); pEnumerator->Release(); - return true; + if (!found) + { + LogError("{ERR-095} [Display] WARNING: Unable to enumerate the rift via WMI (found %d monitors). This is not normally an issue. Running as a user with Administrator privileges has fixed this problem in the past.", enumeratedCount); + OVR_ASSERT(false); + } + + return found; +} + +#else // OVR_COMPAT_EDID_VIA_WMI + +#define NAME_SIZE 128 + +DEFINE_GUID(GUID_CLASS_MONITOR, + 0x4d36e96e, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, + 0x03, 0x18); + +static void truncateNonalphanum(char* str, int len) +{ + for (int i = 0; i < len; ++i) + { + char ch = str[i]; + + if ((ch < 'A' || ch > 'Z') && + (ch < 'a' || ch > 'z') && + (ch < '0' || ch > '9') && + ch != ' ') + { + str[i] = '\0'; + break; + } + } +} + +static bool AccessDeviceRegistry(IN HDEVINFO devInfo, IN PSP_DEVINFO_DATA devInfoData, + const WCHAR* displayName, String& serialNumberStr, String& userFriendlyNameStr) +{ + // Match hardware id to display name + WCHAR hardwareId[128]; + if (!SetupDiGetDeviceRegistryProperty( + devInfo, + devInfoData, + SPDRP_HARDWAREID, + NULL, + (PBYTE)hardwareId, + sizeof(hardwareId), + NULL)) + { + LogError("{ERR-096} [Display] WARNING: SetupDiGetDeviceRegistryProperty for SPDRP_HARDWAREID failed. LastErr=%d", GetLastError()); + OVR_ASSERT(false); + return false; + } + hardwareId[127] = 0; + + // If the hardware id did not match, + if (!wcsstr(hardwareId, displayName)) + { + // Stop here + return false; + } + + // Grab hardware info registry key + HKEY hDevRegKey = SetupDiOpenDevRegKey( + devInfo, + devInfoData, + DICS_FLAG_GLOBAL, + 0, + DIREG_DEV, + KEY_READ); // Only read permissions so it can be run without Administrator privs + + if (hDevRegKey == INVALID_HANDLE_VALUE) + { + LogError("{ERR-097} [Display] WARNING: SetupDiOpenDevRegKey failed. LastErr=%d", GetLastError()); + OVR_ASSERT(false); + return false; + } + + // Enumerate keys in registry + bool found = false; + + // For each key, + for (int i = 0;; i++) + { + BYTE EDIDdata[1024]; + DWORD edidsize = sizeof(EDIDdata); + + DWORD dwType, ActualValueNameLength = NAME_SIZE; + CHAR valueName[NAME_SIZE]; + + // Read the key value data + LSTATUS retValue = RegEnumValueA( + hDevRegKey, + i, + &valueName[0], + &ActualValueNameLength, + NULL, + &dwType, + EDIDdata, + &edidsize); + + if (FAILED(retValue)) + { + if (retValue == ERROR_NO_MORE_ITEMS) + { + break; + } + + LogError("{ERR-098} [Display] WARNING: RegEnumValueA failed to read a key. LastErr=%d", retValue); + OVR_ASSERT(false); + } + else if (0 == strcmp(valueName, "EDID")) // Value is EDID: + { + // Tested working for DK1 and DK2: + + char friendlyString[9]; + memcpy(friendlyString, EDIDdata + 77, 8); + truncateNonalphanum(friendlyString, 8); + friendlyString[8] = '\0'; + + char edidString[14]; + memcpy(edidString, EDIDdata + 95, 13); + truncateNonalphanum(edidString, 13); + edidString[13] = '\0'; + + serialNumberStr = edidString; + userFriendlyNameStr = friendlyString; + + found = true; + break; + } + } + + RegCloseKey(hDevRegKey); + + return found; +} + +static bool getCompatDisplayEDID(const WCHAR* displayName, String& serialNumberStr, String& userFriendlyNameStr) +{ + HDEVINFO devInfo = NULL; + + devInfo = SetupDiGetClassDevsEx( + &GUID_CLASS_MONITOR, //class GUID + NULL, //enumerator + NULL, //HWND + DIGCF_PRESENT, // Flags //DIGCF_ALLCLASSES| + NULL, // device info, create a new one. + NULL, // machine name, local machine + NULL);// reserved + + if (NULL == devInfo) + { + return false; + } + + DWORD lastError = 0; + + // For each display, + for (int i = 0;; i++) + { + SP_DEVINFO_DATA devInfoData = {}; + devInfoData.cbSize = sizeof(devInfoData); + + // Grab device info + if (SetupDiEnumDeviceInfo(devInfo, i, &devInfoData)) + { + // Access device info from registry + if (AccessDeviceRegistry(devInfo, &devInfoData, displayName, serialNumberStr, userFriendlyNameStr)) + { + return true; + } + } + else + { + lastError = GetLastError(); + + // If no more items found, + if (lastError != ERROR_NO_MORE_ITEMS) + { + LogError("{ERR-099} [Display] WARNING: SetupDiEnumDeviceInfo failed. LastErr=%d", lastError); + OVR_ASSERT(false); + } + + break; + } + } + + LogError("{ERR-100} [Display] WARNING: SetupDiEnumDeviceInfo did not return the rift display. LastErr=%d", lastError); + OVR_ASSERT(false); + + return false; } +#endif // OVR_COMPAT_EDID_VIA_WMI + // This is function that's used bool anyRiftsInExtendedMode() { @@ -797,27 +1006,28 @@ bool Display::InCompatibilityMode( bool displaySearch ) bool result = false; if( displaySearch ) { - OVR::Win32::DisplayDesc displayArray[8]; + OVR::Win32::DisplayDesc displayArray[8]; - int extendedRiftCount = discoverExtendedRifts(displayArray, 8, false); - if( extendedRiftCount ) - { - result = true; - } - else - { - result = GlobalDisplayContext.InCompatibilityMode; + int extendedRiftCount = discoverExtendedRifts(displayArray, 8, false); + if( extendedRiftCount ) + { + result = true; + } + else + { + result = GlobalDisplayContext.CompatibilityMode; } } else { - result = GlobalDisplayContext.InCompatibilityMode; + result = GlobalDisplayContext.CompatibilityMode; } return result; } #define OVR_FLAG_COMPATIBILITY_MODE 1 +#define OVR_FLAG_HIDE_DK1 2 bool Display::Initialize() { @@ -830,7 +1040,7 @@ bool Display::Initialize() if (hDevice != NULL && hDevice != INVALID_HANDLE_VALUE) { GlobalDisplayContext.hDevice = hDevice; - GlobalDisplayContext.InCompatibilityMode = FALSE; + GlobalDisplayContext.CompatibilityMode = false; DWORD bytesReturned = 0; LONG compatiblityResult = OVR_STATUS_SUCCESS; @@ -839,16 +1049,16 @@ bool Display::Initialize() &compatiblityResult, sizeof( LONG ), &bytesReturned, NULL ); if (result) { - if( compatiblityResult & OVR_FLAG_COMPATIBILITY_MODE ) - GlobalDisplayContext.InCompatibilityMode = TRUE; - } + GlobalDisplayContext.CompatibilityMode = (compatiblityResult & OVR_FLAG_COMPATIBILITY_MODE) != 0; + GlobalDisplayContext.HideDK1Mode = (compatiblityResult & OVR_FLAG_HIDE_DK1) != 0; + } else { // If calling our driver fails in any way, assume compatibility mode as well - GlobalDisplayContext.InCompatibilityMode = TRUE; + GlobalDisplayContext.CompatibilityMode = true; } - if (!GlobalDisplayContext.InCompatibilityMode) + if (!GlobalDisplayContext.CompatibilityMode) { Ptr<DisplaySearchHandle> searchHandle = *Display::GetDisplaySearchHandle(); @@ -861,19 +1071,89 @@ bool Display::Initialize() } else { - GlobalDisplayContext.InCompatibilityMode = TRUE; + GlobalDisplayContext.CompatibilityMode = true; } } } else { - GlobalDisplayContext.InCompatibilityMode = TRUE; + GlobalDisplayContext.CompatibilityMode = true; } return true; } +bool Display::GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode) +{ + if (GlobalDisplayContext.hDevice == NULL) + { + driverInstalled = false; + compatMode = true; + hideDK1Mode = false; + } + else + { + driverInstalled = true; + compatMode = GlobalDisplayContext.CompatibilityMode; + hideDK1Mode = GlobalDisplayContext.HideDK1Mode; + } + + return true; +} + +bool Display::SetDriverMode(bool compatMode, bool hideDK1Mode) +{ + // If device is not initialized, + if (GlobalDisplayContext.hDevice == NULL) + { + OVR_ASSERT(false); + return false; + } + + // If no change, + if ((compatMode == GlobalDisplayContext.CompatibilityMode) && + (hideDK1Mode == GlobalDisplayContext.HideDK1Mode)) + { + return true; + } + + LONG mode_flags = 0; + if (compatMode) + { + mode_flags |= OVR_FLAG_COMPATIBILITY_MODE; + } + if (hideDK1Mode) + { + mode_flags |= OVR_FLAG_HIDE_DK1; + } + + DWORD bytesReturned = 0; + LONG err = 1; + + if (!DeviceIoControl(GlobalDisplayContext.hDevice, + IOCTL_RIFTMGR_SETCOMPATIBILITYMODE, + &mode_flags, + sizeof(LONG), + &err, + sizeof(LONG), + &bytesReturned, + NULL) || + (err != 0 && err != -3)) + { + LogError("{ERR-001w} [Win32Display] Unable to set device mode to (compat=%d dk1hide=%d): err=%d", + (int)compatMode, (int)hideDK1Mode, (int)err); + return false; + } + + OVR_DEBUG_LOG(("[Win32Display] Set device mode to (compat=%d dk1hide=%d)", + (int)compatMode, (int)hideDK1Mode)); + + GlobalDisplayContext.HideDK1Mode = hideDK1Mode; + GlobalDisplayContext.CompatibilityMode = compatMode; + return true; +} + DisplaySearchHandle* Display::GetDisplaySearchHandle() { return new Win32::Win32DisplaySearchHandle(); @@ -950,10 +1230,8 @@ Ptr<Display> Display::GetDisplay(int index, DisplaySearchHandle* handle) } // FIXME: We have the EDID. Let's just use that instead. - uint32_t nativeWidth = 1080; - uint32_t nativeHeight = 1920; - uint32_t logicalWidth = 1920; - uint32_t logicalHeight = 1080; + uint32_t nativeWidth = 1080, nativeHeight = 1920; + uint32_t logicalWidth = 1920, logicalHeight = 1080; uint32_t rotation = 0; switch (dEdid.ModelNumber) diff --git a/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h b/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h index ab1582c..bdcd813 100644 --- a/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h +++ b/LibOVR/Src/Displays/OVR_Win32_Dxgi_Display.h @@ -372,19 +372,31 @@ typedef struct _RIFT_STATUS_ARRAY // Enable or disable compatibility mode. Entering compatibility mode will fail if // the Rift is already actively scanning out a surface -// Input Buffer: BOOL - Nonzero if compatibility mode is desired, zero if it's not +// Input Buffer: LONG - Bit assignments: +// LSB (bit 0) is a flag for compatibility mode itself. +// 1 means compatibility mode. +// 0 means application direct mode. +// Bit 1 means "Hide DK1's". +// 1 means operate DK1's in synchronous with the compatibility mode exactly. +// 0 means operate in DK1 legacy mode. // Output Buffer: LONG - Result value (see OVR statuses) // 0 = success // -1 = general failure // -2 = failure, rift scanning out +// -3 = already active +// -4 = rift not present #define IOCTL_RIFTMGR_SETCOMPATIBILITYMODE CTL_CODE(FILE_DEVICE_VIDEO, \ FUNCTION_INDEX + 8, METHOD_NEITHER, FILE_ANY_ACCESS) // Call to obtain the current status of compatibility mode // Input Buffer: NOTHING -// Output Buffer: LONG - Result value -// 0 = Not in compatibility mode -// Non-zero = In compatibility mode +// Output Buffer: LONG - Bit assignments: +// LSB (bit 0) is a flag for compatibility mode itself. +// 1 means compatibility mode. +// 0 means application direct mode. +// Bit 1 means "Hide DK1's". +// 1 means operate DK1's in synchronous with the compatibility mode exactly. +// 0 means operate in DK1 legacy mode. #define IOCTL_RIFTMGR_GETCOMPATIBILITYMODE CTL_CODE(FILE_DEVICE_VIDEO, \ FUNCTION_INDEX + 9, METHOD_NEITHER, FILE_ANY_ACCESS) @@ -410,4 +422,4 @@ typedef struct _RIFT_STATUS_ARRAY #define IOCTL_RIFTMGR_GETEDID CTL_CODE(FILE_DEVICE_VIDEO, \ FUNCTION_INDEX + 11, METHOD_NEITHER, FILE_ANY_ACCESS) -#endif
\ No newline at end of file +#endif diff --git a/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp b/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp index 852e29e..d665546 100644 --- a/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp +++ b/LibOVR/Src/Displays/OVR_Win32_FocusReader.cpp @@ -75,6 +75,4 @@ void RenderFocusReader::OnSystemDestroy() } - - }} // namespace OVR::Win32 diff --git a/LibOVR/Src/Displays/OVR_Win32_FocusReader.h b/LibOVR/Src/Displays/OVR_Win32_FocusReader.h index f62b8de..1d58264 100644 --- a/LibOVR/Src/Displays/OVR_Win32_FocusReader.h +++ b/LibOVR/Src/Displays/OVR_Win32_FocusReader.h @@ -64,7 +64,7 @@ typedef SharedObjectReader< LocklessFocusState > SharedFocusReader; //----------------------------------------------------------------------------- // RenderFocusReader -class RenderFocusReader : public OVR::SystemSingletonBase<RenderFocusReader> +class RenderFocusReader : public OVR::SystemSingletonBase<RenderFocusReader>, public NewOverrideBase { OVR_DECLARE_SINGLETON(RenderFocusReader); diff --git a/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp b/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp index a58e40d..80b33a2 100644 --- a/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp +++ b/LibOVR/Src/Displays/OVR_Win32_RenderShim.cpp @@ -16,8 +16,7 @@ otherwise accompanies this software in either electronic or hard copy form. #include <windows.h> #include <DbgHelp.h> -#include <AtlBase.h> -#include <AtlConv.h> +#include <malloc.h> #include "OVR_Win32_Dxgi_Display.h" @@ -30,6 +29,12 @@ otherwise accompanies this software in either electronic or hard copy form. #pragma comment(lib, "DbgHelp.lib") +#define WIDE_TO_MB(wideString) \ + int wideString ## _slen = (int)wcslen(wideString); \ + char* wideString ## _cstr = (char*)alloca(wideString ## _slen * 2); \ + int count = WideCharToMultiByte(GetACP(), 0, wideString, -1, wideString ## _cstr, wideString ## _slen * 2, NULL, NULL); \ + wideString ## _cstr[count] = '\0'; + // Forward declarations // These functions are implemented in OVR_Win32_DisplayDevice.cpp. @@ -114,22 +119,63 @@ TryAgainWOW64: #define OLD_DATA_BACKUP_SIZE 16 -WinLoadLibraryA oldProcA = NULL; -WinLoadLibraryExA oldProcExA = NULL; -WinLoadLibraryW oldProcW = NULL; -WinLoadLibraryExW oldProcExW = NULL; -WinGetModuleHandleExA oldProcModExA = NULL; -WinGetModuleHandleExW oldProcModExW = NULL; -WinDirect3DCreate9 oldDirectX9Create = NULL; -BYTE oldDirectX9CreateData[OLD_DATA_BACKUP_SIZE]; -WinDirect3DCreate9Ex oldDirectX9ExCreate = NULL; -BYTE oldDirectX9ExCreateData[OLD_DATA_BACKUP_SIZE]; -WinCreateDXGIFactory oldCreateDXGIFactory = NULL; -BYTE oldCreateDXGIFactoryData[OLD_DATA_BACKUP_SIZE]; -WinCreateDXGIFactory1 oldCreateDXGIFactory1 = NULL; -BYTE oldCreateDXGIFactory1Data[OLD_DATA_BACKUP_SIZE]; -WinCreateDXGIFactory2 oldCreateDXGIFactory2 = NULL; -BYTE oldCreateDXGIFactory2Data[OLD_DATA_BACKUP_SIZE]; +static WinLoadLibraryA oldProcA = NULL; // Note: This is used to indicate that the shim is in place +static WinLoadLibraryExA oldProcExA = NULL; +static WinLoadLibraryW oldProcW = NULL; +static WinLoadLibraryExW oldProcExW = NULL; +static WinGetModuleHandleExA oldProcModExA = NULL; +static WinGetModuleHandleExW oldProcModExW = NULL; +static WinDirect3DCreate9 oldDirectX9Create = NULL; +static BYTE oldDirectX9CreateData[OLD_DATA_BACKUP_SIZE]; +static WinDirect3DCreate9Ex oldDirectX9ExCreate = NULL; +static BYTE oldDirectX9ExCreateData[OLD_DATA_BACKUP_SIZE]; +static WinCreateDXGIFactory oldCreateDXGIFactory = NULL; +static BYTE oldCreateDXGIFactoryData[OLD_DATA_BACKUP_SIZE]; +static WinCreateDXGIFactory1 oldCreateDXGIFactory1 = NULL; +static BYTE oldCreateDXGIFactory1Data[OLD_DATA_BACKUP_SIZE]; +static WinCreateDXGIFactory2 oldCreateDXGIFactory2 = NULL; +static BYTE oldCreateDXGIFactory2Data[OLD_DATA_BACKUP_SIZE]; + +#define NUM_LOADER_LIBS 4 + +static const char* loaderLibraryList[NUM_LOADER_LIBS] = { + "kernel32.dll", + "api-ms-win-core-libraryloader-l1-2-0.dll", + "api-ms-win-core-libraryloader-l1-1-0.dll", + "api-ms-win-core-libraryloader-l1-1-1.dll" +}; + +enum ShimedLibraries +{ + ShimLibDXGI = 0, + ShimLibD3D9 = 1, + ShimLibD3D11 = 2, + ShimLibDXGIDebug = 3, + ShimLibD3D10Core = 4, + ShimLibD3D10 = 5, + ShimLibGL = 6, + ShimCountMax = 7 +}; + +static const char* dllList[ShimCountMax] = { + "dxgi.dll", + "d3d9.dll", + "d3d11.dll", + "dxgidebug.dll", + "d3d10core.dll", + "d3d10.dll", + "opengl32.dll" +}; + +static HINSTANCE oldLoaderInstances[ShimCountMax] = { NULL }; +static PROC oldLoaderProcA[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcW[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcExA[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcExW[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcModExA[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; +static PROC oldLoaderProcModExW[ShimCountMax][NUM_LOADER_LIBS] = { { NULL } }; + +static HMODULE rtFilterModule = NULL; static bool checkForOverride( LPCSTR libFileName, OVRTargetAPI& targetApi ) { @@ -249,15 +295,15 @@ static HMODULE __in LPCWSTR lpLibFileName ) { - USES_CONVERSION; + WIDE_TO_MB(lpLibFileName); // Convert lpLibFileName -> lpLibFileName_cstr OVRTargetAPI targetAPI = DirectX; - bool needShim = checkForOverride( W2A( lpLibFileName ), targetAPI ); + bool needShim = checkForOverride( lpLibFileName_cstr, targetAPI ); if( !needShim ) return (*oldProcW)( lpLibFileName ); - return createShim( W2A( lpLibFileName ), targetAPI ); + return createShim( lpLibFileName_cstr, targetAPI ); } static HMODULE @@ -287,16 +333,16 @@ static HMODULE __in DWORD dwFlags ) { - USES_CONVERSION; + WIDE_TO_MB(lpLibFileName); // Convert lpLibFileName -> lpLibFileName_cstr OVRTargetAPI targetAPI = DirectX; - bool needShim = checkForOverride( W2A( lpLibFileName ), targetAPI ); + bool needShim = checkForOverride( lpLibFileName_cstr, targetAPI ); if( !needShim ) return (*oldProcExW)( lpLibFileName, hFile, dwFlags ); // FIXME: Don't throw away the flags parameter - return createShim( W2A( lpLibFileName ), targetAPI ); + return createShim( lpLibFileName_cstr, targetAPI ); } static BOOL WINAPI OVRGetModuleHandleExA( @@ -324,17 +370,17 @@ static BOOL WINAPI OVRGetModuleHandleExW( __out HMODULE *phModule ) { - USES_CONVERSION; + WIDE_TO_MB(lpModuleName); // Convert lpModuleName -> lpModuleName_cstr - OVRTargetAPI targetAPI = DirectX; + OVRTargetAPI targetAPI = DirectX; - bool needShim = checkForOverride( W2A( lpModuleName ), targetAPI ); + bool needShim = checkForOverride( lpModuleName_cstr, targetAPI ); if( !needShim ) { return (*oldProcModExW)( dwFlags, lpModuleName, phModule ); } - *phModule = createShim( W2A( lpModuleName ), targetAPI ); + *phModule = createShim( lpModuleName_cstr, targetAPI ); return TRUE; } @@ -465,7 +511,6 @@ HRESULT APIENTRY OVRDirect3DCreate9Ex(UINT SDKVersion, void** aDevice) } else { - HMODULE rtFilterModule = (*oldProcA)(RTFilter); WinDirect3DCreate9Ex createFunction = (WinDirect3DCreate9Ex)GetProcAddress(rtFilterModule, "Direct3DCreate9Ex"); result = (*createFunction)(SDKVersion, aDevice); } @@ -501,7 +546,6 @@ HRESULT APIENTRY OVRCreateDXGIFactory( } else { - HMODULE rtFilterModule = (*oldProcA)(RTFilter); WinCreateDXGIFactory createFunction = (WinCreateDXGIFactory)GetProcAddress(rtFilterModule, "CreateDXGIFactory"); result = (*createFunction)(riid, ppFactory); } @@ -528,7 +572,6 @@ HRESULT APIENTRY OVRCreateDXGIFactory1( } else { - HMODULE rtFilterModule = (*oldProcA)(RTFilter); WinCreateDXGIFactory1 createFunction = (WinCreateDXGIFactory1)GetProcAddress(rtFilterModule, "CreateDXGIFactory1"); result = (*createFunction)(riid, ppFactory); } @@ -556,7 +599,6 @@ HRESULT APIENTRY OVRCreateDXGIFactory2( } else { - HMODULE rtFilterModule = (*oldProcA)(RTFilter); WinCreateDXGIFactory2 createFunction = (WinCreateDXGIFactory2)GetProcAddress(rtFilterModule, "CreateDXGIFactory2"); result = (*createFunction)(flags, riid, ppFactory); } @@ -659,43 +701,27 @@ static PROC SetProcAddressA( return pfnHookAPIAddr; } -enum ShimedLibraries -{ - ShimLibDXGI = 0, - ShimLibD3D9 = 1, - ShimLibD3D11 = 2, - ShimLibDXGIDebug = 3, - ShimLibD3D10Core = 4, - ShimLibD3D10 = 5, - ShimLibGL = 6, - ShimCountMax = 7 -}; -void checkUMDriverOverrides( void* context ) +void checkUMDriverOverrides(void* context) { lastContext = context; if( oldProcA == NULL ) { - char* dllList[ShimCountMax] = { "dxgi.dll", "d3d9.dll", "d3d11.dll", "dxgidebug.dll", "d3d10core.dll", "d3d10.dll", "opengl32.dll" }; - PreloadLibraryRTFn loadFunc = NULL; for( int i = 0; i < ShimCountMax; ++i ) { - HINSTANCE hInst = GetModuleHandleA( dllList[i] ); - if( hInst == NULL ) + HINSTANCE hInst = NULL; + try + { + hInst = LoadLibraryA(dllList[i]); + } + catch(...) { - try - { - hInst = LoadLibraryA(dllList[i]); - } - catch(...) - { - - } - } + oldLoaderInstances[i] = hInst; + if( hInst ) { ShimedLibraries libCount = (ShimedLibraries)i; @@ -714,52 +740,75 @@ void checkUMDriverOverrides( void* context ) break; } - char* loaderLibraryList[4] = {"kernel32.dll", "api-ms-win-core-libraryloader-l1-2-0.dll", "api-ms-win-core-libraryloader-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll"}; - - for( int j = 0; j < 4; ++j ) - { - char* loaderLibrary = loaderLibraryList[j]; + for (int j = 0; j < NUM_LOADER_LIBS; ++j) + { + const char* loaderLibrary = loaderLibraryList[j]; PROC temp = NULL; - temp = SetProcAddressA( hInst, loaderLibrary, "LoadLibraryA", (PROC)OVRLoadLibraryA ); - if( !oldProcA ) - oldProcA = (WinLoadLibraryA)temp; - - temp = SetProcAddressA( hInst, loaderLibrary, "LoadLibraryW", (PROC)OVRLoadLibraryW ); - if( !oldProcW ) - oldProcW = (WinLoadLibraryW)temp; - - temp = SetProcAddressA( hInst, loaderLibrary, "LoadLibraryExA", (PROC)OVRLoadLibraryExA ); - if( !oldProcExA ) - oldProcExA = (WinLoadLibraryExA)temp; - - temp = SetProcAddressA( hInst, loaderLibrary, "LoadLibraryExW", (PROC)OVRLoadLibraryExW ); - if( !oldProcExW ) - oldProcExW = (WinLoadLibraryExW)temp; - - temp = SetProcAddressA( hInst, loaderLibrary, "GetModuleHandleExA", (PROC)OVRGetModuleHandleExA ); - if( !oldProcModExA ) - oldProcModExA = (WinGetModuleHandleExA)temp; - - temp = SetProcAddressA( hInst, loaderLibrary, "GetModuleHandleExW", (PROC)OVRGetModuleHandleExW ); - if( !oldProcModExW ) - oldProcModExW = (WinGetModuleHandleExW)temp; - } - - if( loadFunc == NULL ) - loadFunc = (PreloadLibraryRTFn)GetProcAddress( hInst, "PreloadLibraryRT" ); + temp = SetProcAddressA(hInst, loaderLibrary, "LoadLibraryA", (PROC)OVRLoadLibraryA); + if (!oldProcA) + { + oldProcA = (WinLoadLibraryA)temp; + } + oldLoaderProcA[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "LoadLibraryW", (PROC)OVRLoadLibraryW); + if (!oldProcW) + { + oldProcW = (WinLoadLibraryW)temp; + } + oldLoaderProcW[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "LoadLibraryExA", (PROC)OVRLoadLibraryExA); + if (!oldProcExA) + { + oldProcExA = (WinLoadLibraryExA)temp; + } + oldLoaderProcExA[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "LoadLibraryExW", (PROC)OVRLoadLibraryExW); + if (!oldProcExW) + { + oldProcExW = (WinLoadLibraryExW)temp; + } + oldLoaderProcExW[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "GetModuleHandleExA", (PROC)OVRGetModuleHandleExA); + if (!oldProcModExA) + { + oldProcModExA = (WinGetModuleHandleExA)temp; + } + oldLoaderProcModExA[i][j] = temp; + + temp = SetProcAddressA(hInst, loaderLibrary, "GetModuleHandleExW", (PROC)OVRGetModuleHandleExW); + if (!oldProcModExW) + { + oldProcModExW = (WinGetModuleHandleExW)temp; + } + oldLoaderProcModExW[i][j] = temp; + } + + if (loadFunc == NULL) + { + loadFunc = (PreloadLibraryRTFn)GetProcAddress(hInst, "PreloadLibraryRT"); + } } } - HMODULE rtFilterModule = (*oldProcA)( RTFilter ); + rtFilterModule = (*oldProcA)( RTFilter ); - if( loadFunc == NULL ) - loadFunc = (PreloadLibraryRTFn)GetProcAddress( rtFilterModule, "PreloadLibraryRT" ); - IsCreatingBackBuffer backBufferFunc = (IsCreatingBackBuffer)GetProcAddress( rtFilterModule, "OVRIsCreatingBackBuffer" ); - ShouldVSync shouldVSyncFunc = (ShouldVSync)GetProcAddress( rtFilterModule, "OVRShouldVSync" ); + IsCreatingBackBuffer backBufferFunc = NULL; + ShouldVSync shouldVSyncFunc = NULL; - if( loadFunc ) - { + if (rtFilterModule != NULL) + { + loadFunc = (PreloadLibraryRTFn)GetProcAddress(rtFilterModule, "PreloadLibraryRT"); + backBufferFunc = (IsCreatingBackBuffer)GetProcAddress(rtFilterModule, "OVRIsCreatingBackBuffer"); + shouldVSyncFunc = (ShouldVSync)GetProcAddress(rtFilterModule, "OVRShouldVSync"); + } + + if (loadFunc != NULL) + { appDriver.version = 1; appDriver.context = lastContext; @@ -786,3 +835,99 @@ void checkUMDriverOverrides( void* context ) } } } + +void clearUMDriverOverrides() +{ + if (oldProcA != NULL) + { + // Unpatch all the things. + + if (oldCreateDXGIFactory) + { + restoreFunction((PROC)oldCreateDXGIFactory, oldCreateDXGIFactoryData); + } + if (oldCreateDXGIFactory1) + { + restoreFunction((PROC)oldCreateDXGIFactory1, oldCreateDXGIFactory1Data); + } + if (oldCreateDXGIFactory2) + { + restoreFunction((PROC)oldCreateDXGIFactory2, oldCreateDXGIFactory2Data); + } + if (oldDirectX9Create) + { + restoreFunction((PROC)oldDirectX9Create, oldDirectX9CreateData); + } + if (oldDirectX9ExCreate) + { + restoreFunction((PROC)oldDirectX9ExCreate, oldDirectX9ExCreateData); + } + if (oldCreateDXGIFactory2) + { + restoreFunction((PROC)oldCreateDXGIFactory2, oldCreateDXGIFactory2Data); + } + + for (int i = 0; i < ShimCountMax; ++i) + { + HINSTANCE hInst = oldLoaderInstances[i]; + + if (hInst != NULL) + { + for (int j = 0; j < NUM_LOADER_LIBS; ++j) + { + const char* loaderLibrary = loaderLibraryList[j]; + + if (oldLoaderProcA[j]) + { + SetProcAddressA(hInst, loaderLibrary, "LoadLibraryA", oldLoaderProcA[i][j]); + } + if (oldLoaderProcW[j]) + { + SetProcAddressA(hInst, loaderLibrary, "LoadLibraryW", oldLoaderProcW[i][j]); + } + if (oldLoaderProcExA[j]) + { + SetProcAddressA(hInst, loaderLibrary, "LoadLibraryExA", oldLoaderProcExA[i][j]); + } + if (oldLoaderProcExW[j]) + { + SetProcAddressA(hInst, loaderLibrary, "LoadLibraryExW", oldLoaderProcExW[i][j]); + } + if (oldLoaderProcModExA[j]) + { + SetProcAddressA(hInst, loaderLibrary, "GetModuleHandleExA", oldLoaderProcModExA[i][j]); + } + if (oldLoaderProcModExW[j]) + { + SetProcAddressA(hInst, loaderLibrary, "GetModuleHandleExW", oldLoaderProcModExW[i][j]); + } + } + + FreeLibrary(hInst); + } + } + + if (rtFilterModule != NULL) + { + LPFNCANUNLOADNOW pfnCanUnloadNow = (LPFNCANUNLOADNOW)GetProcAddress(rtFilterModule, "DllCanUnloadNow"); + if (pfnCanUnloadNow && pfnCanUnloadNow() == S_OK) + { + FreeLibrary(rtFilterModule); + rtFilterModule = NULL; + } + } + + oldProcA = NULL; + oldProcExA = NULL; + oldProcW = NULL; + oldProcExW = NULL; + oldProcModExA = NULL; + oldProcModExW = NULL; + oldDirectX9Create = NULL; + oldDirectX9ExCreate = NULL; + oldCreateDXGIFactory = NULL; + oldCreateDXGIFactory1 = NULL; + oldCreateDXGIFactory2 = NULL; + lastContext = NULL; + } +} diff --git a/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp b/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp index 9e5442c..907dc13 100644 --- a/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp +++ b/LibOVR/Src/Displays/OVR_Win32_ShimFunctions.cpp @@ -31,7 +31,8 @@ limitations under the License. #include "OVR_Win32_FocusReader.h" // Exported -extern void checkUMDriverOverrides( void* context ); +extern void checkUMDriverOverrides(void* context); +extern void clearUMDriverOverrides(); #include <stdio.h> #include <tchar.h> @@ -203,6 +204,8 @@ bool DisplayShim::Initialize( bool inCompatibility ) bool DisplayShim::Shutdown() { + clearUMDriverOverrides(); + return true; } diff --git a/LibOVR/Src/Kernel/OVR_Atomic.cpp b/LibOVR/Src/Kernel/OVR_Atomic.cpp index 9ea6e76..079792e 100644 --- a/LibOVR/Src/Kernel/OVR_Atomic.cpp +++ b/LibOVR/Src/Kernel/OVR_Atomic.cpp @@ -107,7 +107,7 @@ Lock* SharedLock::GetLockAddRef() do { oldUseCount = UseCount; - if (oldUseCount == LockInitMarker) + if (oldUseCount == (int)LockInitMarker) continue; if (oldUseCount == 0) @@ -137,7 +137,7 @@ void SharedLock::ReleaseLock(Lock* plock) do { oldUseCount = UseCount; - OVR_ASSERT(oldUseCount != LockInitMarker); + OVR_ASSERT(oldUseCount != (int)LockInitMarker); if (oldUseCount == 1) { diff --git a/LibOVR/Src/Kernel/OVR_Atomic.h b/LibOVR/Src/Kernel/OVR_Atomic.h index 6ef862d..47e76e0 100644 --- a/LibOVR/Src/Kernel/OVR_Atomic.h +++ b/LibOVR/Src/Kernel/OVR_Atomic.h @@ -42,6 +42,10 @@ limitations under the License. #include <pthread.h> #endif +#ifdef OVR_CC_MSVC +#include <intrin.h> +#pragma intrinsic(_ReadBarrier, _WriteBarrier, _ReadWriteBarrier) +#endif namespace OVR { @@ -118,7 +122,6 @@ struct AtomicOpsRawBase struct AcquireSync { inline AcquireSync() { } ~AcquireSync() { asm volatile("dmb\n"); } }; struct ReleaseSync { inline ReleaseSync() { asm volatile("dmb\n"); } }; - #elif defined(OVR_CC_GNU) && (__GNUC__ >= 4) // __sync functions are already full sync struct FullSync { inline FullSync() { } }; @@ -138,7 +141,7 @@ struct AtomicOpsRaw_4ByteImpl : public AtomicOpsRawBase // *** Thread - Safe Atomic Versions. -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_WIN32) // Use special defined for VC6, where volatile is not used and // InterlockedCompareExchange is declared incorrectly. @@ -403,7 +406,7 @@ struct AtomicOpsRaw_8ByteImpl : public AtomicOpsRawBase typedef uint64_t T; // *** Thread - Safe OS specific versions. -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_WIN32) // This is only for 64-bit systems. typedef LONG64 T; @@ -537,7 +540,22 @@ struct AtomicOpsRaw_DefImpl : public O #else inline static void Store_Release(volatile O_T* p, O_T val) { O_ReleaseSync sync; OVR_UNUSED(sync); *p = val; } #endif - inline static O_T Load_Acquire(const volatile O_T* p) { O_AcquireSync sync; OVR_UNUSED(sync); return *p; } + inline static O_T Load_Acquire(const volatile O_T* p) + { + O_AcquireSync sync; + OVR_UNUSED(sync); + +#if defined(OVR_CC_MSVC) + _ReadBarrier(); // Compiler fence and load barrier +#elif defined(OVR_CC_INTEL) + __memory_barrier(); // Compiler fence +#else + // GCC-compatible: + asm volatile ("" : : : "memory"); // Compiler fence +#endif + + return *p; + } }; @@ -819,7 +837,7 @@ public: inline void Unlock() { } // Windows. -#elif defined(OVR_OS_WIN32) +#elif defined(OVR_OS_WIN32) CRITICAL_SECTION cs; public: diff --git a/LibOVR/Src/Kernel/OVR_FileFILE.cpp b/LibOVR/Src/Kernel/OVR_FileFILE.cpp index 86096a9..b2a6f68 100644 --- a/LibOVR/Src/Kernel/OVR_FileFILE.cpp +++ b/LibOVR/Src/Kernel/OVR_FileFILE.cpp @@ -219,7 +219,7 @@ void FILEFile::init() else if (OpenFlags & Open_Write) omode = "r+b"; -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) SysErrorModeDisabler disabler(FileName.ToCStr()); #endif @@ -574,7 +574,7 @@ Ptr<File> FileFILEOpen(const String& path, int flags, int mode) // Helper function: obtain file information time. bool SysFile::GetFileStat(FileStat* pfileStat, const String& path) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) // 64-bit implementation on Windows. struct __stat64 fileStat; // Stat returns 0 for success. diff --git a/LibOVR/Src/Kernel/OVR_Lockless.cpp b/LibOVR/Src/Kernel/OVR_Lockless.cpp index 67c9260..c227cec 100644 --- a/LibOVR/Src/Kernel/OVR_Lockless.cpp +++ b/LibOVR/Src/Kernel/OVR_Lockless.cpp @@ -37,7 +37,7 @@ namespace OVR { namespace LocklessTest { const int TestIterations = 10000000; -// Use volatile dummys to force compiler to do spinning. +// Use volatile dummies to force compiler to do spinning. volatile int Dummy1; int Unused1[32]; volatile int Dummy2; @@ -89,7 +89,7 @@ struct TestData volatile bool FirstItemWritten = false; -LocklessUpdater<TestData> TestDataUpdater; +LocklessUpdater<TestData, TestData> TestDataUpdater; // Use this lock to verify that testing algorithm is otherwise correct... Lock TestLock; @@ -213,13 +213,10 @@ void StartLocklessTest() producerThread->Start(); consumerThread->Start(); - /* while (!producerThread->IsFinished() && consumerThread->IsFinished()) { Thread::MSleep(500); - } */ - - // TBD: Cleanup + } } diff --git a/LibOVR/Src/Kernel/OVR_Lockless.h b/LibOVR/Src/Kernel/OVR_Lockless.h index 72b6b31..400b198 100644 --- a/LibOVR/Src/Kernel/OVR_Lockless.h +++ b/LibOVR/Src/Kernel/OVR_Lockless.h @@ -59,7 +59,7 @@ public: OVR_COMPILER_ASSERT(sizeof(T) <= sizeof(SlotType)); } - T GetState() const + T GetState() const { // Copy the state out, then retry with the alternate slot // if we determine that our copy may have been partially @@ -71,9 +71,9 @@ public: { // We are adding 0, only using these as atomic memory barriers, so it // is ok to cast off the const, allowing GetState() to remain const. - end = UpdateEnd.ExchangeAdd_Sync(0); + end = UpdateEnd.Load_Acquire(); state = Slots[ end & 1 ]; - begin = UpdateBegin.ExchangeAdd_Sync(0); + begin = UpdateBegin.Load_Acquire(); if ( begin == end ) { break; } @@ -81,7 +81,7 @@ public: // The producer is potentially blocked while only having partially // written the update, so copy out the other slot. state = Slots[ (begin & 1) ^ 1 ]; - final = UpdateBegin.ExchangeAdd_NoSync(0); + final = UpdateBegin.Load_Acquire(); if ( final == begin ) { break; } @@ -100,9 +100,9 @@ public: UpdateEnd.ExchangeAdd_Sync(1); } - mutable AtomicInt<int> UpdateBegin; - mutable AtomicInt<int> UpdateEnd; - SlotType Slots[2]; + AtomicInt<int> UpdateBegin; + AtomicInt<int> UpdateEnd; + SlotType Slots[2]; }; diff --git a/LibOVR/Src/Kernel/OVR_Log.cpp b/LibOVR/Src/Kernel/OVR_Log.cpp index c81845e..7266497 100644 --- a/LibOVR/Src/Kernel/OVR_Log.cpp +++ b/LibOVR/Src/Kernel/OVR_Log.cpp @@ -29,7 +29,7 @@ limitations under the License. #include <stdarg.h> #include <stdio.h> -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) #define WIN32_LEAN_AND_MEAN #include <windows.h> #elif defined(OVR_OS_ANDROID) diff --git a/LibOVR/Src/Kernel/OVR_SharedMemory.cpp b/LibOVR/Src/Kernel/OVR_SharedMemory.cpp index b314e58..edb7931 100644 --- a/LibOVR/Src/Kernel/OVR_SharedMemory.cpp +++ b/LibOVR/Src/Kernel/OVR_SharedMemory.cpp @@ -30,8 +30,6 @@ limitations under the License. #include "OVR_String.h" #include "OVR_Array.h" -#undef new - #if defined(OVR_OS_WIN32) && !defined(OVR_FAKE_SHAREDMEMORY) #include <Sddl.h> // ConvertStringSecurityDescriptorToSecurityDescriptor #endif // OVR_OS_WIN32 diff --git a/LibOVR/Src/Kernel/OVR_SharedMemory.h b/LibOVR/Src/Kernel/OVR_SharedMemory.h index d18b583..f0ecbe6 100644 --- a/LibOVR/Src/Kernel/OVR_SharedMemory.h +++ b/LibOVR/Src/Kernel/OVR_SharedMemory.h @@ -155,14 +155,18 @@ protected: { // Configure open parameters based on read-only mode SharedMemory::OpenParameters params; - params.globalName = name; - // FIXME: This is a hack. We currently need to open this for read-write even when just reading from - // it because the LocklessUpdater class technically writes to it (increments by 0). - //params.accessMode = readOnly ? SharedMemory::AccessMode_ReadOnly : SharedMemory::AccessMode_ReadWrite; - //params.remoteMode = SharedMemory::RemoteMode_ReadOnly; - params.accessMode = SharedMemory::AccessMode_ReadWrite; - params.remoteMode = SharedMemory::RemoteMode_ReadWrite; - params.minSizeBytes = RegionSize; + + // FIXME: This is a hack. We currently need to allow clients to open this for read-write even + // though they only need read-only access. This is because in the first 0.4 release the + // LocklessUpdater class technically writes to it (increments by 0) to read from the space. + // This was quickly corrected in 0.4.1 and we are waiting for the right time to disallow write + // access when everyone upgrades to 0.4.1+. + //params.remoteMode = SharedMemory::RemoteMode_ReadOnly; + params.remoteMode = SharedMemory::RemoteMode_ReadWrite; + + params.globalName = name; + params.accessMode = readOnly ? SharedMemory::AccessMode_ReadOnly : SharedMemory::AccessMode_ReadWrite; + params.minSizeBytes = RegionSize; params.openMode = readOnly ? SharedMemory::OpenMode_OpenOnly : SharedMemory::OpenMode_CreateOrOpen; // Attempt to open the shared memory file diff --git a/LibOVR/Src/Kernel/OVR_Std.cpp b/LibOVR/Src/Kernel/OVR_Std.cpp index 5f47015..f9d1645 100644 --- a/LibOVR/Src/Kernel/OVR_Std.cpp +++ b/LibOVR/Src/Kernel/OVR_Std.cpp @@ -37,7 +37,7 @@ namespace OVR { // Case insensitive compare implemented in platform-specific way. int OVR_CDECL OVR_stricmp(const char* a, const char* b) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) return ::_stricmp(a, b); #else @@ -51,7 +51,7 @@ int OVR_CDECL OVR_stricmp(const char* a, const char* b) int OVR_CDECL OVR_strnicmp(const char* a, const char* b, size_t count) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) return ::_strnicmp(a, b, count); #else @@ -122,7 +122,7 @@ wchar_t* OVR_CDECL OVR_wcscat(wchar_t* dest, size_t destsize, const wchar_t* src size_t OVR_CDECL OVR_wcslen(const wchar_t* str) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) return wcslen(str); #else size_t i = 0; @@ -134,7 +134,7 @@ size_t OVR_CDECL OVR_wcslen(const wchar_t* str) int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) +#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) return wcscmp(a, b); #else // not supported, use custom implementation @@ -161,7 +161,7 @@ int OVR_CDECL OVR_wcscmp(const wchar_t* a, const wchar_t* b) int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) return ::_wcsicmp(a, b); #else diff --git a/LibOVR/Src/Kernel/OVR_Std.h b/LibOVR/Src/Kernel/OVR_Std.h index d421ca7..cc2de04 100644 --- a/LibOVR/Src/Kernel/OVR_Std.h +++ b/LibOVR/Src/Kernel/OVR_Std.h @@ -46,7 +46,7 @@ limitations under the License. namespace OVR { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) inline char* OVR_CDECL OVR_itoa(int val, char *dest, size_t destsize, int radix) { #if defined(OVR_MSVC_SAFESTRING) @@ -352,7 +352,7 @@ int OVR_CDECL OVR_wcsicmp(const wchar_t* a, const wchar_t* b); inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400) return ::_wcsicoll(a, b); #else @@ -366,7 +366,7 @@ inline int OVR_CDECL OVR_wcsicoll(const wchar_t* a, const wchar_t* b) inline int OVR_CDECL OVR_wcscoll(const wchar_t* a, const wchar_t* b) { -#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) +#if defined(OVR_OS_WIN32) || defined(OVR_OS_LINUX) return wcscoll(a, b); #else // not supported, use regular wcscmp diff --git a/LibOVR/Src/Kernel/OVR_String.h b/LibOVR/Src/Kernel/OVR_String.h index 25c4b68..850118a 100644 --- a/LibOVR/Src/Kernel/OVR_String.h +++ b/LibOVR/Src/Kernel/OVR_String.h @@ -192,6 +192,7 @@ public: // Returns number of characters size_t GetLength() const; + int GetLengthI() const { return (int)GetLength(); } // Returns character at the specified index uint32_t GetCharAt(size_t index) const; diff --git a/LibOVR/Src/Kernel/OVR_System.cpp b/LibOVR/Src/Kernel/OVR_System.cpp index 8fb93b5..1b8d801 100644 --- a/LibOVR/Src/Kernel/OVR_System.cpp +++ b/LibOVR/Src/Kernel/OVR_System.cpp @@ -51,25 +51,25 @@ void SystemSingletonInternal::PushDestroyCallbacks() } void System::DirectDisplayInitialize() -{ +{ #ifdef OVR_OS_WIN32 // Set up display code for Windows Win32::DisplayShim::GetInstance(); - // This code will look for the first display. If it's a display - // that's extending the destkop, the code will assume we're in - // compatibility mode. Compatibility mode prevents shim loading - // and renders only to extended Rifts. - // If we find a display and it's application exclusive, - // we load the shim so we can render to it. - // If no display is available, we revert to whatever the - // driver tells us we're in + // This code will look for the first display. If it's a display + // that's extending the destkop, the code will assume we're in + // compatibility mode. Compatibility mode prevents shim loading + // and renders only to extended Rifts. + // If we find a display and it's application exclusive, + // we load the shim so we can render to it. + // If no display is available, we revert to whatever the + // driver tells us we're in bool anyExtendedRifts = anyRiftsInExtendedMode() || Display::InCompatibilityMode( false ); Win32::DisplayShim::GetInstance().Initialize(anyExtendedRifts); #endif - } +} // Initializes System core, installing allocator. void System::Init(Log* log, Allocator *palloc) diff --git a/LibOVR/Src/Kernel/OVR_System.h b/LibOVR/Src/Kernel/OVR_System.h index 3bc2254..66ecfe9 100644 --- a/LibOVR/Src/Kernel/OVR_System.h +++ b/LibOVR/Src/Kernel/OVR_System.h @@ -111,7 +111,7 @@ template<class T> OVR::AtomicPtr<T> OVR::SystemSingletonBase<T>::SingletonInstan friend class OVR::SystemSingletonBase<T>; \ private: \ T(); \ - ~T(); \ + virtual ~T(); \ virtual void OnSystemDestroy(); // Place this in the singleton class source file diff --git a/LibOVR/Src/Kernel/OVR_Threads.h b/LibOVR/Src/Kernel/OVR_Threads.h index 0ecc152..301b84f 100644 --- a/LibOVR/Src/Kernel/OVR_Threads.h +++ b/LibOVR/Src/Kernel/OVR_Threads.h @@ -325,13 +325,13 @@ public: // and set to the return value if Run function after the thread is finished. inline int GetExitCode() const { return ExitCode; } // Returns an OS handle -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) void* GetOSHandle() const { return ThreadHandle; } #else pthread_t GetOSHandle() const { return ThreadHandle; } #endif -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) ThreadId GetThreadId() const { return IdValue; } #else ThreadId GetThreadId() const { return (ThreadId)GetOSHandle(); } @@ -369,7 +369,7 @@ protected: int Processor; ThreadPriority Priority; -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) void* ThreadHandle; volatile ThreadId IdValue; diff --git a/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp b/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp index 25c4d2b..c1a368a 100644 --- a/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp +++ b/LibOVR/Src/Kernel/OVR_ThreadsWinAPI.cpp @@ -886,9 +886,8 @@ bool Thread::Start(ThreadState initialState) ExitCode = 0; SuspendCount = 0; ThreadFlags = (initialState == Running) ? 0 : OVR_THREAD_START_SUSPENDED; - ThreadHandle = (HANDLE) _beginthreadex(0, (unsigned)StackSize, - Thread_Win32StartFn, this, 0, (unsigned*)&IdValue); + Thread_Win32StartFn, this, 0, (unsigned*)&IdValue); // Failed? Fail the function if (ThreadHandle == 0) diff --git a/LibOVR/Src/Kernel/OVR_Timer.cpp b/LibOVR/Src/Kernel/OVR_Timer.cpp index 5269106..50f4c1f 100644 --- a/LibOVR/Src/Kernel/OVR_Timer.cpp +++ b/LibOVR/Src/Kernel/OVR_Timer.cpp @@ -27,7 +27,7 @@ limitations under the License. #include "OVR_Timer.h" #include "OVR_Log.h" -#if defined (OVR_OS_WIN32) +#if defined (OVR_OS_WIN32) #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <MMSystem.h> @@ -99,7 +99,7 @@ uint64_t Timer::GetTicksNanos() //------------------------------------------------------------------------ // *** Win32 Specific Timer -#elif defined (OVR_OS_WIN32) +#elif defined (OVR_OS_WIN32) // This helper class implements high-resolution wrapper that combines timeGetTime() output @@ -154,7 +154,6 @@ PerformanceTimer Win32_PerfTimer; void PerformanceTimer::Initialize() { - MMRESULT mmr = timeBeginPeriod(1); OVR_ASSERT(TIMERR_NOERROR == mmr); OVR_UNUSED(mmr); @@ -164,13 +163,16 @@ void PerformanceTimer::Initialize() getFrequency(); // Set Vista flag. On Vista, we can just use QPC() without all the extra work - UsingVista = false; - OSVERSIONINFOA vi; - vi.dwOSVersionInfoSize = sizeof(vi); - if (GetVersionExA(&vi)) - { - UsingVista = vi.dwMajorVersion >= 6; - } + OSVERSIONINFOEX ver; + ZeroMemory(&ver, sizeof(OSVERSIONINFOEX)); + ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + ver.dwMajorVersion = 6; // Vista+ + + DWORDLONG condMask = 0; + VER_SET_CONDITION(condMask, VER_MAJORVERSION, VER_GREATER_EQUAL); + + // VerifyVersionInfo returns true if the OS meets the conditions set above + UsingVista = VerifyVersionInfo(&ver, VER_MAJORVERSION, condMask) != 0; OVR_DEBUG_LOG(("Performance timer Vista flag = %d", (int)UsingVista)); } @@ -178,7 +180,6 @@ void PerformanceTimer::Initialize() void PerformanceTimer::Shutdown() { DeleteCriticalSection(&TimeCS); - MMRESULT mmr = timeEndPeriod(1); OVR_ASSERT(TIMERR_NOERROR == mmr); OVR_UNUSED(mmr); @@ -211,6 +212,7 @@ uint64_t PerformanceTimer::GetTimeNanos() // Get raw value and perf counter "At the same time". QueryPerformanceCounter(&li); + DWORD mmTimeMs = timeGetTime(); if (OldMMTimeMs > mmTimeMs) MMTimeWrapCounter++; diff --git a/LibOVR/Src/Kernel/OVR_Types.h b/LibOVR/Src/Kernel/OVR_Types.h index 9126f78..ce8053d 100644 --- a/LibOVR/Src/Kernel/OVR_Types.h +++ b/LibOVR/Src/Kernel/OVR_Types.h @@ -30,6 +30,7 @@ limitations under the License. #include "OVR_Compiler.h" + // Unsupported compiler configurations #if _MSC_VER == 0x1600 # if _MSC_FULL_VER < 160040219 @@ -163,16 +164,6 @@ limitations under the License. # define _CRTDBG_MAP_ALLOC # include <stdlib.h> # include <crtdbg.h> - -#if 0 -// Uncomment this to help debug memory leaks under Visual Studio in OVR apps only. -// This shouldn't be defined in customer releases. -# ifndef OVR_DEFINE_NEW -# define OVR_DEFINE_NEW new(__FILE__, __LINE__) -# define new OVR_DEFINE_NEW -# endif -#endif - #endif @@ -205,7 +196,7 @@ typedef size_t UPInt; typedef ptrdiff_t SPInt; -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) typedef char SByte; // 8 bit Integer (Byte) typedef unsigned char UByte; @@ -241,6 +232,15 @@ typedef int64_t SInt64; typedef uint64_t UInt64; #endif + + +//osx PID is a signed int32 (already defined to pid_t in OSX framework) +//linux PID is a signed int32 (already defined) +//win32 PID is an unsigned int64 +#ifdef OVR_OS_WIN32 +//process ID representation +typedef unsigned long pid_t; +#endif struct OVR_GUID { @@ -306,7 +306,7 @@ struct OVR_GUID #define OVR_BIG_ENDIAN 2 -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) // ***** Win32 @@ -508,7 +508,7 @@ struct OVR_GUID #else // Microsoft Win32 specific debugging support -#if defined(OVR_OS_WIN32) +#if defined(OVR_OS_WIN32) # ifdef OVR_CPU_X86 # if defined(__cplusplus_cli) # define OVR_DEBUG_BREAK do { __debugbreak(); } while(0) @@ -578,6 +578,29 @@ struct OVR_GUID #endif +// ***** OVR_PROCESSOR_PAUSE +// +// Yields the processor for other hyperthreads, usually for the purpose of implementing spins and spin locks. +// +// Example usage: +// while(!finished()) +// OVR_PROCESSOR_PAUSE(); + +#if defined(OVR_CPU_X86) || defined(OVR_CPU_X86_64) + #if defined(OVR_CC_GNU) || defined(OVR_CC_CLANG) + #define OVR_PROCESSOR_PAUSE() asm volatile("pause" ::: "memory") // Consumes 38-40 clocks on current Intel x86 and x64 hardware. + #elif defined(OVR_CC_MSVC) + #include <emmintrin.h> + #pragma intrinsic(_mm_pause) // Maps to asm pause. + #define OVR_PROCESSOR_PAUSE _mm_pause + #else + #define OVR_PROCESSOR_PAUSE() + #endif +#else + #define OVR_PROCESSOR_PAUSE() +#endif + + // ------------------------------------------------------------------------ // ***** OVR_ARRAY_COUNT // @@ -720,5 +743,30 @@ struct OVR_GUID // +//----------------------------------------------------------------------------------- +// ***** Find normal allocations +// +// Our allocations are all supposed to go through the OVR System Allocator, so that +// they can be run through a game's own preferred allocator. Occasionally we will +// accidentally introduce new code that doesn't adhere to this contract. And it +// then becomes difficult to track down these normal allocations. This piece of +// code makes it easy to check for normal allocations by asserting whenever they +// happen in our code. + +//#define OVR_FIND_NORMAL_ALLOCATIONS +#ifdef OVR_FIND_NORMAL_ALLOCATIONS + +inline void* operator new (size_t size, const char* filename, int line) +{ + void* ptr = new char[size]; + OVR_ASSERT(false); + return ptr; +} + +#define new new(__FILE__, __LINE__) + +#endif // OVR_FIND_NORMAL_ALLOCATIONS + + #endif // OVR_Types_h diff --git a/LibOVR/Src/Net/OVR_NetworkPlugin.h b/LibOVR/Src/Net/OVR_NetworkPlugin.h index c56eda3..b5675b6 100644 --- a/LibOVR/Src/Net/OVR_NetworkPlugin.h +++ b/LibOVR/Src/Net/OVR_NetworkPlugin.h @@ -32,6 +32,7 @@ limitations under the License. namespace OVR { namespace Net { namespace Plugins { + //----------------------------------------------------------------------------- // NetworkPlugin diff --git a/LibOVR/Src/Net/OVR_RPC1.cpp b/LibOVR/Src/Net/OVR_RPC1.cpp index 0568e2f..477884c 100644 --- a/LibOVR/Src/Net/OVR_RPC1.cpp +++ b/LibOVR/Src/Net/OVR_RPC1.cpp @@ -58,7 +58,7 @@ RPC1::~RPC1() delete blockingReturnValue; } -void RPC1::RegisterSlot(OVR::String sharedIdentifier, OVR::Observer<RPCSlot> *rpcSlotObserver ) +void RPC1::RegisterSlot(OVR::String sharedIdentifier, OVR::Observer<RPCSlot>* rpcSlotObserver ) { slotHash.AddObserverToSubject(sharedIdentifier, rpcSlotObserver); } @@ -77,7 +77,7 @@ void RPC1::UnregisterBlockingFunction(OVR::String uniqueID) registeredBlockingFunctions.Remove(uniqueID); } -bool RPC1::CallBlocking( OVR::String uniqueID, OVR::Net::BitStream * bitStream, Ptr<Connection> pConnection, OVR::Net::BitStream *returnData ) +bool RPC1::CallBlocking( OVR::String uniqueID, OVR::Net::BitStream* bitStream, Ptr<Connection> pConnection, OVR::Net::BitStream* returnData ) { // If invalid parameters, if (!pConnection) @@ -133,7 +133,7 @@ bool RPC1::CallBlocking( OVR::String uniqueID, OVR::Net::BitStream * bitStream, return true; } -bool RPC1::Signal(OVR::String sharedIdentifier, OVR::Net::BitStream * bitStream, Ptr<Connection> pConnection) +bool RPC1::Signal(OVR::String sharedIdentifier, OVR::Net::BitStream* bitStream, Ptr<Connection> pConnection) { OVR::Net::BitStream out; out.Write((MessageID) OVRID_RPC1); @@ -150,7 +150,7 @@ bool RPC1::Signal(OVR::String sharedIdentifier, OVR::Net::BitStream * bitStream, int32_t bytesSent = pSession->Send(&sp); return bytesSent == sp.Bytes; } -void RPC1::BroadcastSignal(OVR::String sharedIdentifier, OVR::Net::BitStream * bitStream) +void RPC1::BroadcastSignal(OVR::String sharedIdentifier, OVR::Net::BitStream* bitStream) { OVR::Net::BitStream out; out.Write((MessageID) OVRID_RPC1); diff --git a/LibOVR/Src/Net/OVR_RPC1.h b/LibOVR/Src/Net/OVR_RPC1.h index 2e5b1db..d24f26c 100644 --- a/LibOVR/Src/Net/OVR_RPC1.h +++ b/LibOVR/Src/Net/OVR_RPC1.h @@ -44,7 +44,7 @@ typedef Delegate2<void, BitStream*, ReceivePayload*> RPCSlot; // typedef void ( *Slot ) ( OVR::Net::BitStream *userData, OVR::Net::ReceivePayload *pPayload ); /// NetworkPlugin that maps strings to function pointers. Can invoke the functions using blocking calls with return values, or signal/slots. Networked parameters serialized with BitStream -class RPC1 : public NetworkPlugin +class RPC1 : public NetworkPlugin, public NewOverrideBase { public: RPC1(); diff --git a/LibOVR/Src/Net/OVR_Session.cpp b/LibOVR/Src/Net/OVR_Session.cpp index 29c96e6..db370b4 100644 --- a/LibOVR/Src/Net/OVR_Session.cpp +++ b/LibOVR/Src/Net/OVR_Session.cpp @@ -55,10 +55,17 @@ bool RPC_C2S_Hello::Validate() HelloString.CompareNoCase(OfficialHelloString) == 0; } -void RPC_S2C_Authorization::Generate(Net::BitStream* bs) +void RPC_S2C_Authorization::Generate(Net::BitStream* bs, String errorString) { RPC_S2C_Authorization auth; - auth.AuthString = OfficialAuthorizedString; + if (errorString.IsEmpty()) + { + auth.AuthString = OfficialAuthorizedString; + } + else + { + auth.AuthString = errorString; + } auth.MajorVersion = RPCVersion_Major; auth.MinorVersion = RPCVersion_Minor; auth.PatchVersion = RPCVersion_Patch; @@ -169,17 +176,25 @@ SessionResult Session::Connect(ConnectParameters *cp) AllConnections.PushBack(c); } - + if (cp2->Blocking) { c->WaitOnConnecting(); + } - if (c->State == State_Connected) - return SessionResult_OK; - else - return SessionResult_ConnectFailure; + if (c->State == State_Connected) + { + return SessionResult_OK; } - } + else if (c->State == Client_Connecting) + { + return SessionResult_ConnectInProgress; + } + else + { + return SessionResult_ConnectFailure; + } + } else if (cp->Transport == TransportType_Loopback) { if (HasLoopbackListener) @@ -284,8 +299,10 @@ int Session::Send(SendParameters *payload) rp.pData = (uint8_t*)payload->pData; // FIXME ListenerReceiveResult lrr = LRR_CONTINUE; sl->OnReceive(&rp, &lrr); - if (lrr==LRR_RETURN) - return payload->Bytes; + if (lrr == LRR_RETURN) + { + return payload->Bytes; + } else if (lrr == LRR_BREAK) { break; @@ -522,11 +539,10 @@ void Session::TCP_OnRecv(Socket* pSocket, uint8_t* pData, int bytesRead) if (!auth.Deserialize(&bsIn) || !auth.Validate()) { + LogError("{ERR-001} [Session] REJECTED: OVRService did not authorize us: %s", auth.AuthString.ToCStr()); + conn->SetState(State_Zombie); invokeSessionEvent(&SessionListener::OnIncompatibleProtocol, conn); - - LogError("[Session] REJECTED: Server did not respond with a valid authorization message"); - AllConnections.RemoveAtUnordered(connIndex); } else { @@ -550,13 +566,16 @@ void Session::TCP_OnRecv(Socket* pSocket, uint8_t* pData, int bytesRead) if (!hello.Deserialize(&bsIn) || !hello.Validate()) { - conn->SetState(State_Zombie); - invokeSessionEvent(&SessionListener::OnIncompatibleProtocol, conn); - - LogError("[Session] REJECTED: Rift application is using an incompatible version %d.%d.%d (my version=%d.%d.%d)", + LogError("{ERR-002} [Session] REJECTED: Rift application is using an incompatible version %d.%d.%d (my version=%d.%d.%d)", hello.MajorVersion, hello.MinorVersion, hello.PatchVersion, RPCVersion_Major, RPCVersion_Minor, RPCVersion_Patch); - AllConnections.RemoveAtUnordered(connIndex); + + conn->SetState(State_Zombie); + + // Send auth response + BitStream bsOut; + RPC_S2C_Authorization::Generate(&bsOut, "Incompatible protocol version. Please make sure your OVRService and SDK are both up to date."); + conn->pSocket->Send(bsOut.GetData(), bsOut.GetNumberOfBytesUsed()); } else { @@ -612,6 +631,7 @@ void Session::TCP_OnClosed(TCPSocket* s) invokeSessionEvent(&SessionListener::OnHandshakeAttemptFailed, conn); break; case State_Connected: + case State_Zombie: invokeSessionEvent(&SessionListener::OnDisconnected, conn); break; default: diff --git a/LibOVR/Src/Net/OVR_Session.h b/LibOVR/Src/Net/OVR_Session.h index 8f709eb..8bd0b24 100644 --- a/LibOVR/Src/Net/OVR_Session.h +++ b/LibOVR/Src/Net/OVR_Session.h @@ -44,11 +44,13 @@ class Session; // Based on Semantic Versioning ( http://semver.org/ ) // // Please update changelog below: -// 1.0.0 - Initial DK2 release version (July 21, 2014) -catid +// 1.0.0 - [SDK 0.4.0] Initial version (July 21, 2014) +// 1.1.0 - Add Get/SetDriverMode_1, HMDCountUpdate_1 +// Version mismatch results (July 28, 2014) //----------------------------------------------------------------------------- static const uint16_t RPCVersion_Major = 1; // MAJOR version when you make incompatible API changes, -static const uint16_t RPCVersion_Minor = 0; // MINOR version when you add functionality in a backwards-compatible manner, and +static const uint16_t RPCVersion_Minor = 1; // MINOR version when you add functionality in a backwards-compatible manner, and static const uint16_t RPCVersion_Patch = 0; // PATCH version when you make backwards-compatible bug fixes. // Client starts communication by sending its version number. @@ -118,7 +120,7 @@ struct RPC_S2C_Authorization return bs->Read(PatchVersion); } - static void Generate(Net::BitStream* bs); + static void Generate(Net::BitStream* bs, String errorString = ""); bool Validate(); }; @@ -132,6 +134,7 @@ enum SessionResult SessionResult_BindFailure, SessionResult_ListenFailure, SessionResult_ConnectFailure, + SessionResult_ConnectInProgress, SessionResult_AlreadyConnected, }; @@ -196,28 +199,37 @@ protected: } public: - virtual void SetState(EConnectionState s) { - if (s==State) - return; + virtual void SetState(EConnectionState s) + { + if (s != State) + { + Mutex::Locker locker(&StateMutex); - Mutex::Locker locker(&StateMutex); - State = s; - if (State != Client_Connecting) - ConnectingWait.NotifyAll(); + if (s != State) + { + State = s; + + if (State != Client_Connecting) + { + ConnectingWait.NotifyAll(); + } + } + } } - void WaitOnConnecting() { + void WaitOnConnecting() + { + Mutex::Locker locker(&StateMutex); + while (State == Client_Connecting) { - Mutex::Locker locker(&StateMutex); ConnectingWait.Wait(&StateMutex); } } - SockAddr Address; - - OVR::Mutex StateMutex; - OVR::WaitCondition ConnectingWait; + SockAddr Address; + Mutex StateMutex; + WaitCondition ConnectingWait; }; diff --git a/LibOVR/Src/Net/OVR_Win32_Socket.cpp b/LibOVR/Src/Net/OVR_Win32_Socket.cpp index e2705fe..36b83ca 100644 --- a/LibOVR/Src/Net/OVR_Win32_Socket.cpp +++ b/LibOVR/Src/Net/OVR_Win32_Socket.cpp @@ -65,7 +65,7 @@ void WSAStartupSingleton::AddRef() // If an error code is returned if (errCode != 0) { - LogError("[Socket] Unable to initialize Winsock %d", errCode); + LogError("{ERR-007w} [Socket] Unable to initialize Winsock %d", errCode); } } } @@ -135,6 +135,9 @@ BitStream& operator>>(BitStream& in, SockAddr& out) SockAddr::SockAddr() { WSAStartupSingleton::AddRef(); + + // Zero out the address to squelch static analysis tools + ZeroMemory(&Addr6, sizeof(Addr6)); } SockAddr::SockAddr(SockAddr* address) @@ -197,7 +200,7 @@ void SockAddr::Set(const char* hostAddress, uint16_t port, int sockType) if (0 != errcode) { - OVR::LogError("getaddrinfo error: %s", gai_strerror(errcode)); + OVR::LogError("{ERR-008w} getaddrinfo error: %s", gai_strerror(errcode)); } OVR_ASSERT(0 != servinfo); @@ -266,25 +269,29 @@ bool SockAddr::operator<( const SockAddr& right ) const return memcmp(&Addr6, &right.Addr6, sizeof(Addr6)) < 0; } - -static void SetSocketOptions(SocketHandle sock) +static bool SetSocketOptions(SocketHandle sock) { + int result = 0; int sock_opt; // This doubles the max throughput rate sock_opt=1024*256; - setsockopt(sock, SOL_SOCKET, SO_RCVBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) ); + result |= setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char *)& sock_opt, sizeof (sock_opt)); // Immediate hard close. Don't linger the socket, or recreating the socket quickly on Vista fails. // Fail with voice sock_opt=0; - setsockopt(sock, SOL_SOCKET, SO_LINGER, ( char * ) & sock_opt, sizeof ( sock_opt ) ); + result |= setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)& sock_opt, sizeof (sock_opt)); // This doesn't make much difference: 10% maybe // Not supported on console 2 sock_opt=1024*16; - setsockopt(sock, SOL_SOCKET, SO_SNDBUF, ( char * ) & sock_opt, sizeof ( sock_opt ) ); + result |= setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char *)& sock_opt, sizeof (sock_opt)); + + // If all the setsockopt() returned 0 there were no failures, so return true for success, else false + return result == 0; } + void _Ioctlsocket(SocketHandle sock, unsigned long nonblocking) { ioctlsocket( sock, FIONBIO, &nonblocking ); @@ -311,7 +318,7 @@ static SocketHandle BindShared(int ai_family, int ai_socktype, BerkleyBindParame if (0 != errcode) { - OVR::LogError("getaddrinfo error: %s", gai_strerror(errcode)); + OVR::LogError("{ERR-020w} getaddrinfo error: %s", gai_strerror(errcode)); } for (aip = servinfo; aip != NULL; aip = aip->ai_next) @@ -319,10 +326,9 @@ static SocketHandle BindShared(int ai_family, int ai_socktype, BerkleyBindParame // Open socket. The address type depends on what // getaddrinfo() gave us. sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol); - if (sock != 0) + if (sock != INVALID_SOCKET) { - int ret = bind( sock, aip->ai_addr, (int) aip->ai_addrlen ); - if (ret>=0) + if (bind(sock, aip->ai_addr, (int)aip->ai_addrlen) != SOCKET_ERROR) { // The actual socket is always non-blocking // I control blocking or not using WSAEventSelect @@ -330,12 +336,10 @@ static SocketHandle BindShared(int ai_family, int ai_socktype, BerkleyBindParame freeaddrinfo(servinfo); return sock; } - else - { + closesocket(sock); } } - } if (servinfo) { freeaddrinfo(servinfo); } return INVALID_SOCKET; @@ -583,7 +587,7 @@ void TCPSocketPollState::HandleEvent(TCPSocket* tcpSocket, SocketEvent_TCP* even socklen_t sockAddrSize = sizeof(sockAddr); SocketHandle newSock = accept(handle, (sockaddr*)&sockAddr, (socklen_t*)&sockAddrSize); - if (newSock > 0) + if (newSock != INVALID_SOCKET) { SockAddr sa(&sockAddr); eventHandler->TCP_OnAccept(tcpSocket, &sa, newSock); diff --git a/LibOVR/Src/OVR_CAPI.cpp b/LibOVR/Src/OVR_CAPI.cpp index b9b693a..83d0583 100644 --- a/LibOVR/Src/OVR_CAPI.cpp +++ b/LibOVR/Src/OVR_CAPI.cpp @@ -110,6 +110,7 @@ TrackingState::TrackingState(const ovrTrackingState& s) LeveledCameraPose = s.LeveledCameraPose; RawSensorData = s.RawSensorData; StatusFlags = s.StatusFlags; + LastVisionProcessingTime = s.LastVisionProcessingTime; } TrackingState::operator ovrTrackingState() const @@ -120,6 +121,7 @@ TrackingState::operator ovrTrackingState() const result.LeveledCameraPose = LeveledCameraPose; result.RawSensorData = RawSensorData; result.StatusFlags = StatusFlags; + result.LastVisionProcessingTime = LastVisionProcessingTime; return result; } @@ -221,14 +223,14 @@ OVR_EXPORT double ovr_GetTimeInSeconds() // Waits until the specified absolute time. OVR_EXPORT double ovr_WaitTillTime(double absTime) { - volatile int i; double initialTime = ovr_GetTimeInSeconds(); double newTime = initialTime; while(newTime < absTime) { - for (int j = 0; j < 50; j++) - i = 0; + for (int j = 0; j < 5; j++) + OVR_PROCESSOR_PAUSE(); + newTime = ovr_GetTimeInSeconds(); } @@ -248,7 +250,7 @@ static OVR::Service::NetClient* CAPI_pNetClient = 0; OVR_EXPORT void ovr_InitializeRenderingShim() { - OVR::System::DirectDisplayInitialize(); + OVR::System::DirectDisplayInitialize(); } OVR_EXPORT ovrBool ovr_Initialize() @@ -270,7 +272,7 @@ OVR_EXPORT ovrBool ovr_Initialize() // If the server could not start running, if (Service::NetServer::GetInstance()->IsInitialized()) { - CAPI_pNetClient->Connect(); + CAPI_pNetClient->Connect(true); } else { @@ -278,13 +280,13 @@ OVR_EXPORT ovrBool ovr_Initialize() // or another SingleProcess-mode app is running in the background. // In this case, it's using the hardware and we should not also attempt to use // the hardware. - LogError("[LibOVR] Server is already running"); + LogError("{ERR-079} [LibOVR] Server is already running"); } #else - CAPI_pNetClient->Connect(); + CAPI_pNetClient->Connect(true); #endif - CAPI_ovrInitializeCalled = 1; + CAPI_ovrInitializeCalled = 1; return 1; } @@ -292,13 +294,13 @@ OVR_EXPORT ovrBool ovr_Initialize() OVR_EXPORT void ovr_Shutdown() { // We should clean up the system to be complete - if (OVR::System::IsInitialized() && CAPI_SystemInitCalled) + if (OVR::System::IsInitialized() && CAPI_SystemInitCalled) { - OVR::System::Destroy(); - } + OVR::System::Destroy(); + } CAPI_SystemInitCalled = 0; - CAPI_ovrInitializeCalled = 0; + CAPI_ovrInitializeCalled = 0; } @@ -313,10 +315,10 @@ OVR_EXPORT void ovr_Shutdown() OVR_EXPORT int ovrHmd_Detect() { - if (!CAPI_ovrInitializeCalled) + if (!CAPI_ovrInitializeCalled) return 0; - return CAPI_pNetClient->Hmd_Detect(); + return CAPI_pNetClient->Hmd_Detect(); } @@ -341,6 +343,15 @@ OVR_EXPORT ovrHmd ovrHmd_Create(int index) // If two seconds elapse and still no HMD detected, if (Timer::GetSeconds() - t0 > 2.) { + if (!NetClient::GetInstance()->IsConnected(false, false)) + { + NetClient::GetInstance()->SetLastError("Not connected to service"); + } + else + { + NetClient::GetInstance()->SetLastError("No HMD Detected"); + } + return 0; } } @@ -350,6 +361,8 @@ OVR_EXPORT ovrHmd ovrHmd_Create(int index) if (!hmds) { CAPI_pNetClient->Hmd_Release(netInfo.NetId); + + NetClient::GetInstance()->SetLastError("Unable to create HMD state"); return 0; } @@ -361,17 +374,17 @@ OVR_EXPORT ovrHmd ovrHmd_Create(int index) OVR_EXPORT ovrBool ovrHmd_AttachToWindow( ovrHmd hmd, void* window, - const ovrRecti* destMirrorRect, - const ovrRecti* sourceRenderTargetRect ) + const ovrRecti* destMirrorRect, + const ovrRecti* sourceRenderTargetRect ) { - OVR_UNUSED( destMirrorRect ); - OVR_UNUSED( sourceRenderTargetRect ); + OVR_UNUSED( destMirrorRect ); + OVR_UNUSED( sourceRenderTargetRect ); - if (!CAPI_ovrInitializeCalled) - return false; + if (!CAPI_ovrInitializeCalled) + return false; - if (!hmd || !hmd->Handle) - return false; + if (!hmd || !hmd->Handle) + return false; #ifdef OVR_OS_WIN32 HMDState* hmds = (HMDState*)hmd->Handle; @@ -379,16 +392,19 @@ OVR_EXPORT ovrBool ovrHmd_AttachToWindow( ovrHmd hmd, void* window, hmds->pWindow = window; Win32::DisplayShim::GetInstance().hWindow = (HWND)window; +#else + OVR_UNUSED(window); #endif - return true; + + return true; } OVR_EXPORT ovrHmd ovrHmd_CreateDebug(ovrHmdType type) { - if (!CAPI_ovrInitializeCalled) + if (!CAPI_ovrInitializeCalled) return 0; - HMDState* hmds = HMDState::CreateHMDState(type); + HMDState* hmds = HMDState::CreateHMDState(type); return hmds->pHmdDesc; } @@ -427,20 +443,25 @@ OVR_EXPORT const char* ovrHmd_GetLastError(ovrHmd hmddesc) return "System initialize not called"; } + VirtualHmdId netId = InvalidVirtualHmdId; + if (hmddesc && hmddesc->Handle) { HMDState* p = (HMDState*)hmddesc->Handle; - return CAPI_pNetClient->Hmd_GetLastError(p->GetNetId()); + netId = p->GetNetId(); } - return "Uninitialized Hmd"; + return CAPI_pNetClient->Hmd_GetLastError(netId); } +#define OVR_VERSION_LIBOVR_PFX "libOVR:" + // Returns version string representing libOVR version. Static, so // string remains valid for app lifespan OVR_EXPORT const char* ovr_GetVersionString() { - return "libOVR:" OVR_VERSION_STRING; + static const char* version = OVR_VERSION_LIBOVR_PFX OVR_VERSION_STRING; + return version + sizeof(OVR_VERSION_LIBOVR_PFX) - 1; } @@ -486,18 +507,18 @@ OVR_EXPORT void ovrHmd_SetEnabledCaps(ovrHmd hmddesc, unsigned int capsBits) OVR_EXPORT ovrBool ovrHmd_ConfigureTracking(ovrHmd hmddesc, unsigned int supportedCaps, unsigned int requiredCaps) { - if (hmddesc) - { + if (hmddesc) + { HMDState* p = (HMDState*)hmddesc->Handle; return p->ConfigureTracking(supportedCaps, requiredCaps); } - return 0; + return 0; } OVR_EXPORT void ovrHmd_RecenterPose(ovrHmd hmddesc) { - if (hmddesc) + if (hmddesc) { HMDState* p = (HMDState*)hmddesc->Handle; p->TheSensorStateReader.RecenterPose(); @@ -506,7 +527,7 @@ OVR_EXPORT void ovrHmd_RecenterPose(ovrHmd hmddesc) OVR_EXPORT ovrTrackingState ovrHmd_GetTrackingState(ovrHmd hmddesc, double absTime) { - ovrTrackingState result = {0}; + ovrTrackingState result = {0}; if (hmddesc) { @@ -515,11 +536,11 @@ OVR_EXPORT ovrTrackingState ovrHmd_GetTrackingState(ovrHmd hmddesc, double absTi } #ifdef OVR_OS_WIN32 - // Set up display code for Windows - Win32::DisplayShim::GetInstance().Active = (result.StatusFlags & ovrStatus_HmdConnected) != 0; + // Set up display code for Windows + Win32::DisplayShim::GetInstance().Active = (result.StatusFlags & ovrStatus_HmdConnected) != 0; #endif - return result; + return result; } @@ -530,7 +551,7 @@ OVR_EXPORT ovrTrackingState ovrHmd_GetTrackingState(ovrHmd hmddesc, double absTi OVR_EXPORT ovrSizei ovrHmd_GetFovTextureSize(ovrHmd hmddesc, ovrEyeType eye, ovrFovPort fov, float pixelsPerDisplayPixel) { - ovrHmdStruct * hmd = hmddesc->Handle; + ovrHmdStruct * hmd = hmddesc->Handle; if (!hmd) return Sizei(0); HMDState* hmds = (HMDState*)hmd; @@ -548,7 +569,7 @@ ovrBool ovrHmd_ConfigureRendering( ovrHmd hmddesc, const ovrFovPort eyeFovIn[2], ovrEyeRenderDesc eyeRenderDescOut[2] ) { - ovrHmdStruct * hmd = hmddesc->Handle; + ovrHmdStruct * hmd = hmddesc->Handle; if (!hmd) return 0; return ((HMDState*)hmd)->ConfigureRendering(eyeRenderDescOut, eyeFovIn, apiConfig, distortionCaps); @@ -559,7 +580,7 @@ ovrBool ovrHmd_ConfigureRendering( ovrHmd hmddesc, // TBD: MA - Deprecated, need alternative void ovrHmd_SetVsync(ovrHmd hmddesc, ovrBool vsync) { - ovrHmdStruct * hmd = hmddesc->Handle; + ovrHmdStruct * hmd = hmddesc->Handle; if (!hmd) return; return ((HMDState*)hmd)->TimeManager.SetVsync(vsync? true : false); @@ -604,21 +625,11 @@ OVR_EXPORT void ovrHmd_EndFrame(ovrHmd hmddesc, hmds->pRenderer->SetLatencyTestColor(hmds->LatencyTestActive ? hmds->LatencyTestDrawColor : NULL); - // TBD: Move directly into renderer - bool dk2LatencyTest = (hmds->EnabledHmdCaps & ovrHmdCap_DynamicPrediction) != 0; - if (dk2LatencyTest) - { - hmds->TimeManager.GetFrameLatencyTestDrawColor(hmds->LatencyTest2DrawColor); - hmds->pRenderer->SetLatencyTest2Color(hmds->LatencyTest2DrawColor); - } - else - { - hmds->pRenderer->SetLatencyTest2Color(NULL); - } + ovrHmd_GetLatencyTest2DrawColor(hmddesc, NULL); // We don't actually need to draw color, so send NULL if (hmds->pRenderer) - { - hmds->pRenderer->SaveGraphicsState(); + { + hmds->pRenderer->SaveGraphicsState(); // See if we need to show the HSWDisplay. if (hmds->pHSWDisplay) // Until we know that these are valid, assume any of them can't be. @@ -634,19 +645,11 @@ OVR_EXPORT void ovrHmd_EndFrame(ovrHmd hmddesc, } hmds->pRenderer->EndFrame(true); - hmds->pRenderer->RestoreGraphicsState(); + hmds->pRenderer->RestoreGraphicsState(); } // Call after present ovrHmd_EndFrameTiming(hmddesc); - if (dk2LatencyTest) - { - Util::FrameTimeRecordSet recordset; - hmds->TheLatencyTestStateReader.GetRecordSet(recordset); - hmds->TimeManager.UpdateFrameLatencyTrackingAfterEndFrame( hmds->LatencyTest2DrawColor, - recordset); - } - // Out of BeginFrame hmds->BeginFrameThreadId = 0; hmds->BeginFrameCalled = false; @@ -673,7 +676,7 @@ OVR_EXPORT void ovrHmd_RegisterPostDistortionCallback(ovrHmd hmddesc, PostDistor OVR_EXPORT ovrFrameTiming ovrHmd_GetFrameTiming(ovrHmd hmddesc, unsigned int frameIndex) { - ovrHmdStruct * hmd = hmddesc->Handle; + ovrHmdStruct * hmd = hmddesc->Handle; ovrFrameTiming f; memset(&f, 0, sizeof(f)); @@ -702,7 +705,7 @@ OVR_EXPORT ovrFrameTiming ovrHmd_GetFrameTiming(ovrHmd hmddesc, unsigned int fra OVR_EXPORT ovrFrameTiming ovrHmd_BeginFrameTiming(ovrHmd hmddesc, unsigned int frameIndex) { - ovrHmdStruct * hmd = hmddesc->Handle; + ovrHmdStruct * hmd = hmddesc->Handle; ovrFrameTiming f; memset(&f, 0, sizeof(f)); @@ -748,6 +751,15 @@ OVR_EXPORT void ovrHmd_EndFrameTiming(ovrHmd hmddesc) hmds->TimeManager.EndFrame(); hmds->BeginFrameTimingCalled = false; + + bool dk2LatencyTest = (hmds->EnabledHmdCaps & ovrHmdCap_DynamicPrediction) != 0; + if (dk2LatencyTest) + { + Util::FrameTimeRecordSet recordset; + hmds->TheLatencyTestStateReader.GetRecordSet(recordset); + hmds->TimeManager.UpdateFrameLatencyTrackingAfterEndFrame( hmds->LatencyTest2DrawColor, + recordset); + } } @@ -766,7 +778,7 @@ OVR_EXPORT void ovrHmd_ResetFrameTiming(ovrHmd hmddesc, unsigned int frameIndex ovrPosef ovrHmd_GetEyePose(ovrHmd hmd, ovrEyeType eye) { - HMDState* hmds = (HMDState*)hmd->Handle; + HMDState* hmds = (HMDState*)hmd->Handle; if (!hmds) return ovrPosef(); // This isn't a great place, but since we removed ovrHmd_BeginEyeRender... @@ -777,7 +789,7 @@ ovrPosef ovrHmd_GetEyePose(ovrHmd hmd, ovrEyeType eye) } hmds->checkBeginFrameTimingScope("ovrHmd_GetEyePose"); - return hmds->TimeManager.GetEyePredictionPose(hmd, eye); + return hmds->TimeManager.GetEyePredictionPose(hmd, eye); } @@ -788,7 +800,7 @@ OVR_EXPORT void ovrHmd_AddDistortionTimeMeasurement(ovrHmd hmddesc, double disto HMDState* hmds = (HMDState*)hmddesc->Handle; hmds->checkBeginFrameTimingScope("ovrHmd_GetTimewarpEyeMatrices"); - hmds->TimeManager.AddDistortionTimeMeasurement(distortionTimeSeconds); + hmds->TimeManager.AddDistortionTimeMeasurement(distortionTimeSeconds); } @@ -798,7 +810,7 @@ OVR_EXPORT void ovrHmd_GetEyeTimewarpMatrices(ovrHmd hmddesc, ovrEyeType eye, { if (!hmddesc) return; - HMDState* hmds = (HMDState*)hmddesc->Handle; + HMDState* hmds = (HMDState*)hmddesc->Handle; // Debug checks: BeginFrame was called, on the same thread. hmds->checkBeginFrameTimingScope("ovrHmd_GetTimewarpEyeMatrices"); @@ -845,15 +857,14 @@ OVR_EXPORT ovrBool ovrHmd_CreateDistortionMesh( ovrHmd hmddesc, ovrDistortionMesh *meshData) { // The 'internal' function below can be found in CAPI_HMDState. - // Not ideal, but navigating the convolutions of what compiles - // where, meant they are in the few places which actually lets these compile. - // Please relocate (if you wish) to a more meaningful place if you can navigate the compiler gymnastics :) - return(ovrHmd_CreateDistortionMeshInternal( hmddesc->Handle, + // Not ideal, but navigating the convolutions of what compiles + // where, meant they are in the few places which actually lets these compile. + // Please relocate (if you wish) to a more meaningful place if you can navigate the compiler gymnastics :) + return(ovrHmd_CreateDistortionMeshInternal( hmddesc->Handle, eyeType, fov, distortionCaps, meshData, - 0)); - + 0)); } @@ -916,6 +927,36 @@ OVR_EXPORT const char* ovrHmd_GetLatencyTestResult(ovrHmd hmddesc) return NetClient::GetInstance()->LatencyUtil_GetResultsString(); } +OVR_EXPORT ovrBool ovrHmd_GetLatencyTest2DrawColor(ovrHmd hmddesc, unsigned char rgbColorOut[3]) +{ + HMDState* hmds = (HMDState*)hmddesc->Handle; + if (!hmds) return false; + + // TBD: Move directly into renderer + bool dk2LatencyTest = (hmds->EnabledHmdCaps & ovrHmdCap_DynamicPrediction) != 0; + if (dk2LatencyTest) + { + hmds->TimeManager.GetFrameLatencyTestDrawColor(hmds->LatencyTest2DrawColor); + if(rgbColorOut != NULL) + { + rgbColorOut[0] = hmds->LatencyTest2DrawColor[0]; + rgbColorOut[1] = hmds->LatencyTest2DrawColor[1]; + rgbColorOut[2] = hmds->LatencyTest2DrawColor[2]; + } + + if(hmds->pRenderer != NULL) + hmds->pRenderer->SetLatencyTest2Color(hmds->LatencyTest2DrawColor); + } + else + { + if(hmds->pRenderer != NULL) + hmds->pRenderer->SetLatencyTest2Color(NULL); + } + + return dk2LatencyTest; +} + + OVR_EXPORT double ovrHmd_GetMeasuredLatencyTest2(ovrHmd hmddesc) { HMDState* p = (HMDState*)hmddesc->Handle; @@ -936,8 +977,8 @@ OVR_EXPORT void ovrHmd_GetHSWDisplayState(ovrHmd hmd, ovrHSWDisplayState *hswDis { OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle; - if (pHMDState) - { + if (pHMDState) + { OVR::CAPI::HSWDisplay* pHSWDisplay = pHMDState->pHSWDisplay; if(pHSWDisplay) @@ -949,8 +990,8 @@ OVR_EXPORT ovrBool ovrHmd_DismissHSWDisplay(ovrHmd hmd) { OVR::CAPI::HMDState* pHMDState = (OVR::CAPI::HMDState*)hmd->Handle; - if (pHMDState) - { + if (pHMDState) + { OVR::CAPI::HSWDisplay* pHSWDisplay = pHMDState->pHSWDisplay; if(pHSWDisplay) @@ -963,136 +1004,189 @@ OVR_EXPORT ovrBool ovrHmd_DismissHSWDisplay(ovrHmd hmd) // ----------------------------------------------------------------------------------- // ***** Property Access -OVR_EXPORT ovrBool ovrHmd_GetBool(ovrHmd hmddesc, const char* propertyName, ovrBool defaultVal) +OVR_EXPORT ovrBool ovrHmd_GetBool(ovrHmd hmddesc, + const char* propertyName, + ovrBool defaultVal) +{ + OVR_ASSERT(propertyName); + if (hmddesc) { - OVR_ASSERT(hmddesc && propertyName); - HMDState* hmds = (HMDState*)hmddesc->Handle; + OVR_ASSERT(hmds); if (hmds) { return hmds->getBoolValue(propertyName, (defaultVal != 0)); } + } - return defaultVal; + return NetClient::GetInstance()->GetBoolValue(InvalidVirtualHmdId, propertyName, (defaultVal != 0)) ? 1 : 0; } -OVR_EXPORT ovrBool ovrHmd_SetBool(ovrHmd hmddesc, const char* propertyName, ovrBool value) +OVR_EXPORT ovrBool ovrHmd_SetBool(ovrHmd hmddesc, + const char* propertyName, + ovrBool value) +{ + OVR_ASSERT(propertyName); + if (hmddesc) { - OVR_ASSERT(hmddesc && propertyName); - HMDState* hmds = (HMDState*)hmddesc->Handle; + OVR_ASSERT(hmds); if (hmds) { return hmds->setBoolValue(propertyName, value != 0) ? 1 : 0; } - return false; } -OVR_EXPORT int ovrHmd_GetInt(ovrHmd hmddesc, const char* propertyName, int defaultVal) -{ - OVR_ASSERT(hmddesc && propertyName); + return NetClient::GetInstance()->SetBoolValue(InvalidVirtualHmdId, propertyName, (value != 0)) ? 1 : 0; +} +OVR_EXPORT int ovrHmd_GetInt(ovrHmd hmddesc, + const char* propertyName, + int defaultVal) +{ + OVR_ASSERT(propertyName); + if (hmddesc) + { HMDState* hmds = (HMDState*)hmddesc->Handle; + OVR_ASSERT(hmds); if (hmds) { return hmds->getIntValue(propertyName, defaultVal); } + } - return defaultVal; + return NetClient::GetInstance()->GetIntValue(InvalidVirtualHmdId, propertyName, defaultVal); } -OVR_EXPORT ovrBool ovrHmd_SetInt(ovrHmd hmddesc, const char* propertyName, int value) +OVR_EXPORT ovrBool ovrHmd_SetInt(ovrHmd hmddesc, + const char* propertyName, + int value) +{ + OVR_ASSERT(propertyName); + if (hmddesc) { - OVR_ASSERT(hmddesc && propertyName); - HMDState* hmds = (HMDState*)hmddesc->Handle; + OVR_ASSERT(hmds); if (hmds) { - return hmds->setIntValue(propertyName, value); + return hmds->setIntValue(propertyName, value) ? 1 : 0; } - return false; } -OVR_EXPORT float ovrHmd_GetFloat(ovrHmd hmddesc, const char* propertyName, float defaultVal) -{ - OVR_ASSERT(hmddesc && propertyName); + return NetClient::GetInstance()->SetIntValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0; +} +OVR_EXPORT float ovrHmd_GetFloat(ovrHmd hmddesc, + const char* propertyName, + float defaultVal) +{ + OVR_ASSERT(propertyName); + if (hmddesc) + { HMDState* hmds = (HMDState*)hmddesc->Handle; + OVR_ASSERT(hmds); if (hmds) { return hmds->getFloatValue(propertyName, defaultVal); } + } - return defaultVal; + return (float)NetClient::GetInstance()->GetNumberValue(InvalidVirtualHmdId, propertyName, defaultVal); } -OVR_EXPORT ovrBool ovrHmd_SetFloat(ovrHmd hmddesc, const char* propertyName, float value) +OVR_EXPORT ovrBool ovrHmd_SetFloat(ovrHmd hmddesc, + const char* propertyName, + float value) +{ + OVR_ASSERT(propertyName); + if (hmddesc) { - OVR_ASSERT(hmddesc && propertyName); - HMDState* hmds = (HMDState*)hmddesc->Handle; + OVR_ASSERT(hmds); if (hmds) { - return hmds->setFloatValue(propertyName, value); + return hmds->setFloatValue(propertyName, value) ? 1 : 0; } - return false; } -OVR_EXPORT unsigned int ovrHmd_GetFloatArray(ovrHmd hmddesc, const char* propertyName, - float values[], unsigned int arraySize) -{ - OVR_ASSERT(hmddesc && propertyName); + return NetClient::GetInstance()->SetNumberValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0; +} +OVR_EXPORT unsigned int ovrHmd_GetFloatArray(ovrHmd hmddesc, + const char* propertyName, + float values[], + unsigned int arraySize) +{ + OVR_ASSERT(propertyName); + OVR_ASSERT(hmddesc); + if (hmddesc) + { HMDState* hmds = (HMDState*)hmddesc->Handle; + OVR_ASSERT(hmds); if (hmds) { return hmds->getFloatArray(propertyName, values, arraySize); } + } + // FIXME: Currently it takes a few lines of code to do this, so just not supported for now. return 0; } // Modify float[] property; false if property doesn't exist or is readonly. -OVR_EXPORT ovrBool ovrHmd_SetFloatArray(ovrHmd hmddesc, const char* propertyName, - float values[], unsigned int arraySize) +OVR_EXPORT ovrBool ovrHmd_SetFloatArray(ovrHmd hmddesc, + const char* propertyName, + float values[], + unsigned int arraySize) +{ + OVR_ASSERT(propertyName); + OVR_ASSERT(hmddesc); + if (hmddesc) { - OVR_ASSERT(hmddesc && propertyName); - HMDState* hmds = (HMDState*)hmddesc->Handle; + OVR_ASSERT(hmds); if (hmds) { - return hmds->setFloatArray(propertyName, values, arraySize); + return hmds->setFloatArray(propertyName, values, arraySize) ? 1 : 0; + } } + // FIXME: Currently it takes a few lines of code to do this, so just not supported for now. return 0; } -OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmddesc, const char* propertyName, +OVR_EXPORT const char* ovrHmd_GetString(ovrHmd hmddesc, + const char* propertyName, const char* defaultVal) { - OVR_ASSERT(hmddesc && propertyName); - + OVR_ASSERT(propertyName); + if (hmddesc) + { HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->getString(propertyName, defaultVal); } + } - return defaultVal; + return NetClient::GetInstance()->GetStringValue(InvalidVirtualHmdId, propertyName, defaultVal); } -OVR_EXPORT ovrBool ovrHmd_SetString(ovrHmd hmddesc, const char* propertyName, +OVR_EXPORT ovrBool ovrHmd_SetString(ovrHmd hmddesc, + const char* propertyName, const char* value) { - OVR_ASSERT(hmddesc && propertyName); - + OVR_ASSERT(propertyName); + if (hmddesc) + { HMDState* hmds = (HMDState*)hmddesc->Handle; if (hmds) { return hmds->setString(propertyName, value) ? 1 : 0; } + } - return 0; + return NetClient::GetInstance()->SetStringValue(InvalidVirtualHmdId, propertyName, value) ? 1 : 0; } diff --git a/LibOVR/Src/OVR_CAPI.h b/LibOVR/Src/OVR_CAPI.h index 2efeb15..09a06e2 100644 --- a/LibOVR/Src/OVR_CAPI.h +++ b/LibOVR/Src/OVR_CAPI.h @@ -193,6 +193,7 @@ typedef enum ovrDistortionCap_FlipInput = 0x20, /// Flip the vertical texture coordinate of input images. ovrDistortionCap_SRGB = 0x40, /// Assume input images are in sRGB gamma-corrected color space. ovrDistortionCap_Overdrive = 0x80, /// Overdrive brightness transitions to reduce artifacts on DK2+ displays + ovrDistortionCap_HqDistortion = 0x100, /// High-quality sampling of distortion buffer for anti-aliasing ovrDistortionCap_ProfileNoTimewarpSpinWaits = 0x10000, /// Use when profiling with timewarp to remove false positives } ovrDistortionCaps; @@ -319,6 +320,11 @@ typedef struct ovrTrackingState_ /// Tracking status described by ovrStatusBits. unsigned int StatusFlags; + + //// 0.4.1 + + /// Time spent processing the last vision frame + double LastVisionProcessingTime; } ovrTrackingState; @@ -465,7 +471,7 @@ extern "C" { // Either ovr_InitializeRenderingShim() or ovr_Initialize() must be called before any // Direct3D or OpenGL initilization is done by applictaion (creation of devices, etc). // ovr_Initialize() must still be called after to use the rest of LibOVR APIs. -OVR_EXPORT void ovr_InitializeRenderingShim(); +OVR_EXPORT void ovr_InitializeRenderingShim(); // Library init/shutdown, must be called around all other OVR code. // No other functions calls besides ovr_InitializeRenderingShim are allowed @@ -776,6 +782,9 @@ OVR_EXPORT ovrBool ovrHmd_ProcessLatencyTest(ovrHmd hmd, unsigned char rgbC /// Buffer is valid until next call. OVR_EXPORT const char* ovrHmd_GetLatencyTestResult(ovrHmd hmd); +/// Returns the latency testing color in rgbColorOut to render when using a DK2 +/// Returns false if this feature is disabled or not-applicable (e.g. using a DK1) +OVR_EXPORT ovrBool ovrHmd_GetLatencyTest2DrawColor(ovrHmd hmddesc, unsigned char rgbColorOut[3]); //------------------------------------------------------------------------------------- @@ -849,27 +858,30 @@ OVR_EXPORT ovrBool ovrHmd_DismissHSWDisplay(ovrHmd hmd); // For now, access profile entries; this will change. #if !defined(OVR_KEY_USER) - #define OVR_KEY_USER "User" - #define OVR_KEY_NAME "Name" - #define OVR_KEY_GENDER "Gender" - #define OVR_KEY_PLAYER_HEIGHT "PlayerHeight" - #define OVR_KEY_EYE_HEIGHT "EyeHeight" - #define OVR_KEY_IPD "IPD" - #define OVR_KEY_NECK_TO_EYE_DISTANCE "NeckEyeDistance" - - // TODO: remove this duplication with OVR_Profile.h - // Default measurements empirically determined at Oculus to make us happy - // The neck model numbers were derived as an average of the male and female averages from ANSUR-88 - // NECK_TO_EYE_HORIZONTAL = H22 - H43 = INFRAORBITALE_BACK_OF_HEAD - TRAGION_BACK_OF_HEAD - // NECK_TO_EYE_VERTICAL = H21 - H15 = GONION_TOP_OF_HEAD - ECTOORBITALE_TOP_OF_HEAD - // These were determined to be the best in a small user study, clearly beating out the previous default values - #define OVR_DEFAULT_GENDER "Unknown" - #define OVR_DEFAULT_PLAYER_HEIGHT 1.778f - #define OVR_DEFAULT_EYE_HEIGHT 1.675f - #define OVR_DEFAULT_IPD 0.064f - #define OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL 0.0805f - #define OVR_DEFAULT_NECK_TO_EYE_VERTICAL 0.075f - #define OVR_DEFAULT_EYE_RELIEF_DIAL 3 +#define OVR_KEY_USER "User" +#define OVR_KEY_NAME "Name" +#define OVR_KEY_GENDER "Gender" +#define OVR_KEY_PLAYER_HEIGHT "PlayerHeight" +#define OVR_KEY_EYE_HEIGHT "EyeHeight" +#define OVR_KEY_IPD "IPD" +#define OVR_KEY_NECK_TO_EYE_DISTANCE "NeckEyeDistance" +#define OVR_KEY_CAMERA_POSITION "CenteredFromWorld" + +// TODO: remove this duplication with OVR_Profile.h +// Default measurements empirically determined at Oculus to make us happy +// The neck model numbers were derived as an average of the male and female averages from ANSUR-88 +// NECK_TO_EYE_HORIZONTAL = H22 - H43 = INFRAORBITALE_BACK_OF_HEAD - TRAGION_BACK_OF_HEAD +// NECK_TO_EYE_VERTICAL = H21 - H15 = GONION_TOP_OF_HEAD - ECTOORBITALE_TOP_OF_HEAD +// These were determined to be the best in a small user study, clearly beating out the previous default values +#define OVR_DEFAULT_GENDER "Unknown" +#define OVR_DEFAULT_PLAYER_HEIGHT 1.778f +#define OVR_DEFAULT_EYE_HEIGHT 1.675f +#define OVR_DEFAULT_IPD 0.064f +#define OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL 0.0805f +#define OVR_DEFAULT_NECK_TO_EYE_VERTICAL 0.075f +#define OVR_DEFAULT_EYE_RELIEF_DIAL 3 +#define OVR_DEFAULT_CAMERA_POSITION {0,0,0,1,0,0,0} + #endif /// Get boolean property. Returns first element if property is a boolean array. diff --git a/LibOVR/Src/OVR_CAPI_D3D.h b/LibOVR/Src/OVR_CAPI_D3D.h index 330615d..fbbd1f5 100644 --- a/LibOVR/Src/OVR_CAPI_D3D.h +++ b/LibOVR/Src/OVR_CAPI_D3D.h @@ -41,10 +41,8 @@ limitations under the License. //----------------------------------------------------------------------------------- // ***** D3D11 Specific - #include <d3d11.h> - /// Used to configure slave D3D rendering (i.e. for devices created externally). struct ovrD3D11ConfigData { diff --git a/LibOVR/Src/OVR_Profile.cpp b/LibOVR/Src/OVR_Profile.cpp index b22477f..fdcc5ba 100644 --- a/LibOVR/Src/OVR_Profile.cpp +++ b/LibOVR/Src/OVR_Profile.cpp @@ -136,7 +136,7 @@ String GetBaseOVRPath(bool create_dir) CreateDirectory(wpath, NULL); } } - + #elif defined(OVR_OS_MAC) const char* home = getenv("HOME"); @@ -158,8 +158,7 @@ String GetBaseOVRPath(bool create_dir) #else - passwd* pwd = getpwuid(getuid()); - const char* home = pwd->pw_dir; + const char* home = getenv("HOME"); path = home; path += "/.config/Oculus"; @@ -183,7 +182,7 @@ String GetBaseOVRPath(bool create_dir) String ProfileManager::GetProfilePath() { - return BasePath + "/ProfileDB.json"; + return BasePath + "/ProfileDB.json"; } static JSON* FindTaggedData(JSON* data, const char** tag_names, const char** qtags, int num_qtags) @@ -274,10 +273,10 @@ template<> ProfileManager* OVR::SystemSingletonBase<ProfileManager>::SlowGetInst } ProfileManager::ProfileManager(bool sys_register) : - Changed(false) + Changed(false) { - // Attempt to get the base path automatically, but this may fail - BasePath = GetBaseOVRPath(false); + // Attempt to get the base path automatically, but this may fail + BasePath = GetBaseOVRPath(false); if (sys_register) PushDestroyCallbacks(); @@ -296,11 +295,11 @@ void ProfileManager::OnSystemDestroy() // In the service process it is important to set the base path because this cannot be detected automatically void ProfileManager::SetBasePath(String basePath) { - if (basePath != BasePath) - { - BasePath = basePath; - LoadCache(false); - } + if (basePath != BasePath) + { + BasePath = basePath; + LoadCache(false); + } } // Clear the local profile cache @@ -315,10 +314,10 @@ void ProfileManager::ClearProfileData() // Serializes the profiles to disk. void ProfileManager::Save() { - Lock::Locker lockScope(&ProfileLock); + Lock::Locker lockScope(&ProfileLock); - if (ProfileCache == NULL) - return; + if (ProfileCache == NULL) + return; // Save the profile to disk BasePath = GetBaseOVRPath(true); // create the base directory if it doesn't exist @@ -357,7 +356,7 @@ Profile* ProfileManager::GetDefaultProfile(HmdTypeEnum device) // TODO: These defaults are a little bogus and designed for continuity with 0.3 // eye-relief values. We need better measurement-based numbers in future releases - float max_eye_plate[2] = { 0.01965f + 0.017f, 0.01965f + 0.017f }; + float max_eye_plate[2] = { 0.01965f + 0.018f, 0.01965f + 0.018f }; profile->SetFloatValues(OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE, max_eye_plate, 2); } else @@ -789,8 +788,8 @@ bool ProfileManager::SetDefaultUser(const ProfileDeviceKey& deviceKey, const cha const char* tag_names[2] = {"Product", "Serial"}; const char* tags[2]; - const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr(); - const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr(); + const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr(); + const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr(); if (product_str && serial_str) { @@ -985,7 +984,7 @@ bool ProfileManager::SetTaggedProfile(const char** tag_names, const char** tags, //----------------------------------------------------------------------------- Profile* ProfileManager::GetDefaultUserProfile(const ProfileDeviceKey& deviceKey) { - const char* userName = GetDefaultUser(deviceKey); + const char* userName = GetDefaultUser(deviceKey); Profile* profile = GetProfile(deviceKey, userName); @@ -1009,11 +1008,11 @@ Profile* ProfileManager::GetProfile(const ProfileDeviceKey& deviceKey, const cha return NULL; } - Profile* profile = new Profile(BasePath); + Profile* profile = new Profile(BasePath); - if (deviceKey.Valid) + if (deviceKey.Valid) { - if (!profile->LoadDeviceProfile(deviceKey) && (user == NULL)) + if (!profile->LoadDeviceProfile(deviceKey) && (user == NULL)) { profile->Release(); return NULL; @@ -1022,8 +1021,8 @@ Profile* ProfileManager::GetProfile(const ProfileDeviceKey& deviceKey, const cha if (user) { - const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr(); - const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr(); + const char* product_str = deviceKey.ProductName.IsEmpty() ? NULL : deviceKey.ProductName.ToCStr(); + const char* serial_str = deviceKey.PrintedSerial.IsEmpty() ? NULL : deviceKey.PrintedSerial.ToCStr(); if (!profile->LoadProfile(ProfileCache.GetPtr(), user, product_str, serial_str)) { @@ -1084,7 +1083,7 @@ void Profile::CopyItems(JSON* root, String prefix) //----------------------------------------------------------------------------- bool Profile::LoadDeviceFile(unsigned int productId, const char* printedSerialNumber) { - if (printedSerialNumber[0] == 0) + if (printedSerialNumber[0] == 0) return false; String path = BasePath + "/Devices.json"; @@ -1115,7 +1114,7 @@ bool Profile::LoadDeviceFile(unsigned int productId, const char* printedSerialNu JSON* product_item = device->GetItemByName("ProductID"); JSON* serial_item = device->GetItemByName("Serial"); if (product_item && serial_item && - (product_item->dValue == productId) && (serial_item->Value == printedSerialNumber)) + (product_item->dValue == productId) && (serial_item->Value == printedSerialNumber)) { // found the entry for this device so recursively copy all the settings to the profile CopyItems(device, ""); @@ -1144,7 +1143,7 @@ static int BCDByte(unsigned int byte) bool Profile::LoadDeviceProfile(const ProfileDeviceKey& deviceKey) { bool success = false; - if (!deviceKey.Valid) + if (!deviceKey.Valid) return false; #if 0 @@ -1162,7 +1161,7 @@ bool Profile::LoadDeviceProfile(const ProfileDeviceKey& deviceKey) #endif // Grab the model and serial number from the device and use it to access the device // profile file stored on the local machine - success = LoadDeviceFile(deviceKey.ProductId, deviceKey.PrintedSerial); + success = LoadDeviceFile(deviceKey.ProductId, deviceKey.PrintedSerial); //} return success; @@ -1390,10 +1389,7 @@ int Profile::GetDoubleValues(const char* key, double* values, int num_vals) cons return count; } - else - { - return 0; - } + return 0; } //----------------------------------------------------------------------------- @@ -1576,7 +1572,7 @@ void Profile::SetDoubleValues(const char* key, const double* vals, int num_vals) //------------------------------------------------------------------------------ bool Profile::IsDefaultProfile() { - return 0 == OVR::String::CompareNoCase("Default", GetValue(OVR_KEY_NAME)); + return 0 == OVR::String::CompareNoCase("Default", GetValue(OVR_KEY_NAME)); } diff --git a/LibOVR/Src/OVR_Profile.h b/LibOVR/Src/OVR_Profile.h index a11e9c4..cb6a2f5 100644 --- a/LibOVR/Src/OVR_Profile.h +++ b/LibOVR/Src/OVR_Profile.h @@ -96,7 +96,7 @@ class ProfileManager : public NewOverrideBase, public SystemSingletonBase<Profil protected: ProfileManager(bool sys_register); - ~ProfileManager(); + virtual ~ProfileManager(); virtual void OnSystemDestroy(); protected: @@ -227,6 +227,7 @@ protected: #define OVR_KEY_MAX_EYE_TO_PLATE_DISTANCE "MaxEyeToPlateDist" #define OVR_KEY_EYE_CUP "EyeCup" #define OVR_KEY_CUSTOM_EYE_RENDER "CustomEyeRender" +#define OVR_KEY_CAMERA_POSITION "CenteredFromWorld" // Default measurements empirically determined at Oculus to make us happy // The neck model numbers were derived as an average of the male and female averages from ANSUR-88 @@ -240,6 +241,7 @@ protected: #define OVR_DEFAULT_NECK_TO_EYE_HORIZONTAL 0.0805f #define OVR_DEFAULT_NECK_TO_EYE_VERTICAL 0.075f #define OVR_DEFAULT_EYE_RELIEF_DIAL 3 +#define OVR_DEFAULT_CAMERA_POSITION {0,0,0,1,0,0,0} #endif // OVR_KEY_USER diff --git a/LibOVR/Src/OVR_SerialFormat.cpp b/LibOVR/Src/OVR_SerialFormat.cpp index abe68e5..027aed2 100644 --- a/LibOVR/Src/OVR_SerialFormat.cpp +++ b/LibOVR/Src/OVR_SerialFormat.cpp @@ -27,6 +27,10 @@ limitations under the License. #include "OVR_SerialFormat.h" +#ifdef SERIAL_FORMAT_UNIT_TEST +#include "Kernel/OVR_Log.h" +#endif + namespace OVR { @@ -229,7 +233,7 @@ bool DK2PrintedSerialFormat::FromBase32(const char* str, bool allowUnknownTypes) // Product Id - int productId = Base32FromChar[str[0]]; + int productId = Base32FromChar[(unsigned char)str[0]]; if (productId < 0 || (!allowUnknownTypes && !ValidDK2ProductId(productId))) { return false; @@ -239,7 +243,7 @@ bool DK2PrintedSerialFormat::FromBase32(const char* str, bool allowUnknownTypes) // Label Type - int labelType = Base32FromChar[str[1]]; + int labelType = Base32FromChar[(unsigned char)str[1]]; if (labelType < 0 || (!allowUnknownTypes && !ValidDK2PartId(labelType))) { return false; @@ -250,7 +254,7 @@ bool DK2PrintedSerialFormat::FromBase32(const char* str, bool allowUnknownTypes) uint8_t dataBytes[7]; for (int ii = 0; ii < 7; ++ii) { - int c = Base32FromChar[str[2 + ii]]; + int c = Base32FromChar[(unsigned char)str[2 + ii]]; if (c < 0) return false; dataBytes[ii] = (uint8_t)c; } @@ -267,7 +271,7 @@ bool DK2PrintedSerialFormat::FromBase32(const char* str, bool allowUnknownTypes) for (int ii = 0; ii < 3; ++ii) { - int c = Base32FromChar[str[9 + ii]]; + int c = Base32FromChar[(unsigned char)str[9 + ii]]; if (c < 0) { return false; @@ -353,90 +357,563 @@ void DK2PrintedSerialFormat::FromBinary(const DK2BinarySerialFormat& bin) } -//// Unit Tests +//// Human Strings -#ifdef SERIAL_FORMAT_UNIT_TEST +// For generator polynomial 101111b: +static const uint8_t GF32_LOG_TABLE[32] = { + 64, 31, 1, 12, 2, 24, 13, 27, 3, 8, 25, 10, 14, 18, 28, 5, + 4, 17, 9, 7, 26, 23, 11, 30, 15, 21, 19, 20, 29, 22, 6, 16 +}; +static const uint8_t GF32_ALOG_TABLE[129] = { + 1, 2, 4, 8, 16, 15, 30, 19, 9, 18, 11, 22, 3, 6, 12, 24, + 31, 17, 13, 26, 27, 25, 29, 21, 5, 10, 20, 7, 14, 28, 23, 1, + 2, 4, 8, 16, 15, 30, 19, 9, 18, 11, 22, 3, 6, 12, 24, 31, + 17, 13, 26, 27, 25, 29, 21, 5, 10, 20, 7, 14, 28, 23, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0 +}; +static const uint8_t GF32_INV_TABLE[32] = { + 0, 1, 23, 26, 28, 19, 13, 16, 14, 21, 30, 25, 17, 6, 8, 20, + 7, 12, 29, 5, 15, 9, 27, 2, 31, 11, 3, 22, 4, 18, 10, 24 +}; -int DecodeBase32(char ch) +// Multiplication in GF(32) : x * y = e^(log(x) + log(y)) +OVR_FORCE_INLINE uint8_t GF32Multiply(uint8_t x, uint8_t y) { - if (ch >= '2' && ch <= '9') - return 2 + ch - '2'; - if (ch >= 'a' && ch <= 'h') - return 10 + ch - 'a'; - if (ch >= 'A' && ch <= 'H') - return 10 + ch - 'A'; - if (ch >= 'j' && ch <= 'k') - return 18 + ch - 'j'; - if (ch >= 'J' && ch <= 'K') - return 18 + ch - 'J'; - if (ch >= 'm' && ch <= 'n') - return 20 + ch - 'm'; - if (ch >= 'M' && ch <= 'N') - return 20 + ch - 'M'; - if (ch >= 'p' && ch <= 't') - return 22 + ch - 'p'; - if (ch >= 'P' && ch <= 'T') - return 22 + ch - 'P'; - if (ch >= 'v' && ch <= 'z') - return 27 + ch - 'v'; - if (ch >= 'V' && ch <= 'Z') - return 27 + ch - 'V'; - - switch (ch) - { - case '0': - case 'o': - case 'O': - return 0; - case '1': - case 'i': - case '|': - case 'I': - case 'L': - case 'l': - return 1; - } - - return -1; + return GF32_ALOG_TABLE[GF32_LOG_TABLE[x] + GF32_LOG_TABLE[y]]; +} +OVR_FORCE_INLINE uint8_t GF32Divide(uint8_t x, uint8_t y) +{ + return GF32_ALOG_TABLE[GF32_LOG_TABLE[x] + 31 - GF32_LOG_TABLE[y]]; } -void TestSerialFormatStuff() +// Normally these inputs are constant so this is just useful for development +static bool ValidateHumanStringBits(int dataBits, int checkBits) { - for (int ii = 0; ii < 256; ++ii) - { - OVR_ASSERT(Base32FromChar[ii] == (char)DecodeBase32((char)ii)); - } + // If no data bits or data bits leave no room for a checksum, + if (dataBits < 1 || dataBits >= 160) + { + OVR_ASSERT(false); + return false; + } + + // If no check bits or check bits leave no room for a checksum, + if (checkBits < 1 || checkBits >= 160) + { + OVR_ASSERT(false); + return false; + } + // Note: It's recommended to have at least 5 check bits so that + // character typos can be caught. + + // The sum of check bits and data bits must be a multiple of 5! + if ((checkBits + dataBits) % 5 != 0) + { + OVR_ASSERT(false); + return false; + } + + // The total number of human string digits cannot exceed 32. + if ((checkBits + dataBits + 4) / 5 > 32) + { + OVR_ASSERT(false); + return false; + } + + return true; +} - DK2BinarySerialFormat sa; - sa.ProductId = DK2ProductId_DK2; - sa.PartId = DK2PartId_HMD; - sa.MinutesSinceEpoch = 65000; - sa.UnitNumber = 2; - sa.MacHash[0] = 0xa1; - sa.MacHash[1] = 0xb2; - sa.MacHash[2] = 0xc3; - sa.MacHash[3] = 0xd4; - sa.MacHash[4] = 0xe5; +// Generate check buffer +static void GenerateChecks(const uint8_t* data, int dataCount, uint8_t* checks, int checkCount, int msbCount) +{ + // For each check symbol to generate, + for (int i = 0; i < checkCount; ++i) + { + // Matrix multiplication inner loop + uint8_t x = 0; + for (int j = 0; j < dataCount; ++j) + { + // GF(32): x += d[i,j] * k, k = 1 / (j - i), ie. Cauchy matrix + x ^= GF32Multiply(data[j], GF32_INV_TABLE[(checkCount + j) ^ i]); + } + checks[i] = x; + } + + // Clear high bits of checks + if (msbCount > 0) + { + checks[checkCount - 1] &= (1 << msbCount) - 1; + } +} - uint8_t buffer[12]; - sa.ToBuffer(buffer); +// Generates a Human-readable labels with built-in checksums +// Returns false on error +bool GenerateHumanString(int dataBits, // Number of bits to store + int checkBits, // Number of extra bits of checksum data + const unsigned char* input, // Bytes stored LSB-first + const int dataBytes, // Size of data buffer in bytes + String& resultStr) // Output string +{ + if (!ValidateHumanStringBits(dataBits, checkBits)) + { + return false; + } + + // If the buffer is the wrong size, + if (dataBytes < (dataBits + 7) / 8) + { + OVR_ASSERT(false); + return false; + } + + resultStr.Clear(); + + // Copy data bits + int dataCount = (dataBits + 4) / 5; + uint8_t data[32] = { 0 }; // Initialized to zeros + for (int i = 0; i < dataBits; ++i) + { + // Grab bit + int bit = (input[i / 8] >> (i % 8)) & 1; + + // Copy to data + data[i / 5] |= bit << (i % 5); + } + + // Generate checks + int checkCount = (checkBits + 4) / 5; + uint8_t checks[32]; + GenerateChecks(data, dataCount, checks, checkCount, checkBits % 5); + + // Copy full parts of checks after the partial character (if it exists) + int fullCheckCount = checkBits / 5; + for (int i = 0; i < fullCheckCount; ++i) + { + data[dataCount + i] = checks[i]; + } + + // If there is a partial check character, + int partialCheckBits = checkBits % 5; + if (partialCheckBits > 0) + { + // Write the high bits of the partial high symbol there + int word = checks[fullCheckCount] << (5 - partialCheckBits); + word &= 0x1f; + data[dataCount - 1] |= word; + } + + // Write base-32 representation of data + int outCount = (dataBits + checkBits) / 5; + for (int i = 0; i < outCount; ++i) + { + resultStr += CharFromBase32[data[i]]; + } + + return true; +} - DK2BinarySerialFormat sb; - OVR_ASSERT(sb.FromBuffer(buffer)); +// Fix errors in data found by checks +static bool FixHumanChecksum(uint8_t* data, int dataCount, uint8_t* checks, int checkCount, int msbCount) +{ + uint8_t actualChecks[32]; + GenerateChecks(data, dataCount, actualChecks, checkCount, msbCount); + + // Search for check mismatches + int checkFails = 0; + for (int i = 0; i < checkCount; ++i) + { + if (actualChecks[i] != checks[i]) + { + ++checkFails; + } + } + + // Calculate full check count + int fullCheckCount = checkCount; + if (msbCount > 0) + { + fullCheckCount--; + } + + // If there is a lot of full check data, + if (fullCheckCount >= 2) + { + // Accept one error in the checks + if (checkFails <= 1) + { + return true; + } + + // Attempt to correct single errors: + for (int errPosition = 0; errPosition < dataCount; ++errPosition) + { + uint8_t oldData = data[errPosition]; + + // Use the first check symbol for corrections + uint8_t x = 0; + for (int j = 0; j < dataCount; ++j) + { + if (j != errPosition) + { + x ^= GF32Multiply(data[j], GF32_INV_TABLE[checkCount + j]); + } + } + x ^= checks[0]; + + // Calculate missing symbol + data[errPosition] = GF32Divide(x, GF32_INV_TABLE[checkCount + errPosition]); + + GenerateChecks(data, dataCount, actualChecks, checkCount, msbCount); + + // Search for check mismatches again: + int checkFails = 0; + for (int i = 0; i < checkCount; ++i) + { + if (actualChecks[i] != checks[i]) + { + // Ignore the partial checksum in case it got corrupted too + if (msbCount > 0 && + errPosition == dataCount - 1 && + i == checkCount - 1) + { + continue; + } + ++checkFails; + break; + } + } + + // Accept the correction if all checks agree now + if (checkFails == 0) + { + // Keep the correction if it succeeded + return true; + } + + data[errPosition] = oldData; + } + } + else + { + // Do not accept any check fails + if (checkFails <= 0) + { + return true; + } + } + + return false; +} - OVR_ASSERT(sa == sb); +// Returns number of bytes written to result, or zero on failure +int ProcessHumanString(int dataBits, // Number of bits to expect + int checkBits, // Number of extra bits of checksum data + String humanStr, // Human readable input string + unsigned char* result, // Output data buffer stored LSB-first + const int resultBytes) // Size of result buffer in bytes +{ + if (!ValidateHumanStringBits(dataBits, checkBits)) + { + return 0; + } + + // If the string is not precisely the right length, + if (humanStr.GetLengthI() != (dataBits + checkBits + 4) / 5) + { + return 0; + } + + // If the result buffer is not large enough, + int dataBytes = (dataBits + 7) / 8; + if (dataBytes > resultBytes) + { + OVR_ASSERT(false); // Programming error + return 0; + } + + // Convert human string to 5-bit symbols + uint8_t data[32]; + const char* cHumanStr = humanStr.ToCStr(); + for (int i = 0; i < humanStr.GetLengthI(); ++i) + { + char word = Base32FromChar[(unsigned char)cHumanStr[i]]; + if (word < 0) + { + // Attempt to replace invalid characters, + // and rely on error correction to fix it. + word = 0; + } + data[i] = word; + } + + // Extract checks from data + int dataCount = (dataBits + 4) / 5; + int checkCount = (checkBits + 4) / 5; + uint8_t checks[32]; + + // Copy full check characters + int fullCheckCount = checkBits / 5; + for (int i = 0; i < fullCheckCount; ++i) + { + checks[i] = data[dataCount + i]; + } + + // If there is a partial check character, + int partialCheckBits = checkBits % 5; + if (partialCheckBits > 0) + { + // Read high bits as the check high partial symbol + uint8_t word = data[dataCount - 1] >> (5 - partialCheckBits); + checks[fullCheckCount] = word; + + // Clear high bits of data that contain check bits + data[dataCount - 1] ^= word << (5 - partialCheckBits); + } + + // Fuzzy accept input + if (!FixHumanChecksum(data, (dataBits + 4) / 5, checks, checkCount, checkBits % 5)) + { + return 0; + } + + // Copy data bits to output buffer + memset(result, 0, resultBytes); + for (int i = 0; i < dataBits; ++i) + { + // Grab data bit + int bit = (data[i / 5] >> (i % 5)) & 1; + + // Write it into result + result[i / 8] |= bit << (i % 8); + } + + return dataBytes; +} - DK2PrintedSerialFormat psn; - psn.FromBinary(sb); - OVR_ASSERT(psn == sa); +//// Unit Tests - String s = psn.ToBase32(); +#ifdef SERIAL_FORMAT_UNIT_TEST - DK2PrintedSerialFormat psn2; - psn2.FromBase32(s.ToCStr()); +int DecodeBase32(char ch) +{ + if (ch >= '2' && ch <= '9') + return 2 + ch - '2'; + if (ch >= 'a' && ch <= 'h') + return 10 + ch - 'a'; + if (ch >= 'A' && ch <= 'H') + return 10 + ch - 'A'; + if (ch >= 'j' && ch <= 'k') + return 18 + ch - 'j'; + if (ch >= 'J' && ch <= 'K') + return 18 + ch - 'J'; + if (ch >= 'm' && ch <= 'n') + return 20 + ch - 'm'; + if (ch >= 'M' && ch <= 'N') + return 20 + ch - 'M'; + if (ch >= 'p' && ch <= 't') + return 22 + ch - 'p'; + if (ch >= 'P' && ch <= 'T') + return 22 + ch - 'P'; + if (ch >= 'v' && ch <= 'z') + return 27 + ch - 'v'; + if (ch >= 'V' && ch <= 'Z') + return 27 + ch - 'V'; + + switch (ch) + { + case '0': + case 'o': + case 'O': + return 0; + case '1': + case 'i': + case '|': + case 'I': + case 'L': + case 'l': + return 1; + } + + return -1; +} - OVR_ASSERT(psn == psn2); +void TestSerialFormatStuff() +{ + for (int ii = 0; ii < 256; ++ii) + { + OVR_ASSERT(Base32FromChar[ii] == (char)DecodeBase32((char)ii)); + } + + DK2BinarySerialFormat sa; + sa.ProductId = DK2ProductId_DK2; + sa.PartId = DK2PartId_HMD; + sa.MinutesSinceEpoch = 65000; + sa.UnitNumber = 2; + sa.MacHash[0] = 0xa1; + sa.MacHash[1] = 0xb2; + sa.MacHash[2] = 0xc3; + sa.MacHash[3] = 0xd4; + sa.MacHash[4] = 0xe5; + + uint8_t buffer[12]; + sa.ToBuffer(buffer); + + DK2BinarySerialFormat sb; + bool success = sb.FromBuffer(buffer); + OVR_ASSERT(success); + OVR_UNUSED(success); + + OVR_ASSERT(sa == sb); + + DK2PrintedSerialFormat psn; + psn.FromBinary(sb); + + OVR_ASSERT(psn == sa); + + String s = psn.ToBase32(); + + DK2PrintedSerialFormat psn2; + psn2.FromBase32(s.ToCStr()); + + OVR_ASSERT(psn == psn2); + + unsigned char data[32]; + unsigned char result[32]; + + int trials = 0; + int trial_failures = 0; + + for (int seed = 0; seed < 20; ++seed) + { + srand(seed); + + for (int dataBits = 1; dataBits < 160; ++dataBits) + { + for (int checkBits = 1; checkBits < 160 - dataBits; ++checkBits) + { + String human; + + int fillCheckBits = (checkBits + dataBits) % 5; + if (fillCheckBits > 0) + { + fillCheckBits = 5 - fillCheckBits + checkBits; + } + else + { + fillCheckBits = checkBits; + } + + for (int i = 0; i < sizeof(data); ++i) + { + data[i] = (unsigned char)rand(); + if (seed == 1) + { + data[i] = 0; + } + else if (seed == 0) + { + data[i] = 0xff; + } + } + + if (dataBits % 8 != 0) + { + data[dataBits / 8] &= (1 << (dataBits % 8)) - 1; + } + + if (!GenerateHumanString(dataBits, fillCheckBits, data, sizeof(data), human)) + { + OVR_ASSERT(false); + } + + int bytes = ProcessHumanString(dataBits, fillCheckBits, human, result, sizeof(result)); + + if (bytes <= 0) + { + OVR_ASSERT(false); + } + + OVR_ASSERT(bytes == (dataBits + 7) / 8); + + for (int i = 0; i < bytes; ++i) + { + OVR_ASSERT(data[i] == result[i]); + } + + // Produce maximal failures and verify that we catch them: + + if (fillCheckBits >= 5) + { + char* cstr = (char*)human.ToCStr(); + + for (int i = 0; i < fillCheckBits / 5; ++i) + { + cstr[i] ^= 1; + } + + trials++; + bytes = ProcessHumanString(dataBits, fillCheckBits, cstr, result, sizeof(result)); + + // Undo errors + for (int i = 0; i < fillCheckBits / 5; ++i) + { + cstr[i] ^= 1; + } + + if (bytes > 0) + { + for (int i = 0; i < bytes; ++i) + { + if (data[i] != result[i]) + { + trial_failures++; + break; + } + } + } + + // If enough check bits, + if (fillCheckBits >= 10) + { + // Introduce one error at all positions and verify it is corrected: + char* cstr = (char*)human.ToCStr(); + + for (int j = 0; j < human.GetLengthI(); ++j) + { + if (dataBits % 5 != 0 && j == (dataBits / 5)) + { + // Note: Corrupting a shared character + // effectively breaks two symbols at once and recovery is not possible.. + continue; + } + + cstr[j] ^= 1; + + bytes = ProcessHumanString(dataBits, fillCheckBits, cstr, result, sizeof(result)); + + OVR_ASSERT(bytes > 0); + + for (int i = 0; i < bytes; ++i) + { + OVR_ASSERT(data[i] == result[i]); + } + + cstr[j] ^= 1; + } + } + } + } + } + } + + // Allow some number of false positives in exchange for error correction + OVR_ASSERT(trial_failures <= 0.008 * trials); + + LogText("[SerialFormatUnitTest] Success: False accept rate = %d / %d\n", trial_failures, trials); } #endif // SERIAL_FORMAT_UNIT_TEST diff --git a/LibOVR/Src/OVR_SerialFormat.h b/LibOVR/Src/OVR_SerialFormat.h index 1050e74..22151f7 100644 --- a/LibOVR/Src/OVR_SerialFormat.h +++ b/LibOVR/Src/OVR_SerialFormat.h @@ -117,11 +117,28 @@ public: }; +// Generates a Human-readable labels with built-in checksums +// Returns false on error +bool GenerateHumanString(int dataBits, // Number of bits to store + int checkBits, // Number of extra bits of checksum data + const unsigned char* input, // Bytes stored LSB-first + int dataBytes, // Size of data buffer in bytes + String& resultStr); // Output string + +// Returns number of bytes written to result, or zero on failure +int ProcessHumanString(int dataBits, // Number of bits to expect + int checkBits, // Number of extra bits of checksum data + String humanStr, // Human readable input string + unsigned char* result, // Output data buffer stored LSB-first + int resultBytes); // Size of result buffer in bytes + + //#define SERIAL_FORMAT_UNIT_TEST #ifdef SERIAL_FORMAT_UNIT_TEST void TestSerialFormatStuff(); #endif + } // OVR #endif // OVR_SerialFormat_h diff --git a/LibOVR/Src/OVR_Stereo.cpp b/LibOVR/Src/OVR_Stereo.cpp index 5f4cae3..beb936b 100644 --- a/LibOVR/Src/OVR_Stereo.cpp +++ b/LibOVR/Src/OVR_Stereo.cpp @@ -1036,7 +1036,35 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI numDistortions = 0; - distortions[numDistortions].EyeRelief = 0.010f; + distortions[numDistortions].EyeRelief = 0.008f; + distortions[numDistortions].Config.MetersPerTanAngleAtCenter = 0.036f; + // TODO: Need to retune this distortion for minimum eye relief + distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10; + distortions[numDistortions].Config.K[0] = 1.003f; + distortions[numDistortions].Config.K[1] = 1.02f; + distortions[numDistortions].Config.K[2] = 1.042f; + distortions[numDistortions].Config.K[3] = 1.066f; + distortions[numDistortions].Config.K[4] = 1.094f; + distortions[numDistortions].Config.K[5] = 1.126f; + distortions[numDistortions].Config.K[6] = 1.162f; + distortions[numDistortions].Config.K[7] = 1.203f; + distortions[numDistortions].Config.K[8] = 1.25f; + distortions[numDistortions].Config.K[9] = 1.31f; + distortions[numDistortions].Config.K[10] = 1.38f; + distortions[numDistortions].MaxRadius = 1.0f; + + distortions[numDistortions].Config.ChromaticAberration[0] = -0.0112f; + distortions[numDistortions].Config.ChromaticAberration[1] = -0.015f; + distortions[numDistortions].Config.ChromaticAberration[2] = 0.0187f; + distortions[numDistortions].Config.ChromaticAberration[3] = 0.015f; + + numDistortions++; + + + + + + distortions[numDistortions].EyeRelief = 0.018f; distortions[numDistortions].Config.MetersPerTanAngleAtCenter = 0.036f; distortions[numDistortions].Config.Eqn = Distortion_CatmullRom10; @@ -1044,15 +1072,23 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI distortions[numDistortions].Config.K[1] = 1.02f; distortions[numDistortions].Config.K[2] = 1.042f; distortions[numDistortions].Config.K[3] = 1.066f; - distortions[numDistortions].Config.K[4] = 1.094f; //1.0945f; - distortions[numDistortions].Config.K[5] = 1.126f; //1.127f; - distortions[numDistortions].Config.K[6] = 1.162f; //1.167f; - distortions[numDistortions].Config.K[7] = 1.203f; //1.218f; - distortions[numDistortions].Config.K[8] = 1.25f; //1.283f; - distortions[numDistortions].Config.K[9] = 1.31f; //1.37f; - distortions[numDistortions].Config.K[10] = 1.38f; //1.48f; + distortions[numDistortions].Config.K[4] = 1.094f; + distortions[numDistortions].Config.K[5] = 1.126f; + distortions[numDistortions].Config.K[6] = 1.162f; + distortions[numDistortions].Config.K[7] = 1.203f; + distortions[numDistortions].Config.K[8] = 1.25f; + distortions[numDistortions].Config.K[9] = 1.31f; + distortions[numDistortions].Config.K[10] = 1.38f; distortions[numDistortions].MaxRadius = 1.0f; + distortions[numDistortions].Config.ChromaticAberration[0] = -0.015f; + distortions[numDistortions].Config.ChromaticAberration[1] = -0.02f; + distortions[numDistortions].Config.ChromaticAberration[2] = 0.025f; + distortions[numDistortions].Config.ChromaticAberration[3] = 0.02f; + + defaultDistortion = numDistortions; // this is the default + numDistortions++; + /* // Orange Lens on DK2 distortions[numDistortions].EyeRelief = 0.010f; @@ -1072,22 +1108,6 @@ LensConfig GenerateLensConfigFromEyeRelief ( float eyeReliefInMeters, HmdRenderI distortions[numDistortions].Config.K[10] = 1.56f; distortions[numDistortions].MaxRadius = 1.0f; */ - - defaultDistortion = numDistortions; // this is the default - numDistortions++; - - distortions[numDistortions] = distortions[0]; - distortions[numDistortions].EyeRelief = 0.020f; - numDistortions++; - - // Chromatic aberration doesn't seem to change with eye relief. - for ( int i = 0; i < numDistortions; i++ ) - { - distortions[i].Config.ChromaticAberration[0] = -0.015f; - distortions[i].Config.ChromaticAberration[1] = -0.02f; - distortions[i].Config.ChromaticAberration[2] = 0.025f; - distortions[i].Config.ChromaticAberration[3] = 0.02f; - } } else { diff --git a/LibOVR/Src/Service/Service_NetClient.cpp b/LibOVR/Src/Service/Service_NetClient.cpp index b0fa464..8c3e232 100644 --- a/LibOVR/Src/Service/Service_NetClient.cpp +++ b/LibOVR/Src/Service/Service_NetClient.cpp @@ -27,6 +27,9 @@ limitations under the License. #include "Service_NetClient.h" #include "../Net/OVR_MessageIDTypes.h" +#ifdef OVR_OS_MAC +#define GetCurrentProcessId getpid +#endif OVR_DEFINE_SINGLETON(OVR::Service::NetClient); namespace OVR { namespace Service { @@ -37,7 +40,9 @@ using namespace OVR::Net; //// NetClient NetClient::NetClient() : - LatencyTesterAvailable(false) + LatencyTesterAvailable(false), + HMDCount(0), + EdgeTriggeredHMDCount(false) { GetSession()->AddSessionListener(this); @@ -69,10 +74,14 @@ int NetClient::Run() while (!Terminated) { - if (GetSession()->GetActiveSocketsCount()==0) - Thread::MSleep(10); + // Note: There is no watchdog here because the watchdog is part of the private code GetSession()->Poll(false); + + if (GetSession()->GetActiveSocketsCount() == 0) + { + Thread::MSleep(10); + } } return 0; @@ -82,7 +91,6 @@ void NetClient::OnReceive(ReceivePayload* pPayload, ListenerReceiveResult* lrrOu { OVR_UNUSED(lrrOut); OVR_UNUSED(pPayload); - } void NetClient::OnDisconnected(Connection* conn) @@ -90,13 +98,8 @@ void NetClient::OnDisconnected(Connection* conn) OVR_UNUSED(conn); OVR_DEBUG_LOG(("[NetClient] Disconnected")); -} -void NetClient::OnConnectionAttemptFailed(Net::Connection* conn) -{ - OVR_UNUSED(conn); - - OVR_DEBUG_LOG(("[NetClient] OnConnectionAttemptFailed")); + EdgeTriggeredHMDCount = false; } void NetClient::OnConnected(Connection* conn) @@ -106,9 +109,11 @@ void NetClient::OnConnected(Connection* conn) OVR_DEBUG_LOG(("[NetClient] Connected to a server running version %d.%d.%d (my version=%d.%d.%d)", conn->RemoteMajorVersion, conn->RemoteMinorVersion, conn->RemotePatchVersion, RPCVersion_Major, RPCVersion_Minor, RPCVersion_Patch)); + + EdgeTriggeredHMDCount = false; } -bool NetClient::Connect() +bool NetClient::Connect(bool blocking) { // Set up bind parameters OVR::Net::BerkleyBindParameters bbp; @@ -118,7 +123,12 @@ bool NetClient::Connect() sa.Set("::1", VRServicePort, SOCK_STREAM); // Attempt to connect - return GetSession()->ConnectPTCP(&bbp, &sa, true) == Net::SessionResult_OK; + OVR::Net::SessionResult result = GetSession()->ConnectPTCP(&bbp, &sa, blocking); + + // Already connected counts as success too + return result == Net::SessionResult_OK || + result == Net::SessionResult_AlreadyConnected || + result == Net::SessionResult_ConnectInProgress; } void NetClient::Disconnect() @@ -126,7 +136,7 @@ void NetClient::Disconnect() GetSession()->Shutdown(); } -bool NetClient::IsConnected(bool attemptReconnect) +bool NetClient::IsConnected(bool attemptReconnect, bool blockOnReconnect) { // If it was able to connect, if (GetSession()->GetConnectionCount() > 0) @@ -136,7 +146,7 @@ bool NetClient::IsConnected(bool attemptReconnect) else if (attemptReconnect) { // Attempt to connect here - Connect(); + Connect(blockOnReconnect); // If it connected, if (GetSession()->GetConnectionCount() > 0) @@ -176,8 +186,10 @@ bool NetClient::GetRemoteProtocolVersion(int& major, int& minor, int& patch) const char* NetClient::GetStringValue(VirtualHmdId hmd, const char* key, const char* default_val) { - if (!IsConnected(true)) + if (!IsConnected(true, true)) + { return ""; + } ProfileGetValue1_Str = default_val; @@ -197,8 +209,10 @@ const char* NetClient::GetStringValue(VirtualHmdId hmd, const char* key, const c } bool NetClient::GetBoolValue(VirtualHmdId hmd, const char* key, bool default_val) { - if (!IsConnected(true)) + if (!IsConnected(true, true)) + { return default_val; + } OVR::Net::BitStream bsOut, returnData; bsOut.Write(hmd); @@ -217,8 +231,10 @@ bool NetClient::GetBoolValue(VirtualHmdId hmd, const char* key, bool default_val } int NetClient::GetIntValue(VirtualHmdId hmd, const char* key, int default_val) { - if (!IsConnected(true)) + if (!IsConnected(true, true)) + { return default_val; + } OVR::Net::BitStream bsOut, returnData; bsOut.Write(hmd); @@ -237,8 +253,10 @@ int NetClient::GetIntValue(VirtualHmdId hmd, const char* key, int default_val) } double NetClient::GetNumberValue(VirtualHmdId hmd, const char* key, double default_val) { - if (!IsConnected(true)) + if (!IsConnected(true, true)) + { return default_val; + } OVR::Net::BitStream bsOut, returnData; bsOut.Write(hmd); @@ -254,8 +272,10 @@ double NetClient::GetNumberValue(VirtualHmdId hmd, const char* key, double defau } int NetClient::GetNumberValues(VirtualHmdId hmd, const char* key, double* values, int num_vals) { - if (!IsConnected(true)) + if (!IsConnected(true, true)) + { return 0; + } OVR::Net::BitStream bsOut, returnData; bsOut.Write(hmd); @@ -294,10 +314,13 @@ int NetClient::GetNumberValues(VirtualHmdId hmd, const char* key, double* values return out; } -void NetClient::SetStringValue(VirtualHmdId hmd, const char* key, const char* val) + +bool NetClient::SetStringValue(VirtualHmdId hmd, const char* key, const char* val) { - if (!IsConnected(true)) - return; + if (!IsConnected(true, true)) + { + return false; + } OVR::Net::BitStream bsOut; bsOut.Write(hmd); @@ -308,12 +331,18 @@ void NetClient::SetStringValue(VirtualHmdId hmd, const char* key, const char* va if (!GetRPC1()->Signal("SetStringValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0))) { OVR_ASSERT(false); + return false; } + + return true; } -void NetClient::SetBoolValue(VirtualHmdId hmd, const char* key, bool val) + +bool NetClient::SetBoolValue(VirtualHmdId hmd, const char* key, bool val) { - if (!IsConnected(true)) - return; + if (!IsConnected(true, true)) + { + return false; + } OVR::Net::BitStream bsOut; bsOut.Write(hmd); @@ -325,12 +354,18 @@ void NetClient::SetBoolValue(VirtualHmdId hmd, const char* key, bool val) if (!GetRPC1()->Signal("SetBoolValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0))) { OVR_ASSERT(false); + return false; } + + return true; } -void NetClient::SetIntValue(VirtualHmdId hmd, const char* key, int val) + +bool NetClient::SetIntValue(VirtualHmdId hmd, const char* key, int val) { - if (!IsConnected(true)) - return; + if (!IsConnected(true, true)) + { + return false; + } OVR::Net::BitStream bsOut; bsOut.Write(hmd); @@ -342,12 +377,18 @@ void NetClient::SetIntValue(VirtualHmdId hmd, const char* key, int val) if (!GetRPC1()->Signal("SetIntValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0))) { OVR_ASSERT(false); + return false; } + + return true; } -void NetClient::SetNumberValue(VirtualHmdId hmd, const char* key, double val) + +bool NetClient::SetNumberValue(VirtualHmdId hmd, const char* key, double val) { - if (!IsConnected(true)) - return; + if (!IsConnected(true, true)) + { + return false; + } OVR::Net::BitStream bsOut; bsOut.Write(hmd); @@ -358,13 +399,17 @@ void NetClient::SetNumberValue(VirtualHmdId hmd, const char* key, double val) if (!GetRPC1()->Signal("SetNumberValue_1", &bsOut, GetSession()->GetConnectionAtIndex(0))) { OVR_ASSERT(false); + return false; } + + return true; } -void NetClient::SetNumberValues(VirtualHmdId hmd, const char* key, const double* vals, int num_vals) + +bool NetClient::SetNumberValues(VirtualHmdId hmd, const char* key, const double* vals, int num_vals) { - if (!IsConnected(true)) + if (!IsConnected(true, true)) { - return; + return false; } OVR::Net::BitStream bsOut; @@ -382,16 +427,28 @@ void NetClient::SetNumberValues(VirtualHmdId hmd, const char* key, const double* if (!GetRPC1()->Signal("SetNumberValues_1", &bsOut, GetSession()->GetConnectionAtIndex(0))) { OVR_ASSERT(false); + return false; } + + return true; } int NetClient::Hmd_Detect() { - if (!IsConnected(true)) + if (!IsConnected(true, false)) { return 0; } + // If using edge-triggered HMD counting, + if (EdgeTriggeredHMDCount) + { + // Return the last update from the server + return HMDCount; + } + + // Otherwise: We need to ask the first time + OVR::Net::BitStream bsOut, returnData; if (!GetRPC1()->CallBlocking("Hmd_Detect_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) @@ -405,12 +462,14 @@ int NetClient::Hmd_Detect() { OVR_ASSERT(false); } + HMDCount = out; + EdgeTriggeredHMDCount = true; return out; } bool NetClient::Hmd_Create(int index, HMDNetworkInfo* netInfo) { - if (!IsConnected(true)) + if (!IsConnected(true, true)) { return false; } @@ -420,9 +479,9 @@ bool NetClient::Hmd_Create(int index, HMDNetworkInfo* netInfo) int32_t w = (int32_t)index; bsOut.Write(w); -#ifdef OVR_OS_WIN32 +#if defined(OVR_OS_WIN32) || defined(OVR_OS_MAC) // Need the Pid for driver mode - DWORD pid = GetCurrentProcessId(); + pid_t pid = GetCurrentProcessId(); bsOut.Write(pid); #endif @@ -435,10 +494,78 @@ bool NetClient::Hmd_Create(int index, HMDNetworkInfo* netInfo) return netInfo->Deserialize(&returnData); } -void NetClient::Hmd_AttachToWindow(VirtualHmdId hmd, void* hWindow) +bool NetClient::GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode) { - if (!IsConnected()) - return; + if (!IsConnected(true, true)) + { + return false; + } + + OVR::Net::BitStream bsOut, returnData; + + bsOut.Write(InvalidVirtualHmdId); + + if (!GetRPC1()->CallBlocking("GetDriverMode_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) + { + OVR_ASSERT(false); + return false; + } + + int32_t w_driverInstalled = 0; + int32_t w_compatMode = 0; + int32_t w_hideDK1Mode = 0; + returnData.Read(w_driverInstalled); + returnData.Read(w_compatMode); + if (!returnData.Read(w_hideDK1Mode)) + { + return false; + } + + driverInstalled = w_driverInstalled != 0; + compatMode = w_compatMode != 0; + hideDK1Mode = w_hideDK1Mode != 0; + return true; +} + +bool NetClient::SetDriverMode(bool compatMode, bool hideDK1Mode) +{ + if (!IsConnected(true, true)) + { + return false; + } + + OVR::Net::BitStream bsOut, returnData; + + bsOut.Write(InvalidVirtualHmdId); + + int32_t w_compatMode, w_hideDK1Mode; + w_compatMode = compatMode ? 1 : 0; + w_hideDK1Mode = hideDK1Mode ? 1 : 0; + bsOut.Write(w_compatMode); + bsOut.Write(w_hideDK1Mode); + + if (!GetRPC1()->CallBlocking("SetDriverMode_1", &bsOut, GetSession()->GetConnectionAtIndex(0), &returnData)) + { + OVR_ASSERT(false); + return false; + } + + int32_t out = 0; + if (!returnData.Read(out)) + { + OVR_ASSERT(false); + return false; + } + + return out != 0; +} + +bool NetClient::Hmd_AttachToWindow(VirtualHmdId hmd, void* hWindow) +{ + if (!IsConnected(false, false)) + { + return false; + } OVR::Net::BitStream bsOut; bsOut.Write(hmd); @@ -449,13 +576,18 @@ void NetClient::Hmd_AttachToWindow(VirtualHmdId hmd, void* hWindow) if (!GetRPC1()->CallBlocking("Hmd_AttachToWindow_1", &bsOut, GetSession()->GetConnectionAtIndex(0))) { OVR_ASSERT(false); + return false; } + + return true; } void NetClient::Hmd_Release(VirtualHmdId hmd) { - if (!IsConnected()) - return; + if (!IsConnected(false, false)) + { + return; + } OVR::Net::BitStream bsOut; bsOut.Write(hmd); @@ -465,10 +597,15 @@ void NetClient::Hmd_Release(VirtualHmdId hmd) } } +void NetClient::SetLastError(String str) +{ + Hmd_GetLastError_Str = str; +} + // Last string is cached locally. const char* NetClient::Hmd_GetLastError(VirtualHmdId hmd) { - if (!IsConnected()) + if (hmd == InvalidVirtualHmdId || !IsConnected(false, false)) { return Hmd_GetLastError_Str.ToCStr(); } @@ -492,7 +629,7 @@ const char* NetClient::Hmd_GetLastError(VirtualHmdId hmd) // The actual descriptor is a par bool NetClient::Hmd_GetHmdInfo(VirtualHmdId hmd, HMDInfo* hmdInfo) { - if (!IsConnected()) + if (!IsConnected(false, false)) { return false; } @@ -512,7 +649,7 @@ bool NetClient::Hmd_GetHmdInfo(VirtualHmdId hmd, HMDInfo* hmdInfo) //------------------------------------------------------------------------------------- unsigned int NetClient::Hmd_GetEnabledCaps(VirtualHmdId hmd) { - if (!IsConnected()) + if (!IsConnected(false, false)) { return 0; } @@ -536,7 +673,7 @@ unsigned int NetClient::Hmd_GetEnabledCaps(VirtualHmdId hmd) // Returns new caps after modification unsigned int NetClient::Hmd_SetEnabledCaps(VirtualHmdId hmd, unsigned int hmdCaps) { - if (!IsConnected()) + if (!IsConnected(false, false)) { return 0; } @@ -567,7 +704,7 @@ unsigned int NetClient::Hmd_SetEnabledCaps(VirtualHmdId hmd, unsigned int hmdCap bool NetClient::Hmd_ConfigureTracking(VirtualHmdId hmd, unsigned supportedCaps, unsigned requiredCaps) { - if (!IsConnected()) + if (!IsConnected(false, false)) { return false; } @@ -598,7 +735,7 @@ bool NetClient::Hmd_ConfigureTracking(VirtualHmdId hmd, unsigned supportedCaps, void NetClient::Hmd_ResetTracking(VirtualHmdId hmd) { - if (!IsConnected()) + if (!IsConnected(false, false)) { return; } @@ -614,7 +751,7 @@ void NetClient::Hmd_ResetTracking(VirtualHmdId hmd) bool NetClient::LatencyUtil_ProcessInputs(double startTestSeconds, unsigned char rgbColorOut[3]) { - if (!IsConnected()) + if (!IsConnected(false, false)) { return false; } @@ -648,7 +785,7 @@ bool NetClient::LatencyUtil_ProcessInputs(double startTestSeconds, unsigned char const char* NetClient::LatencyUtil_GetResultsString() { - if (!IsConnected()) + if (!IsConnected(false, false)) { return NULL; } @@ -670,7 +807,7 @@ const char* NetClient::LatencyUtil_GetResultsString() bool NetClient::ShutdownServer() { - if (!IsConnected()) + if (!IsConnected(false, false)) { return false; } @@ -692,7 +829,7 @@ void NetClient::registerRPC() // Register RPC functions: RPC_REGISTER_SLOT(InitialServerStateScope, InitialServerState_1); RPC_REGISTER_SLOT(LatencyTesterAvailableScope, LatencyTesterAvailable_1); - + RPC_REGISTER_SLOT(HMDCountUpdateScope, HMDCountUpdate_1); } void NetClient::InitialServerState_1(BitStream* userData, ReceivePayload* pPayload) @@ -714,6 +851,20 @@ void NetClient::LatencyTesterAvailable_1(BitStream* userData, ReceivePayload* pP LatencyTesterAvailable = (b != 0); } +void NetClient::HMDCountUpdate_1(BitStream* userData, ReceivePayload* pPayload) +{ + OVR_UNUSED(pPayload); + + int32_t hmdCount = 0; + if (!userData->Read(hmdCount)) + { + OVR_ASSERT(false); + return; + } + + HMDCount = hmdCount; + EdgeTriggeredHMDCount = true; +} }} // namespace OVR::Service diff --git a/LibOVR/Src/Service/Service_NetClient.h b/LibOVR/Src/Service/Service_NetClient.h index 6be6de8..96a8ad9 100644 --- a/LibOVR/Src/Service/Service_NetClient.h +++ b/LibOVR/Src/Service/Service_NetClient.h @@ -50,35 +50,42 @@ class NetClient : public NetSessionCommon, // Status bool LatencyTesterAvailable; + int HMDCount; + bool EdgeTriggeredHMDCount; virtual void OnReceive(Net::ReceivePayload* pPayload, Net::ListenerReceiveResult* lrrOut); virtual void OnDisconnected(Net::Connection* conn); virtual void OnConnected(Net::Connection* conn); - virtual void OnConnectionAttemptFailed(Net::Connection* conn); virtual int Run(); public: - bool Connect(); - bool IsConnected(bool attemptReconnect = false); + bool Connect(bool blocking); + bool IsConnected(bool attemptReconnect, bool blockOnReconnect); void Disconnect(); void GetLocalProtocolVersion(int& major, int& minor, int& patch); // This function may fail if it is not connected bool GetRemoteProtocolVersion(int& major, int& minor, int& patch); + void SetLastError(String str); + public: - // Key-value storage + // Persistent key-value storage const char* GetStringValue(VirtualHmdId hmd, const char* key, const char* default_val); bool GetBoolValue(VirtualHmdId hmd, const char* key, bool default_val); int GetIntValue(VirtualHmdId hmd, const char* key, int default_val); double GetNumberValue(VirtualHmdId hmd, const char* key, double default_val); int GetNumberValues(VirtualHmdId hmd, const char* key, double* values, int num_vals); - void SetStringValue(VirtualHmdId hmd, const char* key, const char* val); - void SetBoolValue(VirtualHmdId hmd, const char* key, bool val); - void SetIntValue(VirtualHmdId hmd, const char* key, int val); - void SetNumberValue(VirtualHmdId hmd, const char* key, double val); - void SetNumberValues(VirtualHmdId hmd, const char* key, const double* vals, int num_vals); + + bool SetStringValue(VirtualHmdId hmd, const char* key, const char* val); + bool SetBoolValue(VirtualHmdId hmd, const char* key, bool val); + bool SetIntValue(VirtualHmdId hmd, const char* key, int val); + bool SetNumberValue(VirtualHmdId hmd, const char* key, double val); + bool SetNumberValues(VirtualHmdId hmd, const char* key, const double* vals, int num_vals); + + bool GetDriverMode(bool& driverInstalled, bool& compatMode, bool& hideDK1Mode); + bool SetDriverMode(bool compatMode, bool hideDK1Mode); int Hmd_Detect(); bool Hmd_Create(int index, HMDNetworkInfo* netInfo); @@ -99,7 +106,7 @@ public: unsigned int Hmd_SetEnabledCaps(VirtualHmdId hmd, unsigned int hmdCaps); // Updates driver render target - void Hmd_AttachToWindow(VirtualHmdId hmd, void* hWindow); + bool Hmd_AttachToWindow(VirtualHmdId hmd, void* hWindow); //------------------------------------------------------------------------------------- // *** Tracking Setup @@ -123,11 +130,14 @@ protected: void registerRPC(); - ObserverScope<OVR::Net::Plugins::RPCSlot> InitialServerStateScope; + ObserverScope<Net::Plugins::RPCSlot> InitialServerStateScope; void InitialServerState_1(BitStream* userData, ReceivePayload* pPayload); - ObserverScope<OVR::Net::Plugins::RPCSlot> LatencyTesterAvailableScope; + ObserverScope<Net::Plugins::RPCSlot> LatencyTesterAvailableScope; void LatencyTesterAvailable_1(BitStream* userData, ReceivePayload* pPayload); + + ObserverScope<Net::Plugins::RPCSlot> HMDCountUpdateScope; + void HMDCountUpdate_1(BitStream* userData, ReceivePayload* pPayload); }; diff --git a/LibOVR/Src/Tracking/Tracking_PoseState.h b/LibOVR/Src/Tracking/Tracking_PoseState.h index c22395c..393d483 100644 --- a/LibOVR/Src/Tracking/Tracking_PoseState.h +++ b/LibOVR/Src/Tracking/Tracking_PoseState.h @@ -43,7 +43,7 @@ public: typedef typename CompatibleTypes<Pose<T> >::Type CompatibleType; PoseState() : TimeInSeconds(0.0) { } - PoseState(Pose<T> pose, double time) : TimeInSeconds(time), ThePose(pose) { } + PoseState(Pose<T> pose, double time) : ThePose(pose), TimeInSeconds(time) { } // float <-> double conversion constructor. explicit PoseState(const PoseState<typename Math<T>::OtherFloatType> &src) diff --git a/LibOVR/Src/Tracking/Tracking_SensorState.h b/LibOVR/Src/Tracking/Tracking_SensorState.h index 12072c0..b7c87ea 100644 --- a/LibOVR/Src/Tracking/Tracking_SensorState.h +++ b/LibOVR/Src/Tracking/Tracking_SensorState.h @@ -89,6 +89,11 @@ public: // Sensor status described by ovrStatusBits. uint32_t StatusFlags; + + //// 0.4.1 + + // Time spent processing the last vision frame + double LastVisionProcessingTime; }; @@ -110,6 +115,7 @@ struct LocklessSensorState // ImuFromCpf for HMD pose tracking Posed ImuFromCpf; + double LastVisionProcessingTime; // Initialized to invalid state LocklessSensorState() : @@ -119,7 +125,7 @@ struct LocklessSensorState LocklessSensorState& operator = (const LocklessSensorStatePadding& rhs); }; - + // Padded out version stored in the updater slots // Designed to be a larger fixed size to allow the data to grow in the future // without breaking older compiled code. diff --git a/LibOVR/Src/Tracking/Tracking_SensorStateReader.cpp b/LibOVR/Src/Tracking/Tracking_SensorStateReader.cpp index b290480..bad4ffc 100644 --- a/LibOVR/Src/Tracking/Tracking_SensorStateReader.cpp +++ b/LibOVR/Src/Tracking/Tracking_SensorStateReader.cpp @@ -98,7 +98,6 @@ void SensorStateReader::RecenterPose() const LocklessSensorState lstate = Updater->SharedSensorState.GetState(); Posed worldFromCpf = lstate.WorldFromImu.ThePose * lstate.ImuFromCpf; - double hmdYaw, hmdPitch, hmdRoll; worldFromCpf.Rotation.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(&hmdYaw, &hmdPitch, &hmdRoll); @@ -138,7 +137,7 @@ bool SensorStateReader::GetSensorStateAtTime(double absoluteTime, TrackingState& return false; } - // Delta time from the last available data + // Delta time from the last available data double pdt = absoluteTime - lstate.WorldFromImu.TimeInSeconds; static const double maxPdt = 0.1; @@ -167,6 +166,7 @@ bool SensorStateReader::GetSensorStateAtTime(double absoluteTime, TrackingState& ss.LeveledCameraPose = Posef(CenteredFromWorld * worldFromLeveledCamera); ss.RawSensorData = lstate.RawSensorData; + ss.LastVisionProcessingTime = lstate.LastVisionProcessingTime; return true; } @@ -203,5 +203,28 @@ uint32_t SensorStateReader::GetStatus() const return lstate.StatusFlags; } +void SensorStateReader::LoadProfileCenteredFromWorld(Profile* profile) +{ + double camerastate[7]; + if (profile->GetDoubleValues(OVR_KEY_CAMERA_POSITION, camerastate, 7) == 0) + { + for (int i = 0; i < 7; i++) camerastate[i] = 0; + camerastate[3] = 1;//no offset. by default, give the quaternion w component value 1 + } + + OVR::Quatd orientation = OVR::Quatd(camerastate[0], camerastate[1], camerastate[2], camerastate[3]); + OVR::Vector3d position = OVR::Vector3d(camerastate[4], camerastate[5], camerastate[6]); + + CenteredFromWorld = OVR::Posed(orientation, position); + +} + +void SensorStateReader::SaveProfileCenteredFromWorld(Profile* profile) +{ + OVR::Quatd rot = CenteredFromWorld.Rotation; + OVR::Vector3d trans = CenteredFromWorld.Translation; + double vals[7] = { rot.x, rot.y, rot.z, rot.w, trans.x, trans.y, trans.z }; + profile->SetDoubleValues(OVR_KEY_CAMERA_POSITION, vals, 7); +} }} // namespace OVR::Tracking diff --git a/LibOVR/Src/Tracking/Tracking_SensorStateReader.h b/LibOVR/Src/Tracking/Tracking_SensorStateReader.h index f1aa5f9..53b6efe 100644 --- a/LibOVR/Src/Tracking/Tracking_SensorStateReader.h +++ b/LibOVR/Src/Tracking/Tracking_SensorStateReader.h @@ -30,6 +30,8 @@ limitations under the License. #include "../Kernel/OVR_Lockless.h" #include "Tracking_SensorState.h" +#include "../OVR_Profile.h" + namespace OVR { namespace Tracking { @@ -42,12 +44,13 @@ class SensorStateReader : public NewOverrideBase protected: const CombinedSharedStateUpdater *Updater; - // Transform from real-world coordinates to centered coordinates - Posed CenteredFromWorld; // Last latency warning time mutable double LastLatWarnTime; + // Transform from real-world coordinates to centered coordinates + Posed CenteredFromWorld; + public: SensorStateReader(); @@ -66,6 +69,9 @@ public: // Get the sensor status (same as GetSensorStateAtTime(...).Status) uint32_t GetStatus() const; + + void LoadProfileCenteredFromWorld(Profile* profile); + void SaveProfileCenteredFromWorld(Profile* profile); }; diff --git a/LibOVR/Src/Util/Util_LongPollThread.cpp b/LibOVR/Src/Util/Util_LongPollThread.cpp deleted file mode 100644 index c7c5c5d..0000000 --- a/LibOVR/Src/Util/Util_LongPollThread.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/************************************************************************************ - -Filename : Util_LongPollThread.cpp -Content : Allows us to do all long polling tasks from a single thread to minimize deadlock risk -Created : June 30, 2013 -Authors : Chris Taylor - -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. - -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); -you may not use the Oculus VR Rift SDK except in compliance with the License, -which is provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -You may obtain a copy of the License at - -http://www.oculusvr.com/licenses/LICENSE-3.1 - -Unless required by applicable law or agreed to in writing, the Oculus VR SDK -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -*************************************************************************************/ - -#include "Util_LongPollThread.h" -#include "Util_Watchdog.h" - -OVR_DEFINE_SINGLETON(OVR::Util::LongPollThread); - -namespace OVR { namespace Util { - - -void LongPollThread::AddPollFunc(Observer<PollFunc>* func) -{ - func->Observe(PollSubject); -} - -LongPollThread::LongPollThread() : - Terminated(false) -{ - Start(); - - PushDestroyCallbacks(); -} - -LongPollThread::~LongPollThread() -{ - fireTermination(); - - Join(); -} - -void LongPollThread::OnThreadDestroy() -{ - fireTermination(); -} - -void LongPollThread::Wake() -{ - WakeEvent.SetEvent(); -} - -void LongPollThread::fireTermination() -{ - Terminated = true; - Wake(); -} - -void LongPollThread::OnSystemDestroy() -{ - Release(); -} - -int LongPollThread::Run() -{ - SetThreadName("LongPoll"); - WatchDog watchdog("LongPoll"); - - // While not terminated, - do - { - watchdog.Feed(10000); - - PollSubject->Call(); - - WakeEvent.Wait(WakeupInterval); - WakeEvent.ResetEvent(); - } while (!Terminated); - - return 0; -} - - -}} // namespace OVR::Util diff --git a/LibOVR/Src/Util/Util_LongPollThread.h b/LibOVR/Src/Util/Util_LongPollThread.h deleted file mode 100644 index 5183e2f..0000000 --- a/LibOVR/Src/Util/Util_LongPollThread.h +++ /dev/null @@ -1,72 +0,0 @@ -/************************************************************************************ - -Filename : Util_LongPollThread.h -Content : Allows us to do all long polling tasks from a single thread to minimize deadlock risk -Created : June 30, 2013 -Authors : Chris Taylor - -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. - -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); -you may not use the Oculus VR Rift SDK except in compliance with the License, -which is provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -You may obtain a copy of the License at - -http://www.oculusvr.com/licenses/LICENSE-3.1 - -Unless required by applicable law or agreed to in writing, the Oculus VR SDK -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -*************************************************************************************/ - -#ifndef OVR_Util_LongPollThread_h -#define OVR_Util_LongPollThread_h - -#include "../Kernel/OVR_Timer.h" -#include "../Kernel/OVR_Atomic.h" -#include "../Kernel/OVR_Allocator.h" -#include "../Kernel/OVR_String.h" -#include "../Kernel/OVR_System.h" -#include "../Kernel/OVR_Threads.h" -#include "../Kernel/OVR_Observer.h" - -namespace OVR { namespace Util { - - -//----------------------------------------------------------------------------- -// LongPollThread - -// This thread runs long-polling subsystems that wake up every second or so -// The motivation is to reduce the number of threads that are running to minimize the risk of deadlock -class LongPollThread : public Thread, public SystemSingletonBase<LongPollThread> -{ - OVR_DECLARE_SINGLETON(LongPollThread); - virtual void OnThreadDestroy(); - -public: - typedef Delegate0<void> PollFunc; - static const int WakeupInterval = 1000; // milliseconds - - void AddPollFunc(Observer<PollFunc>* func); - - void Wake(); - -protected: - ObserverScope<PollFunc> PollSubject; - - bool Terminated; - Event WakeEvent; - void fireTermination(); - - virtual int Run(); -}; - - -}} // namespace OVR::Util - -#endif // OVR_Util_LongPollThread_h diff --git a/LibOVR/Src/Util/Util_Render_Stereo.cpp b/LibOVR/Src/Util/Util_Render_Stereo.cpp index 6937141..1389462 100644 --- a/LibOVR/Src/Util/Util_Render_Stereo.cpp +++ b/LibOVR/Src/Util/Util_Render_Stereo.cpp @@ -545,8 +545,10 @@ void StereoConfig::UpdateComputedState() eyeTypes[1] = StereoEye_Right; break; - default: - OVR_ASSERT( false ); break; + default: + numEyes = 0; + OVR_ASSERT( false ); + break; } // If either of these fire, you've probably forgotten to call SetRendertargetSize() @@ -1069,14 +1071,14 @@ void HeightmapMeshCreate( HeightmapMeshVertexData **ppVertices, uint16_t **ppTri } // Populate vertex buffer info - float xOffset = 0.0f; - float uOffset = 0.0f; - - if (rightEye) - { - xOffset = 1.0f; - uOffset = 0.5f; - } + //float xOffset = 0.0f; Not currently used. + //float uOffset = 0.0f; + + //if (rightEye) + //{ + // xOffset = 1.0f; + // uOffset = 0.5f; + //} // First pass - build up raw vertex data. HeightmapMeshVertexData* pcurVert = *ppVertices; diff --git a/LibOVR/Src/Util/Util_Settings.cpp b/LibOVR/Src/Util/Util_Settings.cpp deleted file mode 100644 index d7b3f0d..0000000 --- a/LibOVR/Src/Util/Util_Settings.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/************************************************************************************ - -Filename : Util_Settings.cpp -Content : Persistent settings subsystem -Created : June 11, 2014 -Author : Chris Taylor - -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. - -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); -you may not use the Oculus VR Rift SDK except in compliance with the License, -which is provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -You may obtain a copy of the License at - -http://www.oculusvr.com/licenses/LICENSE-3.1 - -Unless required by applicable law or agreed to in writing, the Oculus VR SDK -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -************************************************************************************/ - -#include "Util_Settings.h" -#include "../OVR_Profile.h" - -OVR_DEFINE_SINGLETON(Util::Settings); - -namespace OVR { namespace Util { - - -//// Settings - -Settings::Settings() : - Dirty(false) -{ - // Set up long poll handler - PollObserver.SetHandler(LongPollThread::PollFunc::FromMember<Settings, &Settings::pollDirty>(this)); - LongPollThread::GetInstance()->AddPollFunc(PollObserver); - - PushDestroyCallbacks(); -} - -Settings::~Settings() -{ - PollObserver.ReleaseAll(); - - Lock::Locker locker(&DataLock); - - if (Dirty) - { - updateFile(); - Dirty = false; - } -} - -void Settings::OnSystemDestroy() -{ - delete this; -} - -void Settings::SetFileName(const String& fileName) -{ - Lock::Locker locker(&DataLock); - - OVR_ASSERT(FullFilePath.IsEmpty()); - - if (FullFilePath.IsEmpty()) - { - FullFilePath = GetBaseOVRPath(true) + "/" + fileName; - - loadFile(); - } -} - -void Settings::loadFile() -{ - Root = *JSON::Load(FullFilePath.ToCStr()); - if (!Root) - { - OVR_DEBUG_LOG(("[Settings] Settings file was empty")); - } - else - { - OVR_DEBUG_LOG(("[Settings] Successfully read settings file")); - } -} - -void Settings::updateFile() -{ - OVR_ASSERT(!FullFilePath.IsEmpty()); - - if (Root->Save(FullFilePath.ToCStr())) - { - OVR_DEBUG_LOG(("[Settings] Updated settings file: %s", FullFilePath.ToCStr())); - Dirty = false; - } - else - { - LogError("[Settings] WARNING: Unable to write settings file: %s", FullFilePath.ToCStr()); - OVR_ASSERT(false); - } -} - -void Settings::pollDirty() -{ - // If dirty, - if (Dirty) - { - Lock::Locker locker(&DataLock); - - if (!Dirty) - { - return; - } - - updateFile(); - } -} - -void Settings::SetNumber(const char* key, double value) -{ - Lock::Locker locker(&DataLock); - - Dirty = true; - - if (!Root) - { - Root = *JSON::CreateObject(); - } - - Ptr<JSON> item = Root->GetItemByName(key); - if (!item) - { - Root->AddNumberItem(key, value); - return; - } - - item->Type = JSON_Number; - item->dValue = value; -} - -void Settings::SetInt(const char* key, int value) -{ - Lock::Locker locker(&DataLock); - - if (!Root) - { - Root = *JSON::CreateObject(); - Dirty = true; - } - - Ptr<JSON> item = Root->GetItemByName(key); - if (!item) - { - Root->AddIntItem(key, value); - Dirty = true; - return; - } - - // If the value changed, - if (item->Type != JSON_Number || - (int)item->dValue != value) - { - item->Type = JSON_Number; - item->dValue = value; - Dirty = true; - } -} - -void Settings::SetBool(const char* key, bool value) -{ - Lock::Locker locker(&DataLock); - - if (!Root) - { - Root = *JSON::CreateObject(); - Dirty = true; - } - - Ptr<JSON> item = Root->GetItemByName(key); - if (!item) - { - Root->AddBoolItem(key, value); - Dirty = true; - return; - } - - // If the value changed, - if (item->Type != JSON_Bool || - ((int)item->dValue != 0) != value) - { - item->Type = JSON_Bool; - item->dValue = value ? 1. : 0.; - item->Value = value ? "true" : "false"; - Dirty = true; - } -} - -void Settings::SetString(const char* key, const char* value) -{ - Lock::Locker locker(&DataLock); - - if (!Root) - { - Root = *JSON::CreateObject(); - Dirty = true; - } - - Ptr<JSON> item = Root->GetItemByName(key); - if (!item) - { - Root->AddStringItem(key, value); - Dirty = true; - return; - } - - // If the value changed, - if (item->Type != JSON_String || - item->Value != value) - { - item->Type = JSON_String; - item->Value = value; - Dirty = true; - } -} - -double Settings::GetNumber(const char* key, double defaultValue) -{ - Lock::Locker locker(&DataLock); - - if (!Root) - { - SetNumber(key, defaultValue); - return defaultValue; - } - - Ptr<JSON> item = Root->GetItemByName(key); - if (!item) - { - SetNumber(key, defaultValue); - return defaultValue; - } - - return item->dValue; -} - -int Settings::GetInt(const char* key, int defaultValue) -{ - Lock::Locker locker(&DataLock); - - if (!Root) - { - SetInt(key, defaultValue); - return defaultValue; - } - - Ptr<JSON> item = Root->GetItemByName(key); - if (!item) - { - SetInt(key, defaultValue); - return defaultValue; - } - - return (int)item->dValue; -} - -bool Settings::GetBool(const char* key, bool defaultValue) -{ - Lock::Locker locker(&DataLock); - - if (!Root) - { - SetBool(key, defaultValue); - return defaultValue; - } - - Ptr<JSON> item = Root->GetItemByName(key); - if (!item) - { - SetBool(key, defaultValue); - return defaultValue; - } - - return (int)item->dValue != 0; -} - -String Settings::GetString(const char* key, const char* defaultValue) -{ - Lock::Locker locker(&DataLock); - - if (!Root) - { - SetString(key, defaultValue); - return defaultValue; - } - - Ptr<JSON> item = Root->GetItemByName(key); - if (!item) - { - SetString(key, defaultValue); - return defaultValue; - } - - return item->Value; -} - - -}} // namespace OVR::Util diff --git a/LibOVR/Src/Util/Util_Settings.h b/LibOVR/Src/Util/Util_Settings.h deleted file mode 100644 index 79ea172..0000000 --- a/LibOVR/Src/Util/Util_Settings.h +++ /dev/null @@ -1,83 +0,0 @@ -/************************************************************************************ - -PublicHeader: n/a -Filename : Util_Settings.h -Content : Persistent settings subsystem -Created : June 11, 2014 -Author : Chris Taylor - -Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved. - -Licensed under the Oculus VR Rift SDK License Version 3.1 (the "License"); -you may not use the Oculus VR Rift SDK except in compliance with the License, -which is provided at the time of installation or download, or which -otherwise accompanies this software in either electronic or hard copy form. - -You may obtain a copy of the License at - -http://www.oculusvr.com/licenses/LICENSE-3.1 - -Unless required by applicable law or agreed to in writing, the Oculus VR SDK -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -************************************************************************************/ - -#ifndef OVR_Settings_h -#define OVR_Settings_h - -#include "../Kernel/OVR_String.h" -#include "../Kernel/OVR_System.h" -#include "../Kernel/OVR_Observer.h" -#include "../OVR_JSON.h" -#include "Util_LongPollThread.h" - -namespace OVR { namespace Util { - - -//----------------------------------------------------------------------------- -// Settings - -class Settings : public NewOverrideBase, public SystemSingletonBase<Settings> -{ - OVR_DECLARE_SINGLETON(Settings); - - ObserverScope<LongPollThread::PollFunc> PollObserver; - void pollDirty(); - - // Helpers (call with lock held) - void loadFile(); - void updateFile(); - - // Synchronization for data access - Lock DataLock; - - // Full path to the JSON settings file - String FullFilePath; - - // Backed by JSON - Ptr<JSON> Root; - - // Dirty flag to capture multiple changes for long poll writes - bool Dirty; - -public: - void SetFileName(const String& fileName); - - void SetNumber(const char* key, double value); - void SetInt(const char* key, int value); - void SetBool(const char* key, bool value); - void SetString(const char* key, const char* value); - - double GetNumber(const char* key, double defaultValue = 0.); - int GetInt(const char* key, int defaultValue = 0); - bool GetBool(const char* key, bool defaultValue = false); - String GetString(const char* key, const char* defaultValue = ""); -}; - - -}} // namespace OVR::Util - -#endif // OVR_Settings_h |