nuclear@3: /************************************************************************************ nuclear@3: nuclear@3: PublicHeader: OVR.h nuclear@3: Filename : Util_LatencyTest.h nuclear@3: Content : Wraps the lower level LatencyTesterDevice and adds functionality. nuclear@3: Created : February 14, 2013 nuclear@3: Authors : Lee Cooper nuclear@3: nuclear@3: Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. nuclear@3: nuclear@3: Use of this software is subject to the terms of the Oculus license nuclear@3: agreement provided at the time of installation or download, or which nuclear@3: otherwise accompanies this software in either electronic or hard copy form. nuclear@3: nuclear@3: *************************************************************************************/ nuclear@3: nuclear@3: #ifndef OVR_Util_LatencyTest_h nuclear@3: #define OVR_Util_LatencyTest_h nuclear@3: nuclear@3: #include "../OVR_Device.h" nuclear@3: nuclear@3: #include "../Kernel/OVR_String.h" nuclear@3: #include "../Kernel/OVR_List.h" nuclear@3: nuclear@3: namespace OVR { namespace Util { nuclear@3: nuclear@3: nuclear@3: //------------------------------------------------------------------------------------- nuclear@3: // ***** LatencyTest nuclear@3: // nuclear@3: // LatencyTest utility class wraps the low level LatencyTestDevice and manages the scheduling nuclear@3: // of a latency test. A single test is composed of a series of individual latency measurements nuclear@3: // which are used to derive min, max, and an average latency value. nuclear@3: // nuclear@3: // Developers are required to call the following methods: nuclear@3: // SetDevice - Sets the LatencyTestDevice to be used for the tests. nuclear@3: // ProcessInputs - This should be called at the same place in the code where the game engine nuclear@3: // reads the headset orientation from LibOVR (typically done by calling nuclear@3: // 'GetOrientation' on the SensorFusion object). Calling this at the right time nuclear@3: // enables us to measure the same latency that occurs for headset orientation nuclear@3: // changes. nuclear@3: // DisplayScreenColor - The latency tester works by sensing the color of the pixels directly nuclear@3: // beneath it. The color of these pixels can be set by drawing a small nuclear@3: // quad at the end of the rendering stage. The quad should be small nuclear@3: // such that it doesn't significantly impact the rendering of the scene, nuclear@3: // but large enough to be 'seen' by the sensor. See the SDK nuclear@3: // documentation for more information. nuclear@3: // GetResultsString - Call this to get a string containing the most recent results. nuclear@3: // If the string has already been gotten then NULL will be returned. nuclear@3: // The string pointer will remain valid until the next time this nuclear@3: // method is called. nuclear@3: // nuclear@3: nuclear@3: class LatencyTest : public NewOverrideBase nuclear@3: { nuclear@3: public: nuclear@3: LatencyTest(LatencyTestDevice* device = NULL); nuclear@3: ~LatencyTest(); nuclear@3: nuclear@3: // Set the Latency Tester device that we'll use to send commands to and receive nuclear@3: // notification messages from. nuclear@3: bool SetDevice(LatencyTestDevice* device); nuclear@3: nuclear@3: // Returns true if this LatencyTestUtil has a Latency Tester device. nuclear@3: bool HasDevice() const nuclear@3: { return Handler.IsHandlerInstalled(); } nuclear@3: nuclear@3: void ProcessInputs(); nuclear@3: bool DisplayScreenColor(Color& colorToDisplay); nuclear@3: const char* GetResultsString(); nuclear@3: nuclear@3: // Begin test. Equivalent to pressing the button on the latency tester. nuclear@3: void BeginTest(); nuclear@3: nuclear@3: private: nuclear@3: LatencyTest* getThis() { return this; } nuclear@3: nuclear@3: enum LatencyTestMessageType nuclear@3: { nuclear@3: LatencyTest_None, nuclear@3: LatencyTest_Timer, nuclear@3: LatencyTest_ProcessInputs, nuclear@3: }; nuclear@3: nuclear@3: UInt32 getRandomComponent(UInt32 range); nuclear@3: void handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage = LatencyTest_None); nuclear@3: void reset(); nuclear@3: void setTimer(UInt32 timeMilliS); nuclear@3: void clearTimer(); nuclear@3: nuclear@3: class LatencyTestHandler : public MessageHandler nuclear@3: { nuclear@3: LatencyTest* pLatencyTestUtil; nuclear@3: public: nuclear@3: LatencyTestHandler(LatencyTest* latencyTester) : pLatencyTestUtil(latencyTester) { } nuclear@3: ~LatencyTestHandler(); nuclear@3: nuclear@3: virtual void OnMessage(const Message& msg); nuclear@3: }; nuclear@3: nuclear@3: bool areResultsComplete(); nuclear@3: void processResults(); nuclear@3: void updateForTimeouts(); nuclear@3: nuclear@3: Ptr Device; nuclear@3: LatencyTestHandler Handler; nuclear@3: nuclear@3: enum TesterState nuclear@3: { nuclear@3: State_WaitingForButton, nuclear@3: State_WaitingForSettlePreCalibrationColorBlack, nuclear@3: State_WaitingForSettlePostCalibrationColorBlack, nuclear@3: State_WaitingForSettlePreCalibrationColorWhite, nuclear@3: State_WaitingForSettlePostCalibrationColorWhite, nuclear@3: State_WaitingToTakeMeasurement, nuclear@3: State_WaitingForTestStarted, nuclear@3: State_WaitingForColorDetected, nuclear@3: State_WaitingForSettlePostMeasurement nuclear@3: }; nuclear@3: TesterState State; nuclear@3: nuclear@3: bool HaveOldTime; nuclear@3: UInt32 OldTime; nuclear@3: UInt32 ActiveTimerMilliS; nuclear@3: nuclear@3: Color RenderColor; nuclear@3: nuclear@3: struct MeasurementResult : public ListNode, public NewOverrideBase nuclear@3: { nuclear@3: MeasurementResult() nuclear@3: : DeviceMeasuredElapsedMilliS(0), nuclear@3: TimedOutWaitingForTestStarted(false), nuclear@3: TimedOutWaitingForColorDetected(false), nuclear@3: StartTestTicksMicroS(0), nuclear@3: TestStartedTicksMicroS(0) nuclear@3: {} nuclear@3: nuclear@3: Color TargetColor; nuclear@3: nuclear@3: UInt32 DeviceMeasuredElapsedMilliS; nuclear@3: nuclear@3: bool TimedOutWaitingForTestStarted; nuclear@3: bool TimedOutWaitingForColorDetected; nuclear@3: nuclear@3: UInt64 StartTestTicksMicroS; nuclear@3: UInt64 TestStartedTicksMicroS; nuclear@3: }; nuclear@3: nuclear@3: List Results; nuclear@3: void clearMeasurementResults(); nuclear@3: nuclear@3: MeasurementResult* getActiveResult(); nuclear@3: nuclear@3: StringBuffer ResultsString; nuclear@3: String ReturnedResultString; nuclear@3: }; nuclear@3: nuclear@3: }} // namespace OVR::Util nuclear@3: nuclear@3: #endif // OVR_Util_LatencyTest_h