nuclear@0: /************************************************************************************ nuclear@0: nuclear@0: Filename : CAPI_DistortionRenderer.h nuclear@0: Content : Abstract interface for platform-specific rendering of distortion nuclear@0: Created : February 2, 2014 nuclear@0: Authors : Michael Antonov nuclear@0: nuclear@0: Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. nuclear@0: nuclear@0: Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); nuclear@0: you may not use the Oculus VR Rift SDK except in compliance with the License, nuclear@0: which is provided at the time of installation or download, or which nuclear@0: otherwise accompanies this software in either electronic or hard copy form. nuclear@0: nuclear@0: You may obtain a copy of the License at nuclear@0: nuclear@0: http://www.oculusvr.com/licenses/LICENSE-3.2 nuclear@0: nuclear@0: Unless required by applicable law or agreed to in writing, the Oculus VR SDK nuclear@0: distributed under the License is distributed on an "AS IS" BASIS, nuclear@0: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. nuclear@0: See the License for the specific language governing permissions and nuclear@0: limitations under the License. nuclear@0: nuclear@0: ************************************************************************************/ nuclear@0: nuclear@0: #ifndef OVR_CAPI_DistortionRenderer_h nuclear@0: #define OVR_CAPI_DistortionRenderer_h nuclear@0: nuclear@0: #include "CAPI_HMDRenderState.h" nuclear@0: #include "CAPI_FrameTimeManager.h" nuclear@0: nuclear@0: typedef void (*PostDistortionCallback)(void* pRenderContext); nuclear@0: nuclear@0: namespace OVR { namespace CAPI { nuclear@0: nuclear@0: //------------------------------------------------------------------------------------- nuclear@0: // ***** CAPI::DistortionRenderer nuclear@0: nuclear@0: // DistortionRenderer implements rendering of distortion and other overlay elements nuclear@0: // in platform-independent way. nuclear@0: // Platform-specific renderer back ends for CAPI are derived from this class. nuclear@0: nuclear@0: class DistortionRenderer : public RefCountBase nuclear@0: { nuclear@0: // Quiet assignment compiler warning. nuclear@0: void operator = (const DistortionRenderer&) { } nuclear@0: public: nuclear@0: nuclear@0: DistortionRenderer(ovrRenderAPIType api, ovrHmd hmd, nuclear@0: FrameTimeManager& timeManager, nuclear@0: const HMDRenderState& renderState) : nuclear@0: LastUsedOverdriveTextureIndex(-1), nuclear@0: LatencyTestActive(false), nuclear@0: LatencyTest2Active(false), nuclear@0: RenderAPI(api), nuclear@0: HMD(hmd), nuclear@0: TimeManager(timeManager), nuclear@0: RState(renderState), nuclear@0: GfxState(), nuclear@0: RegisteredPostDistortionCallback(NULL) nuclear@0: { nuclear@0: #ifdef OVR_OS_WIN32 nuclear@0: timer = CreateWaitableTimer(NULL, TRUE, NULL); nuclear@0: OVR_ASSERT(timer != NULL); nuclear@0: #endif nuclear@0: } nuclear@0: virtual ~DistortionRenderer() nuclear@0: { nuclear@0: } nuclear@0: nuclear@0: nuclear@0: // Configures the Renderer based on externally passed API settings. Must be nuclear@0: // called before use. nuclear@0: // Under D3D, apiConfig includes D3D Device pointer, back buffer and other nuclear@0: // needed structures. nuclear@0: virtual bool Initialize(const ovrRenderAPIConfig* apiConfig) = 0; nuclear@0: nuclear@0: // Submits one eye texture for rendering. This is in the separate method to nuclear@0: // allow "submit as you render" scenarios on horizontal screens where one nuclear@0: // eye can be scanned out before the other. nuclear@0: virtual void SubmitEye(int eyeId, const ovrTexture* eyeTexture) = 0; nuclear@0: nuclear@0: // Finish the frame, optionally swapping buffers. nuclear@0: // Many implementations may actually apply the distortion here. nuclear@0: virtual void EndFrame(bool swapBuffers) = 0; nuclear@0: nuclear@0: void RegisterPostDistortionCallback(PostDistortionCallback postDistortionCallback) nuclear@0: { nuclear@0: RegisteredPostDistortionCallback = postDistortionCallback; nuclear@0: } nuclear@0: nuclear@0: // Stores the current graphics pipeline state so it can be restored later. nuclear@0: void SaveGraphicsState() { if (GfxState && !(RState.DistortionCaps & ovrDistortionCap_NoRestore)) GfxState->Save(); } nuclear@0: nuclear@0: // Restores the saved graphics pipeline state. nuclear@0: void RestoreGraphicsState() { if (GfxState && !(RState.DistortionCaps & ovrDistortionCap_NoRestore)) GfxState->Restore(); } nuclear@0: nuclear@0: // *** Creation Factory logic nuclear@0: nuclear@0: ovrRenderAPIType GetRenderAPI() const { return RenderAPI; } nuclear@0: nuclear@0: // Creation function for this interface, registered for API. nuclear@0: typedef DistortionRenderer* (*CreateFunc)(ovrHmd hmd, nuclear@0: FrameTimeManager &timeManager, nuclear@0: const HMDRenderState& renderState); nuclear@0: nuclear@0: static CreateFunc APICreateRegistry[ovrRenderAPI_Count]; nuclear@0: nuclear@0: // Color is expected to be 3 byte RGB nuclear@0: void SetLatencyTestColor(unsigned char* color); nuclear@0: void SetLatencyTest2Color(unsigned char* color); nuclear@0: nuclear@0: protected: nuclear@0: // Used for pixel luminance overdrive on DK2 displays nuclear@0: // A copy of back buffer images will be ping ponged nuclear@0: // TODO: figure out 0 dynamically based on DK2 latency? nuclear@0: static const int NumOverdriveTextures = 2; nuclear@0: int LastUsedOverdriveTextureIndex; nuclear@0: nuclear@0: bool LatencyTestActive; nuclear@0: unsigned char LatencyTestDrawColor[3]; nuclear@0: bool LatencyTest2Active; nuclear@0: unsigned char LatencyTest2DrawColor[3]; nuclear@0: nuclear@0: bool IsOverdriveActive() nuclear@0: { nuclear@0: // doesn't make sense to use overdrive when vsync is disabled as we cannot guarantee nuclear@0: // when the rendered frame will be displayed nuclear@0: return LastUsedOverdriveTextureIndex >= 0 && nuclear@0: !((RState.EnabledHmdCaps & ovrHmdCap_NoVSync) > 0) && nuclear@0: (RState.DistortionCaps & ovrDistortionCap_Chromatic); nuclear@0: } nuclear@0: nuclear@0: void GetOverdriveScales(float& outRiseScale, float& outFallScale); nuclear@0: nuclear@0: double WaitTillTime(double absTime); nuclear@0: nuclear@0: #ifdef OVR_OS_WIN32 nuclear@0: HANDLE timer; nuclear@0: LARGE_INTEGER waitableTimerInterval; nuclear@0: #endif nuclear@0: nuclear@0: class GraphicsState : public RefCountBase nuclear@0: { nuclear@0: public: nuclear@0: GraphicsState() : IsValid(false) {} nuclear@0: virtual ~GraphicsState() {} nuclear@0: virtual void Save() = 0; nuclear@0: virtual void Restore() = 0; nuclear@0: nuclear@0: protected: nuclear@0: bool IsValid; nuclear@0: }; nuclear@0: nuclear@0: const ovrRenderAPIType RenderAPI; nuclear@0: const ovrHmd HMD; nuclear@0: FrameTimeManager& TimeManager; nuclear@0: const HMDRenderState& RState; nuclear@0: Ptr GfxState; nuclear@0: PostDistortionCallback RegisteredPostDistortionCallback; nuclear@0: }; nuclear@0: nuclear@0: }} // namespace OVR::CAPI nuclear@0: nuclear@0: nuclear@0: #endif // OVR_CAPI_DistortionRenderer_h