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