summaryrefslogtreecommitdiffstats
path: root/LibOVR/Src/CAPI/D3D1X
diff options
context:
space:
mode:
authorBrad Davis <[email protected]>2014-07-24 16:47:31 -0700
committerBrad Davis <[email protected]>2014-07-24 16:47:31 -0700
commit0f49ce8fc6aa54224e4c0d6fda8c4527ad39cce1 (patch)
treeda07ebc6a7f75185bda857dd5f1c34710b416a93 /LibOVR/Src/CAPI/D3D1X
parentca79271759ff7eecd22ec5c4db438370fe51d687 (diff)
0.4 Win-Beta0.4.0
Diffstat (limited to 'LibOVR/Src/CAPI/D3D1X')
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_HSWDisplay.cpp35
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_HSWDisplay.h41
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_HSWDisplay.cpp35
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_HSWDisplay.h41
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp554
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.h52
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_HSWDisplay.cpp592
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_HSWDisplay.h84
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp1
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h7
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp113
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h11
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_HSWDisplay.cpp433
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_HSWDisplay.h82
-rw-r--r--LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_Util.cpp26
15 files changed, 1934 insertions, 173 deletions
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_HSWDisplay.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_HSWDisplay.cpp
new file mode 100644
index 0000000..4a66ba5
--- /dev/null
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_HSWDisplay.cpp
@@ -0,0 +1,35 @@
+/************************************************************************************
+
+Filename : CAPI_D3D10_HSWDisplay.cpp
+Content : Implements Health and Safety Warning system.
+Created : July 7, 2014
+Authors : Paul Pedriana
+
+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.
+
+************************************************************************************/
+
+#define OVR_D3D_VERSION 10
+#include "CAPI_D3D1X_HSWDisplay.cpp"
+#undef OVR_D3D_VERSION
+
+
+
+
+
+
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_HSWDisplay.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_HSWDisplay.h
new file mode 100644
index 0000000..2d78b8c
--- /dev/null
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D10_HSWDisplay.h
@@ -0,0 +1,41 @@
+/************************************************************************************
+
+Filename : CAPI_D3D10_HSWDisplay.h
+Content : Implements Health and Safety Warning system.
+Created : July 7, 2014
+Authors : Paul Pedriana
+
+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_CAPI_D3D10_HSWDisplay_h
+#define OVR_CAPI_D3D10_HSWDisplay_h
+
+#if !defined(OVR_D3D_VERSION) || ((OVR_D3D_VERSION != 10) && (OVR_D3D_VERSION != 11))
+ #error This header expects OVR_D3D_VERSION to be defined, to 10 or 11.
+#endif
+
+// Due to the similarities between DX10 and DX11, there is a shared implementation of the headers and source
+// which is differentiated only by the OVR_D3D_VERSION define. This define causes D3D_NS (D3D namespace) to
+// be defined to either D3D10 or D3D11, as well as other similar effects.
+#include "CAPI_D3D1X_HSWDisplay.h"
+
+
+#endif // OVR_CAPI_D3D10_HSWDisplay_h
+
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_HSWDisplay.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_HSWDisplay.cpp
new file mode 100644
index 0000000..02e5c01
--- /dev/null
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_HSWDisplay.cpp
@@ -0,0 +1,35 @@
+/************************************************************************************
+
+Filename : CAPI_D3D11_HSWDisplay.cpp
+Content : Implements Health and Safety Warning system.
+Created : July 7, 2014
+Authors : Paul Pedriana
+
+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.
+
+************************************************************************************/
+
+#define OVR_D3D_VERSION 11
+#include "CAPI_D3D1X_HSWDisplay.cpp"
+#undef OVR_D3D_VERSION
+
+
+
+
+
+
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_HSWDisplay.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_HSWDisplay.h
new file mode 100644
index 0000000..b5739fb
--- /dev/null
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D11_HSWDisplay.h
@@ -0,0 +1,41 @@
+/************************************************************************************
+
+Filename : CAPI_D3D11_HSWDisplay.h
+Content : Implements Health and Safety Warning system.
+Created : July 7, 2014
+Authors : Paul Pedriana
+
+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_CAPI_D3D11_HSWDisplay_h
+#define OVR_CAPI_D3D11_HSWDisplay_h
+
+#if !defined(OVR_D3D_VERSION) || ((OVR_D3D_VERSION != 10) && (OVR_D3D_VERSION != 11))
+ #error This header expects OVR_D3D_VERSION to be defined, to 10 or 11.
+#endif
+
+// Due to the similarities between DX10 and DX11, there is a shared implementation of the headers and source
+// which is differentiated only by the OVR_D3D_VERSION define. This define causes D3D_NS (D3D namespace) to
+// be defined to either D3D10 or D3D11, as well as other similar effects.
+#include "CAPI_D3D1X_HSWDisplay.h"
+
+
+#endif // OVR_CAPI_D3D11_HSWDisplay_h
+
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp
index 878d777..18ad298 100644
--- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.cpp
@@ -3,7 +3,7 @@
Filename : CAPI_D3D1X_DistortionRenderer.cpp
Content : Experimental distortion renderer
Created : November 11, 2013
-Authors : Volga Aksoy, Michael Antonov
+Authors : Volga Aksoy, Michael Antonov, Shariq Hashme
Copyright : Copyright 2014 Oculus VR, Inc. All Rights reserved.
@@ -27,6 +27,7 @@ limitations under the License.
#include "CAPI_D3D1X_DistortionRenderer.h"
#include "../../OVR_CAPI_D3D.h"
+#include "../../Kernel/OVR_Color.h"
namespace OVR { namespace CAPI { namespace D3D_NS {
@@ -83,7 +84,7 @@ static PrecompiledShader DistortionVertexShaderLookup[DistortionVertexShaderCoun
static PrecompiledShader DistortionPixelShaderLookup[DistortionPixelShaderCount] =
{
PCS_NOREFL(Distortion_ps),
- PCS_NOREFL(DistortionChroma_ps)
+ PCS_REFL__(DistortionChroma_ps)
};
void DistortionShaderBitIndexCheck()
@@ -96,10 +97,10 @@ void DistortionShaderBitIndexCheck()
struct DistortionVertex
{
- Vector2f Pos;
- Vector2f TexR;
- Vector2f TexG;
- Vector2f TexB;
+ Vector2f ScreenPosNDC;
+ Vector2f TanEyeAnglesR;
+ Vector2f TanEyeAnglesG;
+ Vector2f TanEyeAnglesB;
Color Col;
};
@@ -171,7 +172,7 @@ bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig,
if (!config->D3D_NS.pDevice || !config->D3D_NS.pBackBufferRT)
return false;
-
+
RParams.pDevice = config->D3D_NS.pDevice;
RParams.pContext = D3DSELECT_10_11(config->D3D_NS.pDevice, config->D3D_NS.pDeviceContext);
RParams.pBackBufferRT = config->D3D_NS.pBackBufferRT;
@@ -199,8 +200,11 @@ bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig,
rs.CullMode = D3D1X_(CULL_BACK);
rs.DepthClipEnable = true;
rs.FillMode = D3D1X_(FILL_SOLID);
+ Rasterizer = NULL;
RParams.pDevice->CreateRasterizerState(&rs, &Rasterizer.GetRawRef());
+ initOverdrive();
+
// TBD: Blend state.. not used?
// We'll want to turn off blending
@@ -211,8 +215,50 @@ bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig,
return true;
}
+void DistortionRenderer::initOverdrive()
+{
+ if(RState.DistortionCaps & ovrDistortionCap_Overdrive)
+ {
+ LastUsedOverdriveTextureIndex = 0;
-void DistortionRenderer::SubmitEye(int eyeId, ovrTexture* eyeTexture)
+ for (int i = 0; i < NumOverdriveTextures; i++)
+ {
+ pOverdriveTextures[i] = *new Texture(&RParams, Texture_RGBA, RParams.RTSize,
+ getSamplerState(Sample_Linear|Sample_ClampBorder));
+
+ D3D1X_(TEXTURE2D_DESC) dsDesc;
+ dsDesc.Width = RParams.RTSize.w;
+ dsDesc.Height = RParams.RTSize.h;
+ dsDesc.MipLevels = 1;
+ dsDesc.ArraySize = 1;
+ dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ dsDesc.SampleDesc.Count = 1;
+ dsDesc.SampleDesc.Quality = 0;
+ dsDesc.Usage = D3D1X_(USAGE_DEFAULT);
+ dsDesc.BindFlags = D3D1X_(BIND_SHADER_RESOURCE) | D3D1X_(BIND_RENDER_TARGET);
+ dsDesc.CPUAccessFlags = 0;
+ dsDesc.MiscFlags = 0;
+
+ HRESULT hr = RParams.pDevice->CreateTexture2D(&dsDesc, NULL, &pOverdriveTextures[i]->Tex.GetRawRef());
+ if (FAILED(hr))
+ {
+ OVR_DEBUG_LOG_TEXT(("Failed to create overdrive texture."));
+ // Remove overdrive flag since we failed to create the texture
+ LastUsedOverdriveTextureIndex = -1; // disables feature
+ break;
+ }
+
+ RParams.pDevice->CreateShaderResourceView(pOverdriveTextures[i]->Tex, NULL, &pOverdriveTextures[i]->TexSv.GetRawRef());
+ RParams.pDevice->CreateRenderTargetView(pOverdriveTextures[i]->Tex, NULL, &pOverdriveTextures[i]->TexRtv.GetRawRef());
+ }
+ }
+ else
+ {
+ LastUsedOverdriveTextureIndex = -1;
+ }
+}
+
+void DistortionRenderer::SubmitEye(int eyeId, const ovrTexture* eyeTexture)
{
const ovrD3D1X(Texture)* tex = (const ovrD3D1X(Texture)*)eyeTexture;
@@ -229,44 +275,64 @@ void DistortionRenderer::SubmitEye(int eyeId, ovrTexture* eyeTexture)
EyeTextureSize[eyeId], EyeRenderViewport[eyeId],
UVScaleOffset[eyeId]);
+ if (RState.DistortionCaps & ovrDistortionCap_FlipInput)
+ {
+ UVScaleOffset[eyeId][0].y = -UVScaleOffset[eyeId][0].y;
+ UVScaleOffset[eyeId][1].y = 1.0f - UVScaleOffset[eyeId][1].y;
+ }
+
pEyeTextures[eyeId]->UpdatePlaceholderTexture(tex->D3D_NS.pTexture, tex->D3D_NS.pSRView,
tex->D3D_NS.Header.TextureSize);
}
}
-void DistortionRenderer::EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor,
- unsigned char* latencyTester2DrawColor)
+void DistortionRenderer::renderEndFrame()
{
- if (!TimeManager.NeedDistortionTimeMeasurement())
- {
- if (RState.DistortionCaps & ovrDistortionCap_TimeWarp)
- {
- // Wait for timewarp distortion if it is time and Gpu idle
- FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime);
- }
+ renderDistortion(pEyeTextures[0], pEyeTextures[1]);
+
+ if(RegisteredPostDistortionCallback)
+ RegisteredPostDistortionCallback(RParams.pContext);
- renderDistortion(pEyeTextures[0], pEyeTextures[1]);
+ if(LatencyTest2Active)
+ {
+ renderLatencyPixel(LatencyTest2DrawColor);
}
- else
+}
+
+void DistortionRenderer::EndFrame(bool swapBuffers)
+{
+ // Don't spin if we are explicitly asked not to
+ if (RState.DistortionCaps & ovrDistortionCap_TimeWarp &&
+ !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits))
{
- // If needed, measure distortion time so that TimeManager can better estimate
- // latency-reducing time-warp wait timing.
- WaitUntilGpuIdle();
- double distortionStartTime = ovr_GetTimeInSeconds();
+ if (!TimeManager.NeedDistortionTimeMeasurement())
+ {
+ // Wait for timewarp distortion if it is time and Gpu idle
+ FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime);
- renderDistortion(pEyeTextures[0], pEyeTextures[1]);
+ renderEndFrame();
+ }
+ else
+ {
+ // If needed, measure distortion time so that TimeManager can better estimate
+ // latency-reducing time-warp wait timing.
+ WaitUntilGpuIdle();
+ double distortionStartTime = ovr_GetTimeInSeconds();
- WaitUntilGpuIdle();
- TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime);
- }
+ renderEndFrame();
- if(latencyTesterDrawColor)
+ WaitUntilGpuIdle();
+ TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime);
+ }
+ }
+ else
{
- renderLatencyQuad(latencyTesterDrawColor);
+ renderEndFrame();
}
- else if(latencyTester2DrawColor)
+
+ if(LatencyTestActive)
{
- renderLatencyPixel(latencyTester2DrawColor);
+ renderLatencyQuad(LatencyTestDrawColor);
}
if (swapBuffers)
@@ -278,7 +344,12 @@ void DistortionRenderer::EndFrame(bool swapBuffers, unsigned char* latencyTester
// Force GPU to flush the scene, resulting in the lowest possible latency.
// It's critical that this flush is *after* present.
- WaitUntilGpuIdle();
+ // With the display driver this flush is obsolete and theoretically should
+ // be a no-op.
+ // Doesn't need to be done if running through the Oculus driver.
+ if (RState.OurHMDInfo.InCompatibilityMode &&
+ !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits))
+ WaitUntilGpuIdle();
}
else
{
@@ -312,45 +383,8 @@ void DistortionRenderer::WaitUntilGpuIdle()
double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime)
{
- double initialTime = ovr_GetTimeInSeconds();
- if (initialTime >= absTime)
- return 0.0;
-
- // Flush and Stall CPU while waiting for GPU to complete rendering all of the queued draw calls
- D3D1x_QUERY_DESC queryDesc = { D3D1X_(QUERY_EVENT), 0 };
- Ptr<ID3D1xQuery> query;
- BOOL done = FALSE;
- bool callGetData = false;
-
- if (RParams.pDevice->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK)
- {
- D3DSELECT_10_11(query->End(),
- RParams.pContext->End(query));
- callGetData = true;
- }
-
- double newTime = initialTime;
- volatile int i;
-
- while (newTime < absTime)
- {
- if (callGetData)
- {
- // GetData will returns S_OK for both done == TRUE or FALSE.
- // Stop calling GetData on failure.
- callGetData = !FAILED(D3DSELECT_10_11(query->GetData(&done, sizeof(BOOL), 0),
- RParams.pContext->GetData(query, &done, sizeof(BOOL), 0))) && !done;
- }
- else
- {
- for (int j = 0; j < 50; j++)
- i = 0;
- }
- newTime = ovr_GetTimeInSeconds();
- }
-
- // How long we waited
- return newTime - initialTime;
+ RParams.pContext->Flush();
+ return WaitTillTime(absTime);
}
void DistortionRenderer::initBuffersAndShaders()
@@ -382,16 +416,21 @@ void DistortionRenderer::initBuffersAndShaders()
for ( unsigned vertNum = 0; vertNum < meshData.VertexCount; vertNum++ )
{
- pCurVBVert->Pos.x = pCurOvrVert->Pos.x;
- pCurVBVert->Pos.y = pCurOvrVert->Pos.y;
- pCurVBVert->TexR = (*(Vector2f*)&pCurOvrVert->TexR);
- pCurVBVert->TexG = (*(Vector2f*)&pCurOvrVert->TexG);
- pCurVBVert->TexB = (*(Vector2f*)&pCurOvrVert->TexB);
+ 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);
+
// Convert [0.0f,1.0f] to [0,255]
- pCurVBVert->Col.R = (OVR::UByte)( pCurOvrVert->VignetteFactor * 255.99f );
+ if (DistortionCaps & ovrDistortionCap_Vignette)
+ pCurVBVert->Col.R = (uint8_t)( pCurOvrVert->VignetteFactor * 255.99f );
+ else
+ pCurVBVert->Col.R = 255;
+
pCurVBVert->Col.G = pCurVBVert->Col.R;
pCurVBVert->Col.B = pCurVBVert->Col.R;
- pCurVBVert->Col.A = (OVR::UByte)( pCurOvrVert->TimeWarpFactor * 255.99f );;
+ pCurVBVert->Col.A = (uint8_t)( pCurOvrVert->TimeWarpFactor * 255.99f );;
pCurOvrVert++;
pCurVBVert++;
}
@@ -417,19 +456,63 @@ void DistortionRenderer::initBuffersAndShaders()
void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* rightEyeTexture)
{
+
+#if (OVR_D3D_VERSION == 10)
+ RParams.pContext->GSSetShader(NULL);
+#else // d3d 11
+ RParams.pContext->HSSetShader(NULL, NULL, 0);
+ RParams.pContext->DSSetShader(NULL, NULL, 0);
+ RParams.pContext->GSSetShader(NULL, NULL, 0);
+#endif
+
RParams.pContext->RSSetState(Rasterizer);
- RParams.pContext->OMSetRenderTargets(1, &RParams.pBackBufferRT, 0);
-
- setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h));
-
+ bool overdriveActive = IsOverdriveActive();
+ int currOverdriveTextureIndex = -1;
+
+ if(overdriveActive)
+ {
+ currOverdriveTextureIndex = (LastUsedOverdriveTextureIndex + 1) % NumOverdriveTextures;
+ ID3D1xRenderTargetView* distortionRtv = pOverdriveTextures[currOverdriveTextureIndex]->TexRtv.GetRawRef();
+ ID3D1xRenderTargetView* mrtRtv[2] = {distortionRtv, RParams.pBackBufferRT};
+ RParams.pContext->OMSetRenderTargets(2, mrtRtv, 0);
+
+ RParams.pContext->ClearRenderTargetView(distortionRtv, RState.ClearColor);
+ }
+ else
+ {
+ RParams.pContext->OMSetRenderTargets(1, &RParams.pBackBufferRT, 0);
+ }
+
// Not affected by viewport.
RParams.pContext->ClearRenderTargetView(RParams.pBackBufferRT, RState.ClearColor);
+ setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h));
+
+
for(int eyeNum = 0; eyeNum < 2; eyeNum++)
{
ShaderFill distortionShaderFill(DistortionShader);
distortionShaderFill.SetTexture(0, eyeNum == 0 ? leftEyeTexture : rightEyeTexture);
+
+ 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
+ DistortionShader->SetUniform2f("OverdriveScales", overdriveScaleRegularRise, overdriveScaleRegularFall);
+ }
+ else
+ {
+ // -1.0f disables PLO
+ DistortionShader->SetUniform2f("OverdriveInvRTSize", -1.0f, -1.0f);
+ }
+
distortionShaderFill.SetInputLayout(DistortionVertexIL);
DistortionShader->SetUniform2f("EyeToSourceUVScale", UVScaleOffset[eyeNum][0].x, UVScaleOffset[eyeNum][0].y);
@@ -437,7 +520,7 @@ void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* righ
if (DistortionCaps & ovrDistortionCap_TimeWarp)
{
- ovrMatrix4f timeWarpMatrices[2];
+ ovrMatrix4f timeWarpMatrices[2];
ovrHmd_GetEyeTimewarpMatrices(HMD, (ovrEyeType)eyeNum,
RState.EyeRenderPoses[eyeNum], timeWarpMatrices);
@@ -446,14 +529,22 @@ void DistortionRenderer::renderDistortion(Texture* leftEyeTexture, Texture* righ
DistortionShader->SetUniform4x4f("EyeRotationEnd", Matrix4f(timeWarpMatrices[1]));
renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum],
- NULL, 0, (int)DistortionMeshVBs[eyeNum]->GetSize(), Prim_Triangles);
+ NULL, 0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles);
}
else
{
renderPrimitives(&distortionShaderFill, DistortionMeshVBs[eyeNum], DistortionMeshIBs[eyeNum],
- NULL, 0, (int)DistortionMeshVBs[eyeNum]->GetSize(), Prim_Triangles);
+ NULL, 0, (int)DistortionMeshIBs[eyeNum]->GetSize()/2, Prim_Triangles);
}
}
+
+ LastUsedOverdriveTextureIndex = currOverdriveTextureIndex;
+
+ // Re-activate to only draw on back buffer
+ if(overdriveActive)
+ {
+ RParams.pContext->OMSetRenderTargets(1, &RParams.pBackBufferRT, 0);
+ }
}
void DistortionRenderer::createDrawQuad()
@@ -500,7 +591,7 @@ void DistortionRenderer::renderLatencyQuad(unsigned char* latencyTesterDrawColor
setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h));
- SimpleQuadShader->SetUniform2f("Scale", 0.2f, 0.2f);
+ SimpleQuadShader->SetUniform2f("Scale", 0.3f, 0.3f);
SimpleQuadShader->SetUniform4f("Color", (float)latencyTesterDrawColor[0] / 255.99f,
(float)latencyTesterDrawColor[0] / 255.99f,
(float)latencyTesterDrawColor[0] / 255.99f,
@@ -508,7 +599,7 @@ void DistortionRenderer::renderLatencyQuad(unsigned char* latencyTesterDrawColor
for(int eyeNum = 0; eyeNum < 2; eyeNum++)
{
- SimpleQuadShader->SetUniform2f("PositionOffset", eyeNum == 0 ? -0.4f : 0.4f, 0.0f);
+ SimpleQuadShader->SetUniform2f("PositionOffset", eyeNum == 0 ? -0.5f : 0.5f, 0.0f);
renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, NULL, 0, numQuadVerts, Prim_TriangleStrip);
}
}
@@ -521,20 +612,29 @@ void DistortionRenderer::renderLatencyPixel(unsigned char* latencyTesterPixelCol
{
createDrawQuad();
}
-
+
ShaderFill quadFill(SimpleQuadShader);
quadFill.SetInputLayout(SimpleQuadVertexIL);
setViewport(Recti(0,0, RParams.RTSize.w, RParams.RTSize.h));
+#ifdef OVR_BUILD_DEBUG
+ SimpleQuadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f,
+ (float)latencyTesterPixelColor[1] / 255.99f,
+ (float)latencyTesterPixelColor[2] / 255.99f,
+ 1.0f);
+
+ Vector2f scale(20.0f / RParams.RTSize.w, 20.0f / RParams.RTSize.h);
+#else
SimpleQuadShader->SetUniform4f("Color", (float)latencyTesterPixelColor[0] / 255.99f,
(float)latencyTesterPixelColor[0] / 255.99f,
(float)latencyTesterPixelColor[0] / 255.99f,
1.0f);
- Vector2f scale(2.0f / RParams.RTSize.w, 2.0f / RParams.RTSize.h);
+ Vector2f scale(1.0f / RParams.RTSize.w, 1.0f / RParams.RTSize.h);
+#endif
SimpleQuadShader->SetUniform2f("Scale", scale.x, scale.y);
- SimpleQuadShader->SetUniform2f("PositionOffset", 1.0f, 1.0f);
+ SimpleQuadShader->SetUniform2f("PositionOffset", 1.0f-scale.x, 1.0f-scale.y);
renderPrimitives(&quadFill, LatencyTesterQuadVB, NULL, NULL, 0, numQuadVerts, Prim_TriangleStrip);
}
@@ -653,7 +753,8 @@ void DistortionRenderer::initShaders()
(void*)vsShaderByteCode.ShaderData, vsShaderByteCode.ShaderSize,
vsShaderByteCode.ReflectionData, vsShaderByteCode.ReflectionSize);
- ID3D1xInputLayout** objRef = &DistortionVertexIL.GetRawRef();
+ DistortionVertexIL = NULL;
+ ID3D1xInputLayout** objRef = &DistortionVertexIL.GetRawRef();
HRESULT validate = RParams.pDevice->CreateInputLayout(
DistortionMeshVertexDesc, sizeof(DistortionMeshVertexDesc) / sizeof(DistortionMeshVertexDesc[0]),
@@ -680,6 +781,7 @@ void DistortionRenderer::initShaders()
SimpleQuad_vs_refl, sizeof(SimpleQuad_vs_refl) / sizeof(SimpleQuad_vs_refl[0]));
//NULL, 0);
+ SimpleQuadVertexIL = NULL;
ID3D1xInputLayout** objRef = &SimpleQuadVertexIL.GetRawRef();
HRESULT validate = RParams.pDevice->CreateInputLayout(
@@ -758,47 +860,279 @@ void DistortionRenderer::destroy()
DistortionRenderer::GraphicsState::GraphicsState(ID3D1xDeviceContext* c)
: context(c)
, rasterizerState(NULL)
+, inputLayoutState(NULL)
+, depthStencilViewState(NULL)
+, omBlendState(NULL)
+, omSampleMaskState(0xffffffff)
+, iaIndexBufferPointerState(NULL)
+, memoryCleared(TRUE)
+, currentPixelShader(NULL)
+, currentVertexShader(NULL)
+, currentGeometryShader(NULL)
+#if (OVR_D3D_VERSION == 11)
+, currentHullShader(NULL)
+, currentDomainShader(NULL)
+#endif
{
- for (int i = 0; i < 8; ++i)
+ for (int i = 0; i < D3D1x_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i)
samplerStates[i] = NULL;
-}
-
-
-void DistortionRenderer::GraphicsState::Save()
-{
- if (rasterizerState != NULL)
- rasterizerState->Release();
- context->RSGetState(&rasterizerState);
+ for (int i = 0; i < D3D1x_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++)
+ {
+ psShaderResourceState[i] = NULL;
+ vsShaderResourceState[i] = NULL;
+ }
- for (int i = 0; i < 8; ++i)
+ for (int i = 0; i < D3D1x_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++)
{
- if (samplerStates[i] != NULL)
- samplerStates[i]->Release();
+ psConstantBuffersState[i] = NULL;
+ vsConstantBuffersState[i] = NULL;
}
- context->PSGetSamplers(0, 8, samplerStates);
-}
+ for (int i = 0; i < D3D1x_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ renderTargetViewState[i] = NULL;
+ for (int i = 0; i < 4; i++)
+ omBlendFactorState[i] = NULL;
-void DistortionRenderer::GraphicsState::Restore()
+ for (int i = 0; i < D3D1x_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++)
+ iaVertexBufferPointersState[i] = NULL;
+}
+
+void DistortionRenderer::GraphicsState::clearMemory()
{
if (rasterizerState != NULL)
{
- context->RSSetState(rasterizerState);
rasterizerState->Release();
rasterizerState = NULL;
}
- for (int i = 0; i < 8; ++i)
+ for (int i = 0; i < D3D1x_COMMONSHADER_SAMPLER_SLOT_COUNT; ++i)
{
if (samplerStates[i] == NULL)
continue;
-
- context->PSSetSamplers(0, 1, &samplerStates[i]);
samplerStates[i]->Release();
samplerStates[i] = NULL;
}
+
+ if (inputLayoutState != NULL)
+ {
+ inputLayoutState->Release();
+ inputLayoutState = NULL;
+ }
+
+ for (int i = 0; i < D3D1x_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; i++)
+ {
+ if (psShaderResourceState[i] != NULL)
+ {
+ psShaderResourceState[i]->Release();
+ psShaderResourceState[i] = NULL;
+ }
+ if (vsShaderResourceState[i] != NULL)
+ {
+ vsShaderResourceState[i]->Release();
+ vsShaderResourceState[i] = NULL;
+ }
+ }
+
+ for (int i = 0; i < D3D1x_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT; i++)
+ {
+ if (psConstantBuffersState[i] != NULL)
+ {
+ psConstantBuffersState[i]->Release();
+ psConstantBuffersState[i] = NULL;
+ }
+ if (vsConstantBuffersState[i] != NULL)
+ {
+ vsConstantBuffersState[i]->Release();
+ vsConstantBuffersState[i] = NULL;
+ }
+ }
+
+ for (int i = 0; i < D3D1x_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ {
+ if (renderTargetViewState[i] != NULL)
+ {
+ renderTargetViewState[i]->Release();
+ renderTargetViewState[i] = NULL;
+ }
+ }
+
+ if (depthStencilViewState != NULL)
+ {
+ depthStencilViewState->Release();
+ depthStencilViewState = NULL;
+ }
+
+ if (omBlendState != NULL)
+ {
+ omBlendState->Release();
+ omBlendState = NULL;
+ }
+
+ if (iaIndexBufferPointerState != NULL)
+ {
+ iaIndexBufferPointerState->Release();
+ iaIndexBufferPointerState = NULL;
+ }
+
+ for (int i = 0; i < D3D1x_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; i++)
+ {
+ if (iaVertexBufferPointersState[i] == NULL)
+ continue;
+ iaVertexBufferPointersState[i]->Release();
+ iaVertexBufferPointersState[i] = NULL;
+ }
+
+ if (currentPixelShader != NULL)
+ {
+ currentPixelShader->Release();
+ currentPixelShader = NULL;
+ }
+
+ if (currentVertexShader != NULL)
+ {
+ currentVertexShader->Release();
+ currentVertexShader = NULL;
+ }
+
+ if (currentGeometryShader != NULL)
+ {
+ currentGeometryShader->Release();
+ currentGeometryShader = NULL;
+ }
+
+#if (OVR_D3D_VERSION == 11)
+
+ if (currentHullShader != NULL)
+ {
+ currentHullShader->Release();
+ currentHullShader = NULL;
+ }
+
+ if (currentDomainShader != NULL)
+ {
+ currentDomainShader->Release();
+ currentDomainShader = NULL;
+ }
+
+#endif
+
+ memoryCleared = TRUE;
+}
+
+DistortionRenderer::GraphicsState::~GraphicsState()
+{
+ clearMemory();
+}
+
+
+void DistortionRenderer::GraphicsState::Save()
+{
+ if (!memoryCleared)
+ clearMemory();
+
+ memoryCleared = FALSE;
+
+ context->RSGetState(&rasterizerState);
+ context->PSGetSamplers(0, D3D1x_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
+ context->IAGetInputLayout(&inputLayoutState);
+
+ context->PSGetShaderResources(0, D3D1x_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, psShaderResourceState);
+ context->VSGetShaderResources(0, D3D1x_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, vsShaderResourceState);
+
+ context->PSGetConstantBuffers(0, D3D1x_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, psConstantBuffersState);
+ context->VSGetConstantBuffers(0, D3D1x_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, vsConstantBuffersState);
+
+ context->OMGetRenderTargets(D3D1x_SIMULTANEOUS_RENDER_TARGET_COUNT, renderTargetViewState, &depthStencilViewState);
+
+ context->OMGetBlendState(&omBlendState, omBlendFactorState, &omSampleMaskState);
+
+ context->IAGetPrimitiveTopology(&primitiveTopologyState);
+
+ context->IAGetIndexBuffer(&iaIndexBufferPointerState, &iaIndexBufferFormatState, &iaIndexBufferOffsetState);
+
+ context->IAGetVertexBuffers(0, D3D1x_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, iaVertexBufferPointersState, iaVertexBufferStridesState, iaVertexBufferOffsetsState);
+
+#if (OVR_D3D_VERSION == 10)
+ context->PSGetShader(&currentPixelShader);
+ context->VSGetShader(&currentVertexShader);
+ context->GSGetShader(&currentGeometryShader);
+#else // Volga says class instance interfaces are very new and almost no one uses them
+ context->PSGetShader(&currentPixelShader, NULL, NULL);
+ context->VSGetShader(&currentVertexShader, NULL, NULL);
+ context->GSGetShader(&currentGeometryShader, NULL, NULL);
+ context->HSGetShader(&currentHullShader, NULL, NULL);
+ context->DSGetShader(&currentDomainShader, NULL, NULL);
+ /* maybe above doesn't work; then do something with this (must test on dx11)
+ ID3D11ClassInstance* blank_array[0];
+ UINT blank_uint = 0;
+ context->PSGetShader(&currentPixelShader, blank_array, blank_uint);
+ context->VSGetShader(&currentVertexShader, blank_array, blank_uint);
+ context->GSGetShader(&currentGeometryShader, blank_array, blank_uint);
+ context->HSGetShader(&currentHullShader, blank_array, blank_uint);
+ context->DSGetShader(&currentDomainShader, blank_array, blank_uint);
+ */
+#endif
+}
+
+
+void DistortionRenderer::GraphicsState::Restore()
+{
+ if (rasterizerState != NULL)
+ context->RSSetState(rasterizerState);
+
+ context->PSSetSamplers(0, D3D1x_COMMONSHADER_SAMPLER_SLOT_COUNT, samplerStates);
+
+ if (inputLayoutState != NULL)
+ context->IASetInputLayout(inputLayoutState);
+
+ if (psShaderResourceState != NULL)
+ context->PSSetShaderResources(0, D3D1x_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, psShaderResourceState);
+
+ if (vsShaderResourceState != NULL)
+ context->VSSetShaderResources(0, D3D1x_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, vsShaderResourceState);
+
+ if (psConstantBuffersState != NULL)
+ context->PSSetConstantBuffers(0, D3D1x_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, psConstantBuffersState);
+
+ if (vsConstantBuffersState != NULL)
+ context->VSSetConstantBuffers(0, D3D1x_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, vsConstantBuffersState);
+
+ if (depthStencilViewState != NULL || renderTargetViewState != NULL)
+ context->OMSetRenderTargets(D3D1x_SIMULTANEOUS_RENDER_TARGET_COUNT, renderTargetViewState, depthStencilViewState);
+
+ if (omBlendState != NULL)
+ context->OMSetBlendState(omBlendState, omBlendFactorState, omSampleMaskState);
+
+ context->IASetPrimitiveTopology(primitiveTopologyState);
+
+ if (iaIndexBufferPointerState != NULL)
+ context->IASetIndexBuffer(iaIndexBufferPointerState, iaIndexBufferFormatState, iaIndexBufferOffsetState);
+
+ if (iaVertexBufferPointersState != NULL)
+ context->IASetVertexBuffers(0, D3D1x_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT, iaVertexBufferPointersState, iaVertexBufferStridesState, iaVertexBufferOffsetsState);
+
+#if (OVR_D3D_VERSION == 10)
+ if (currentPixelShader != NULL)
+ context->PSSetShader(currentPixelShader);
+ if (currentVertexShader != NULL)
+ context->VSSetShader(currentVertexShader);
+ if (currentGeometryShader != NULL)
+ context->GSSetShader(currentGeometryShader);
+#else
+ if (currentPixelShader != NULL)
+ context->PSSetShader(currentPixelShader, NULL, 0);
+ if (currentVertexShader != NULL)
+ context->VSSetShader(currentVertexShader, NULL, 0);
+ if (currentGeometryShader != NULL)
+ context->GSSetShader(currentGeometryShader, NULL, 0);
+ if (currentHullShader != NULL)
+ context->HSSetShader(currentHullShader, NULL, 0);
+ if (currentDomainShader != NULL)
+ context->DSSetShader(currentDomainShader, NULL, 0);
+#endif
+ clearMemory();
}
}}} // OVR::CAPI::D3D1X
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.h
index c4d2619..8543b4a 100644
--- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.h
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_DistortionRenderer.h
@@ -59,9 +59,9 @@ public:
virtual bool Initialize(const ovrRenderAPIConfig* apiConfig,
unsigned distortionCaps);
- virtual void SubmitEye(int eyeId, ovrTexture* eyeTexture);
+ virtual void SubmitEye(int eyeId, const ovrTexture* eyeTexture);
- virtual void EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor);
+ virtual void EndFrame(bool swapBuffers);
// TBD: Make public?
void WaitUntilGpuIdle();
@@ -76,13 +76,50 @@ protected:
{
public:
GraphicsState(ID3D1xDeviceContext* context);
+ virtual ~GraphicsState();
+ virtual void clearMemory();
virtual void Save();
virtual void Restore();
protected:
- ID3D1xRasterizerState* rasterizerState;
- ID3D1xSamplerState* samplerStates[8];
ID3D1xDeviceContext* context;
+ BOOL memoryCleared;
+
+ ID3D1xRasterizerState* rasterizerState;
+ ID3D1xSamplerState* samplerStates[D3D1x_COMMONSHADER_SAMPLER_SLOT_COUNT];
+ ID3D1xInputLayout* inputLayoutState;
+
+ ID3D1xShaderResourceView* psShaderResourceState[D3D1x_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
+ ID3D1xShaderResourceView* vsShaderResourceState[D3D1x_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
+
+ ID3D1xBuffer* psConstantBuffersState[D3D1x_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
+ ID3D1xBuffer* vsConstantBuffersState[D3D1x_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
+
+ ID3D1xRenderTargetView* renderTargetViewState[D3D1x_SIMULTANEOUS_RENDER_TARGET_COUNT];
+ ID3D1xDepthStencilView* depthStencilViewState;
+
+ ID3D1xBlendState* omBlendState;
+ FLOAT omBlendFactorState[4];
+ UINT omSampleMaskState;
+
+ D3D1x_PRIMITIVE_TOPOLOGY primitiveTopologyState;
+
+ ID3D1xBuffer* iaIndexBufferPointerState;
+ DXGI_FORMAT iaIndexBufferFormatState;
+ UINT iaIndexBufferOffsetState;
+
+ ID3D1xBuffer* iaVertexBufferPointersState[D3D1x_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ UINT iaVertexBufferStridesState[D3D1x_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+ UINT iaVertexBufferOffsetsState[D3D1x_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];
+
+ ID3D1xPixelShader* currentPixelShader;
+ ID3D1xVertexShader* currentVertexShader;
+ ID3D1xGeometryShader* currentGeometryShader;
+#if (OVR_D3D_VERSION == 11)
+ ID3D11HullShader* currentHullShader;
+ ID3D11DomainShader* currentDomainShader;
+#endif
+
};
private:
@@ -90,6 +127,7 @@ private:
void initBuffersAndShaders();
void initShaders();
void initFullscreenQuad();
+ void initOverdrive();
void destroy();
void setViewport(const Recti& vp);
@@ -100,6 +138,8 @@ private:
Matrix4f* viewMatrix, int offset, int count,
PrimitiveType rprim);
+ void renderEndFrame();
+
void createDrawQuad();
void renderLatencyQuad(unsigned char* latencyTesterDrawColor);
void renderLatencyPixel(unsigned char* latencyTesterPixelColor);
@@ -114,12 +154,14 @@ private:
// D3DX device and utility variables.
RenderParams RParams;
Ptr<Texture> pEyeTextures[2];
-
+
// U,V scale and offset needed for timewarp.
ovrVector2f UVScaleOffset[2][2];
ovrSizei EyeTextureSize[2];
ovrRecti EyeRenderViewport[2];
+ Ptr<Texture> pOverdriveTextures[NumOverdriveTextures];
+
//Ptr<Buffer> mpFullScreenVertexBuffer;
Ptr<Buffer> DistortionMeshVBs[2]; // one per-eye
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_HSWDisplay.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_HSWDisplay.cpp
new file mode 100644
index 0000000..1e4b11a
--- /dev/null
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_HSWDisplay.cpp
@@ -0,0 +1,592 @@
+/************************************************************************************
+
+Filename : CAPI_D3D1X_HSWDisplay.cpp
+Content : Implements Health and Safety Warning system.
+Created : July 7, 2014
+Authors : Paul Pedriana
+
+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.
+
+************************************************************************************/
+
+// This file is intended to be #included by CAPI_D3D10_HSWDisplay.cpp or CAPI_D3D11_HSWDisplay.cpp,
+// which define OVR_D3D_VERSION to 10 or 11 respectively.
+#if defined(OVR_D3D_VERSION) && ((OVR_D3D_VERSION == 10) || (OVR_D3D_VERSION == 11))
+
+#define _WINSOCKAPI_ // Prevents <Windows.h> from #including <Winsock.h>, as we need the app to use <Winsock2.h> instead.
+#include "../../OVR_CAPI_D3D.h" // OVR_D3D_VERSION will have been defined by who included us.
+#include "CAPI_D3D1X_HSWDisplay.h"
+#include "../../Kernel/OVR_File.h"
+#include "../../Kernel/OVR_SysFile.h"
+#include "../../Kernel/OVR_Math.h"
+#include "../../Kernel/OVR_Allocator.h"
+#include "../../Kernel/OVR_Color.h"
+
+
+#include "../Textures/healthAndSafety.tga.h"
+
+// We currently borrow the SimpleQuad shaders
+#include "../Shaders/SimpleTexturedQuad_vs.h"
+#include "../Shaders/SimpleTexturedQuad_vs_refl.h"
+#include "../Shaders/SimpleTexturedQuad_ps.h"
+#include "../Shaders/SimpleTexturedQuad_ps_refl.h"
+
+
+/*
+#include <d3dcompiler.h>
+
+ID3D10Blob* CompileShader(const char* profile, const char* src, const char* mainName = "main")
+{
+ ID3D10Blob* shader = NULL;
+ ID3D10Blob* errors = NULL;
+ HRESULT hr = D3DCompile(src, strlen(src), NULL, NULL, NULL, mainName, profile, 0, 0, &shader, &errors);
+
+ OVR_ASSERT(SUCCEEDED(hr));
+ if (FAILED(hr))
+ {
+ shader = NULL;
+ OVR_DEBUG_LOG(("Compiling D3D shader for %s failed\n%s\n\n%s", profile, src, errors->GetBufferPointer()));
+ }
+
+ if (errors)
+ errors->Release();
+
+ return shader;
+}
+*/
+
+
+
+// For a given DXGI format: if the format is a typeless one then this function returns a
+// suitable typed one. If the format is a typed one then this function returns it as-is.
+static DXGI_FORMAT GetFullyTypedDXGIFormat(DXGI_FORMAT textureFormat)
+{
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx
+
+ DXGI_FORMAT fullyTypedFormat = textureFormat;
+
+ switch(textureFormat)
+ {
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ return DXGI_FORMAT_R32G32B32A32_FLOAT; // or DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_SINT
+
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ return DXGI_FORMAT_R32G32B32_FLOAT; // or DXGI_FORMAT_R32G32B32_UINT, DXGI_FORMAT_R32G32B32_SINT
+
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ return DXGI_FORMAT_R16G16B16A16_UNORM; // or DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_SNORM, DXGI_FORMAT_R16G16B16A16_SINT
+
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ return DXGI_FORMAT_R8G8B8A8_UNORM; // or DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SINT
+
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
+
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ return DXGI_FORMAT_B8G8R8X8_UNORM_SRGB;
+
+ // Others which we don't currently support:
+ //case DXGI_FORMAT_R32G32_TYPELESS:
+ //case DXGI_FORMAT_R32G8X24_TYPELESS:
+ //case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ //case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ //case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ //case DXGI_FORMAT_R16G16_TYPELESS:
+ //case DXGI_FORMAT_R32_TYPELESS:
+ //case DXGI_FORMAT_R24G8_TYPELESS:
+ //case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ //case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ //case DXGI_FORMAT_R8G8_TYPELESS:
+ //case DXGI_FORMAT_R16_TYPELESS:
+ //case DXGI_FORMAT_R8_TYPELESS:
+ //case DXGI_FORMAT_BC1_TYPELESS:
+ //case DXGI_FORMAT_BC2_TYPELESS:
+ //case DXGI_FORMAT_BC3_TYPELESS:
+ //case DXGI_FORMAT_BC4_TYPELESS:
+ //case DXGI_FORMAT_BC5_TYPELESS:
+ //case DXGI_FORMAT_BC6H_TYPELESS:
+ //case DXGI_FORMAT_BC7_TYPELESS:
+ }
+
+ return fullyTypedFormat;
+}
+
+
+
+namespace OVR { namespace CAPI {
+
+// To do Need to move LoadTextureTgaData to a shared location.
+uint8_t* LoadTextureTgaData(OVR::File* f, uint8_t alpha, int& width, int& height);
+
+
+namespace D3D_NS {
+
+// This is a temporary function implementation, and it functionality needs to be implemented in a more generic way.
+Texture* LoadTextureTga(RenderParams& rParams, ID3D1xSamplerState* pSamplerState, OVR::File* f, uint8_t alpha)
+{
+ OVR::CAPI::D3D_NS::Texture* pTexture = NULL;
+
+ int width, height;
+ const uint8_t* pRGBA = LoadTextureTgaData(f, alpha, width, height);
+
+ if (pRGBA)
+ {
+ pTexture = new OVR::CAPI::D3D_NS::Texture(&rParams, OVR::CAPI::D3D_NS::Texture_RGBA, OVR::Sizei(0,0), pSamplerState, 1);
+
+ // Create the D3D texture
+ D3D1X_(TEXTURE2D_DESC) dsDesc;
+ dsDesc.Width = width;
+ dsDesc.Height = height;
+ dsDesc.MipLevels = 1;
+ dsDesc.ArraySize = 1;
+ dsDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ dsDesc.SampleDesc.Count = 1;
+ dsDesc.SampleDesc.Quality = 0;
+ dsDesc.Usage = D3D1X_(USAGE_DEFAULT);
+ dsDesc.BindFlags = D3D1X_(BIND_SHADER_RESOURCE);
+ dsDesc.CPUAccessFlags = 0;
+ dsDesc.MiscFlags = 0;
+
+ HRESULT hr = rParams.pDevice->CreateTexture2D(&dsDesc, NULL, &pTexture->Tex.GetRawRef());
+
+ if (SUCCEEDED(hr))
+ {
+ if (dsDesc.BindFlags & D3D1X_(BIND_SHADER_RESOURCE))
+ rParams.pDevice->CreateShaderResourceView(pTexture->Tex, NULL, &pTexture->TexSv.GetRawRef());
+
+ rParams.pContext->UpdateSubresource(pTexture->Tex, 0, NULL, pRGBA, width * 4, width * height * 4);
+ }
+ else
+ {
+ OVR_DEBUG_LOG_TEXT(("[LoadTextureTga] CreateTexture2D failed"));
+ pTexture->Release();
+ }
+
+ OVR_FREE(const_cast<uint8_t*>(pRGBA));
+ }
+
+ return pTexture;
+}
+
+
+// Loads a texture from a memory image of a TGA file.
+Texture* LoadTextureTga(RenderParams& rParams, ID3D1xSamplerState* pSamplerState, const uint8_t* pData, int dataSize, uint8_t alpha)
+{
+ MemoryFile memoryFile("", pData, dataSize);
+
+ return LoadTextureTga(rParams, pSamplerState, &memoryFile, alpha);
+}
+
+
+// Loads a texture from a disk TGA file.
+Texture* LoadTextureTga(RenderParams& rParams, ID3D1xSamplerState* pSamplerState, const char* pFilePath, uint8_t alpha)
+{
+ SysFile sysFile;
+
+ if(sysFile.Open(pFilePath, FileConstants::Open_Read | FileConstants::Open_Buffered))
+ return LoadTextureTga(rParams, pSamplerState, &sysFile, alpha);
+
+ return NULL;
+}
+
+
+
+// To do: This needs to be promoted to a central version, possibly in CAPI_HSWDisplay.h
+struct HASWVertex
+{
+ Vector3f Pos;
+ Color C;
+ float U, V;
+
+ HASWVertex(const Vector3f& p, const Color& c = Color(64,0,0,255), float u = 0, float v = 0)
+ : Pos(p), C(c), U(u), V(v)
+ {}
+
+ HASWVertex(float x, float y, float z, const Color& c = Color(64,0,0,255), float u = 0, float v = 0)
+ : Pos(x,y,z), C(c), U(u), V(v)
+ {}
+
+ bool operator==(const HASWVertex& b) const
+ {
+ return (Pos == b.Pos) && (C == b.C) && (U == b.U) && (V == b.V);
+ }
+};
+
+
+
+// The texture below may conceivably be shared between HSWDisplay instances. However,
+// beware that sharing may not be possible if two HMDs are using different locales
+// simultaneously. As of this writing it's not clear if that can occur in practice.
+
+HSWDisplay::HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState)
+ : OVR::CAPI::HSWDisplay(api, hmd, renderState),
+ RenderParams()
+{
+}
+
+bool HSWDisplay::Initialize(const ovrRenderAPIConfig* apiConfig)
+{
+ #if (OVR_D3D_VERSION == 10)
+ const ovrD3D10Config* config = reinterpret_cast<const ovrD3D10Config*>(apiConfig);
+ #else
+ const ovrD3D11Config* config = reinterpret_cast<const ovrD3D11Config*>(apiConfig);
+ #endif
+
+ if(config)
+ {
+ RenderParams.pDevice = config->D3D_NS.pDevice;
+ #if (OVR_D3D_VERSION == 10)
+ RenderParams.pContext = config->D3D10.pDevice;
+ #else
+ RenderParams.pContext = config->D3D11.pDeviceContext;
+ #endif
+ RenderParams.pBackBufferRT = config->D3D_NS.pBackBufferRT;
+ RenderParams.pSwapChain = config->D3D_NS.pSwapChain;
+ RenderParams.RTSize = config->D3D_NS.Header.RTSize;
+ RenderParams.Multisample = config->D3D_NS.Header.Multisample;
+
+ // We may want to create RasterizerState, or alternatively let the DistortionRenderer handle it.
+ }
+ // else do any necessary cleanup
+
+ return true;
+}
+
+void HSWDisplay::Shutdown()
+{
+ UnloadGraphics();
+}
+
+
+void HSWDisplay::DisplayInternal()
+{
+ HSWDISPLAY_LOG(("[HSWDisplay D3D1x] DisplayInternal()"));
+ // We may want to call LoadGraphics here instead of within Render.
+}
+
+
+void HSWDisplay::DismissInternal()
+{
+ HSWDISPLAY_LOG(("[HSWDisplay D3D1x] DismissInternal()"));
+ UnloadGraphics();
+}
+
+
+void HSWDisplay::UnloadGraphics()
+{
+ //RenderParams: nothing to do.
+ pSamplerState.Clear();
+ pTexture.Clear();
+ pVB.Clear();
+ for(size_t i = 0; i < OVR_ARRAY_COUNT(UniformBufferArray); i++)
+ UniformBufferArray[i].Clear();
+ pShaderSet.Clear();
+ pVertexInputLayout.Clear();
+ pBlendState.Clear();
+ pRasterizerState.Clear();
+ // OrthoProjection: No need to clear.
+}
+
+void HSWDisplay::LoadGraphics()
+{
+ // Load the graphics if not loaded already.
+ if(!pSamplerState)
+ {
+ D3D1X_(SAMPLER_DESC) sDesc;
+
+ memset(&sDesc, 0, sizeof(sDesc));
+ sDesc.Filter = D3D1X_(FILTER_MIN_MAG_MIP_LINEAR);
+ sDesc.AddressU = D3D1X_(TEXTURE_ADDRESS_CLAMP);
+ sDesc.AddressV = D3D1X_(TEXTURE_ADDRESS_CLAMP);
+ sDesc.AddressW = D3D1X_(TEXTURE_ADDRESS_CLAMP);
+
+ RenderParams.pDevice->CreateSamplerState(&sDesc, &pSamplerState.GetRawRef());
+ }
+
+ #if defined(OVR_BUILD_DEBUG)
+ if(!pTexture)
+ pTexture = *LoadTextureTga(RenderParams, pSamplerState, "C:\\TestPath\\TestFile.tga", 255);
+ #endif
+
+ if(!pTexture) // To do: Add support for .dds files, which would be significantly smaller than the size of the tga.
+ pTexture = *LoadTextureTga(RenderParams, pSamplerState, healthAndSafety_tga, (int)sizeof(healthAndSafety_tga), 255);
+
+ if(!UniformBufferArray[0])
+ {
+ for(size_t i = 0; i < OVR_ARRAY_COUNT(UniformBufferArray); i++)
+ UniformBufferArray[i] = *new Buffer(&RenderParams);
+ }
+
+ if(!pShaderSet)
+ {
+ pShaderSet = *new ShaderSet;
+
+ // Setup the vertex shader
+ const D3D1X_(INPUT_ELEMENT_DESC) VertexDescription[] = {
+ { "Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(HASWVertex, Pos), D3D1X_(INPUT_PER_VERTEX_DATA), 0 },
+ { "Color", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(HASWVertex, C), D3D1X_(INPUT_PER_VERTEX_DATA), 0 },
+ { "TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(HASWVertex, U), D3D1X_(INPUT_PER_VERTEX_DATA), 0 }
+ };
+
+ Ptr<D3D_NS::VertexShader> vs = *new D3D_NS::VertexShader(&RenderParams, (void*)SimpleTexturedQuad_vs, sizeof(SimpleTexturedQuad_vs), SimpleTexturedQuad_vs_refl, OVR_ARRAY_COUNT(SimpleTexturedQuad_vs_refl));
+ pVertexInputLayout = NULL; // Make sure it's cleared in case it wasn't.
+ ID3D1xInputLayout** ppD3DInputLayout = &pVertexInputLayout.GetRawRef();
+ HRESULT hResult = RenderParams.pDevice->CreateInputLayout(VertexDescription, OVR_ARRAY_COUNT(VertexDescription), SimpleTexturedQuad_vs, sizeof(SimpleTexturedQuad_vs), ppD3DInputLayout);
+ OVR_ASSERT(SUCCEEDED(hResult));
+ if(SUCCEEDED(hResult))
+ pShaderSet->SetShader(vs);
+
+ // Setup the pixel shader
+ Ptr<D3D_NS::PixelShader> ps = *new D3D_NS::PixelShader(&RenderParams, (void*)SimpleTexturedQuad_ps, sizeof(SimpleTexturedQuad_ps), SimpleTexturedQuad_ps_refl, OVR_ARRAY_COUNT(SimpleTexturedQuad_ps_refl));
+ pShaderSet->SetShader(ps);
+
+ if(!pBlendState)
+ {
+ D3D1X_(BLEND_DESC) bm;
+ memset(&bm, 0, sizeof(bm));
+ #if (OVR_D3D_VERSION == 10)
+ bm.BlendEnable[0] = TRUE;
+ bm.BlendOp = bm.BlendOpAlpha = D3D1X_(BLEND_OP_ADD);
+ bm.SrcBlend = bm.SrcBlendAlpha = D3D1X_(BLEND_SRC_ALPHA);
+ bm.DestBlend = bm.DestBlendAlpha = D3D1X_(BLEND_INV_SRC_ALPHA);
+ bm.RenderTargetWriteMask[0] = D3D1X_(COLOR_WRITE_ENABLE_ALL);
+ #else
+ bm.RenderTarget[0].BlendEnable = TRUE;
+ bm.RenderTarget[0].BlendOp = bm.RenderTarget[0].BlendOpAlpha = D3D1X_(BLEND_OP_ADD);
+ bm.RenderTarget[0].SrcBlend = bm.RenderTarget[0].SrcBlendAlpha = D3D1X_(BLEND_SRC_ALPHA);
+ bm.RenderTarget[0].DestBlend = bm.RenderTarget[0].DestBlendAlpha = D3D1X_(BLEND_INV_SRC_ALPHA);
+ bm.RenderTarget[0].RenderTargetWriteMask = D3D1X_(COLOR_WRITE_ENABLE_ALL);
+ #endif
+
+ RenderParams.pDevice->CreateBlendState(&bm, &pBlendState.GetRawRef());
+ }
+
+ if(!pRasterizerState)
+ {
+ D3D1X_(RASTERIZER_DESC) rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.AntialiasedLineEnable = true;
+ rs.CullMode = D3D1X_(CULL_BACK);
+ rs.DepthClipEnable = true;
+ rs.FillMode = D3D1X_(FILL_SOLID);
+
+ RenderParams.pDevice->CreateRasterizerState(&rs, &pRasterizerState.GetRawRef());
+ }
+ }
+
+ if(!pVB)
+ {
+ pVB = *new Buffer(&RenderParams);
+
+ if(pVB)
+ {
+ const size_t vertexCount = 4;
+
+ pVB->Data(Buffer_Vertex, NULL, vertexCount * sizeof(HASWVertex));
+ HASWVertex* pVertices = (HASWVertex*)pVB->Map(0, vertexCount * sizeof(HASWVertex), Map_Discard);
+ OVR_ASSERT(pVertices);
+
+ if(pVertices)
+ {
+ const bool flip = ((RenderState.DistortionCaps & ovrDistortionCap_FlipInput) != 0);
+ const float left = -1.0f; // We currently draw this in normalized device coordinates with an stereo translation
+ const float top = -1.1f; // applied as a vertex shader uniform. In the future when we have a more formal graphics
+ const float right = 1.0f; // API abstraction we may move this draw to an overlay layer or to a more formal
+ const float bottom = 0.9f; // model/mesh scheme with a perspective projection.
+
+ pVertices[0] = HASWVertex(left, top, 0.f, Color(255, 255, 255, 255), 0.f, flip ? 1.f : 0.f);
+ pVertices[1] = HASWVertex(left, bottom, 0.f, Color(255, 255, 255, 255), 0.f, flip ? 0.f : 1.f);
+ pVertices[2] = HASWVertex(right, top, 0.f, Color(255, 255, 255, 255), 1.f, flip ? 1.f : 0.f);
+ pVertices[3] = HASWVertex(right, bottom, 0.f, Color(255, 255, 255, 255), 1.f, flip ? 0.f : 1.f);
+
+ pVB->Unmap(pVertices);
+ }
+ }
+ }
+
+ // Calculate ortho projection.
+ GetOrthoProjection(RenderState, OrthoProjection);
+}
+
+
+// Note: If we are drawing this warning onto the eye texture before distortion, the "time warp" functionality
+// will cause the warning to shake on the screen when the user moves their head. One solution is to disable
+// time warping while the warning or any screen-static GUI elements are present.
+
+void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture)
+{
+ if(RenderEnabled && eyeTexture)
+ {
+ // We need to render to the eyeTexture with the texture viewport.
+ // Setup rendering to the texture.
+ ovrD3D1X(Texture)* eyeTextureD3D = const_cast<ovrD3D1X(Texture)*>(reinterpret_cast<const ovrD3D1X(Texture)*>(eyeTexture));
+ OVR_ASSERT(eyeTextureD3D->Texture.Header.API == ((OVR_D3D_VERSION == 10) ? ovrRenderAPI_D3D10 : ovrRenderAPI_D3D11));
+
+ // D3D10 is currently disabled while we track down a bug that results in a black screen.
+ //if(eyeTextureD3D->Texture.Header.API == ovrRenderAPI_D3D10)
+ // return;
+
+ // Load the graphics if not loaded already.
+ if(!pVB)
+ LoadGraphics();
+
+
+ // Save settings
+ // To do: Merge this saved state with that done by DistortionRenderer::GraphicsState::Save(), and put them in a shared location.
+ Ptr<ID3D1xBlendState> pBlendStateSaved;
+ FLOAT blendFactorSaved[4];
+ UINT blendSampleMaskSaved;
+ RenderParams.pContext->OMGetBlendState(&pBlendStateSaved.GetRawRef(), blendFactorSaved, &blendSampleMaskSaved);
+
+ Ptr<ID3D1xRasterizerState> pRasterizerStateSaved;
+ RenderParams.pContext->RSGetState(&pRasterizerStateSaved.GetRawRef());
+
+ Ptr<ID3D1xRenderTargetView> pTextureRenderTargetViewSaved;
+ Ptr<ID3D1xDepthStencilView> pDepthStencilViewSaved;
+ RenderParams.pContext->OMGetRenderTargets(1, &pTextureRenderTargetViewSaved.GetRawRef(), &pDepthStencilViewSaved.GetRawRef());
+
+ #ifndef D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE // D3D10 doesn't define this, so we pretend that it does.
+ #define D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE 4
+ #endif
+ D3D1x_VIEWPORT d3dViewportSaved[D3D1X_(VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE)];
+ UINT viewportCountSaved = OVR_ARRAY_COUNT(d3dViewportSaved);
+ RenderParams.pContext->RSGetViewports(&viewportCountSaved, d3dViewportSaved);
+
+ UINT stencilRefSaved;
+ Ptr<ID3D1xDepthStencilState> pDepthStencilStateSaved;
+ RenderParams.pContext->OMGetDepthStencilState(&pDepthStencilStateSaved.GetRawRef(), &stencilRefSaved);
+
+ Ptr<ID3D1xInputLayout> pInputLayoutSaved;
+ RenderParams.pContext->IAGetInputLayout(&pInputLayoutSaved.GetRawRef());
+
+ Ptr<ID3D1xBuffer> pVertexBufferSaved;
+ UINT vertexStrideSaved[1];
+ UINT vertexOffsetSaved[1];
+ RenderParams.pContext->IAGetVertexBuffers(0, 1, &pVertexBufferSaved.GetRawRef(), vertexStrideSaved, vertexOffsetSaved);
+
+ D3D1X_(PRIMITIVE_TOPOLOGY) topologySaved;
+ RenderParams.pContext->IAGetPrimitiveTopology(&topologySaved);
+
+
+ // Set our settings
+ RenderParams.pContext->OMSetBlendState(pBlendState, NULL, 0xffffffff);
+ RenderParams.pContext->RSSetState(pRasterizerState);
+
+ // We can't necessarily use a NULL D3D11_RENDER_TARGET_VIEW_DESC argument to CreateRenderTargetView, because we are rendering to
+ // a texture that somebody else created and which may have been created in a typeless format (e.g. DXGI_FORMAT_R8G8B8A8_TYPELESS).
+ // So what we do is check to see if the texture format is a typeless format and if see we pass a suitable D3D11_RENDER_TARGET_VIEW_DESC
+ // to CreateRenderTargetView instead of NULL.
+ D3D1X_(TEXTURE2D_DESC) texture2DDesc;
+ eyeTextureD3D->D3D_NS.pTexture->GetDesc(&texture2DDesc);
+
+ D3D1X_(RENDER_TARGET_VIEW_DESC) renderTargetViewDesc;
+ memset(&renderTargetViewDesc, 0, sizeof(renderTargetViewDesc));
+ renderTargetViewDesc.Format = GetFullyTypedDXGIFormat(texture2DDesc.Format); // DXGI_FORMAT. If this is a typeless format then GetFullyTypedFormat converts it to a fully typed format.
+ renderTargetViewDesc.ViewDimension = (texture2DDesc.SampleDesc.Count > 1) ? D3D1X_(RTV_DIMENSION_TEXTURE2DMS) : D3D1X_(RTV_DIMENSION_TEXTURE2D);
+ renderTargetViewDesc.Texture2D.MipSlice = 0;
+ Ptr<ID3D1xRenderTargetView> pTextureRenderTargetView;
+ HRESULT hResult = RenderParams.pDevice->CreateRenderTargetView(eyeTextureD3D->D3D_NS.pTexture, (renderTargetViewDesc.Format == texture2DDesc.Format) ? NULL : &renderTargetViewDesc, &pTextureRenderTargetView.GetRawRef());
+
+ if(SUCCEEDED(hResult))
+ {
+ RenderParams.pContext->OMSetRenderTargets(1, &pTextureRenderTargetView.GetRawRef(), NULL); // We currently don't bind a depth buffer.
+
+ D3D1x_VIEWPORT D3DViewport;
+
+ OVR_DISABLE_MSVC_WARNING(4244) // conversion from int to float
+ D3DViewport.TopLeftX = eyeTextureD3D->Texture.Header.RenderViewport.Pos.x;
+ D3DViewport.TopLeftY = eyeTextureD3D->Texture.Header.RenderViewport.Pos.y;
+ D3DViewport.Width = eyeTextureD3D->Texture.Header.RenderViewport.Size.w;
+ D3DViewport.Height = eyeTextureD3D->Texture.Header.RenderViewport.Size.h;
+ D3DViewport.MinDepth = 0;
+ D3DViewport.MaxDepth = 1;
+ RenderParams.pContext->RSSetViewports(1, &D3DViewport);
+ OVR_RESTORE_MSVC_WARNING()
+
+ // We don't set up a world/view/projection matrix because we are using
+ // normalized device coordinates below.
+
+ // We don't set the depth state because we aren't using it.
+ // RenderParams.pContext->OMSetDepthStencilState(<depth state>, 0);
+
+ ShaderFill fill(pShaderSet);
+ fill.SetInputLayout(pVertexInputLayout);
+ if(pTexture)
+ fill.SetTexture(0, pTexture);
+
+ const float scale = HSWDISPLAY_SCALE * ((RenderState.OurHMDInfo.HmdType == HmdType_DK1) ? 0.70f : 1.f);
+ pShaderSet->SetUniform2f("Scale", scale, scale / 2.f); // X and Y scale. Y is a fixed proportion to X in order to give a certain aspect ratio.
+ pShaderSet->SetUniform4f("Color", 1.f, 1.f, 1.f, 1.f);
+ pShaderSet->SetUniform2f("PositionOffset", OrthoProjection[eye].GetTranslation().x, 0.0f);
+
+ RenderParams.pContext->IASetInputLayout((ID3D1xInputLayout*)fill.GetInputLayout());
+
+ ID3D1xBuffer* vertexBuffer = pVB->GetBuffer();
+ UINT vertexStride = sizeof(HASWVertex);
+ UINT vertexOffset = 0;
+ RenderParams.pContext->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);
+
+ ShaderBase* vShaderBase = (ShaderBase*)pShaderSet->GetShader(OVR::CAPI::D3D_NS::Shader_Vertex);
+ unsigned char* vertexData = vShaderBase->UniformData;
+
+ if (vertexData)
+ {
+ UniformBufferArray[OVR::CAPI::D3D_NS::Shader_Vertex]->Data(OVR::CAPI::D3D_NS::Buffer_Uniform, vertexData, vShaderBase->UniformsSize);
+ vShaderBase->SetUniformBuffer(UniformBufferArray[OVR::CAPI::D3D_NS::Shader_Vertex]);
+ }
+
+ for (int i = (OVR::CAPI::D3D_NS::Shader_Vertex + 1); i < OVR::CAPI::D3D_NS::Shader_Count; i++)
+ {
+ if (pShaderSet->GetShader(i))
+ {
+ ((ShaderBase*)pShaderSet->GetShader(i))->UpdateBuffer(UniformBufferArray[i]);
+ ((ShaderBase*)pShaderSet->GetShader(i))->SetUniformBuffer(UniformBufferArray[i]);
+ }
+ }
+
+ RenderParams.pContext->IASetPrimitiveTopology(D3D1X_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP));
+ fill.Set(Prim_TriangleStrip);
+
+ RenderParams.pContext->Draw(4, 0);
+ }
+ else
+ {
+ HSWDISPLAY_LOG(("[HSWDisplay D3D1x] CreateRenderTargetView() failed"));
+ }
+
+
+ // Restore settings
+ RenderParams.pContext->IASetPrimitiveTopology(topologySaved);
+ RenderParams.pContext->IASetVertexBuffers(0, 1, &pVertexBufferSaved.GetRawRef(), &vertexStrideSaved[0], &vertexOffsetSaved[0]);
+ RenderParams.pContext->IASetInputLayout(pInputLayoutSaved);
+ RenderParams.pContext->OMSetDepthStencilState(pDepthStencilStateSaved, stencilRefSaved);
+ RenderParams.pContext->RSSetViewports(viewportCountSaved, d3dViewportSaved);
+ RenderParams.pContext->OMSetRenderTargets(1, &pTextureRenderTargetViewSaved.GetRawRef(), pDepthStencilViewSaved);
+ RenderParams.pContext->RSSetState(pRasterizerStateSaved);
+ RenderParams.pContext->OMSetBlendState(pBlendStateSaved, blendFactorSaved, blendSampleMaskSaved);
+ }
+}
+
+}}} // namespace OVR::CAPI::D3D_NS
+
+
+#endif // OVR_D3D_VERSION
+
+
+
+
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_HSWDisplay.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_HSWDisplay.h
new file mode 100644
index 0000000..16391c6
--- /dev/null
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_HSWDisplay.h
@@ -0,0 +1,84 @@
+/************************************************************************************
+
+Filename : CAPI_D3D1X_HSWDisplay.h
+Content : Implements Health and Safety Warning system.
+Created : July 7, 2014
+Authors : Paul Pedriana
+
+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.
+
+************************************************************************************/
+
+// Do not use include guards, as this file is #included separately by both
+// CAPI_D3D10_HSWDisplay.h and CAPI_D3D11_HSWDisplay.h with OVR_D3D_VERSION defined
+// to either 10 or 11. Only those two headers should #include this one.
+//#ifndef OVR_CAPI_D3D1X_HSWDisplay_h
+//#define OVR_CAPI_D3D1X_HSWDisplay_h
+
+//#if !defined(OVR_CAPI_D3D10_HSWDisplay_h) && !defined(OVR_CAPI_D3D11_HSWDisplay_h)
+// #error This header is expected to be compiled only by these two headers.
+//#endif
+#if !defined(OVR_D3D_VERSION) || ((OVR_D3D_VERSION != 10) && (OVR_D3D_VERSION != 11))
+ #error This header expects OVR_D3D_VERSION to be defined, to 10 or 11.
+#endif
+
+#include "../CAPI_HSWDisplay.h"
+#include "CAPI_D3D1X_Util.h"
+
+
+namespace OVR { namespace CAPI { namespace D3D_NS {
+
+ class HSWDisplay : public CAPI::HSWDisplay
+ {
+ public:
+ HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState);
+
+ // Must be called before use. apiConfig is such that:
+ // const ovrD3D11Config* config = (const ovrD3D11Config*)apiConfig; or
+ bool Initialize(const ovrRenderAPIConfig* apiConfig);
+ void Shutdown();
+ void DisplayInternal();
+ void DismissInternal();
+
+ // Draws the warning to the eye texture(s). This must be done at the end of a
+ // frame but prior to executing the distortion rendering of the eye textures.
+ void RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture);
+
+ protected:
+ void LoadGraphics();
+ void UnloadGraphics();
+
+ OVR::CAPI::D3D_NS::RenderParams RenderParams;
+ Ptr<ID3D1xSamplerState> pSamplerState;
+ Ptr<OVR::CAPI::D3D_NS::Texture> pTexture;
+ Ptr<Buffer> pVB;
+ Ptr<Buffer> UniformBufferArray[OVR::CAPI::D3D_NS::Shader_Count];
+ Ptr<ShaderSet> pShaderSet;
+ Ptr<ID3D1xInputLayout> pVertexInputLayout;
+ Ptr<ID3D1xBlendState> pBlendState;
+ Ptr<ID3D1xRasterizerState> pRasterizerState;
+ Matrix4f OrthoProjection[ovrEye_Count];
+
+ private:
+ OVR_NON_COPYABLE(HSWDisplay)
+ };
+
+}}} // namespace OVR::CAPI::D3D_NS
+
+
+
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp
index 501a8e3..e3b438f 100644
--- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.cpp
@@ -116,6 +116,7 @@ bool Buffer::Data(int use, const void *buffer, size_t size)
sr.SysMemPitch = 0;
sr.SysMemSlicePitch = 0;
+ D3DBuffer = NULL;
HRESULT hr = pParams->pDevice->CreateBuffer(&desc, buffer ? &sr : NULL, &D3DBuffer.GetRawRef());
if (SUCCEEDED(hr))
{
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h
index 7bbc685..9aa5e43 100644
--- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D1X_Util.h
@@ -42,6 +42,7 @@ limitations under the License.
#include "../../Kernel/OVR_Math.h"
#if defined(OVR_OS_WIN32)
+#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <comdef.h> // for _COM_SMARTPTR_TYPEDEF()
@@ -107,6 +108,12 @@ typedef D3D1X_(VIEWPORT) D3D1x_VIEWPORT;
typedef D3D1X_(QUERY_DESC) D3D1x_QUERY_DESC;
typedef D3D1X_(SHADER_BUFFER_DESC) D3D1x_SHADER_BUFFER_DESC;
typedef D3D1X_(SHADER_VARIABLE_DESC) D3D1x_SHADER_VARIABLE_DESC;
+typedef D3D1X_(PRIMITIVE_TOPOLOGY) D3D1x_PRIMITIVE_TOPOLOGY;
+static const int D3D1x_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT = D3D1X_(COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT);
+static const int D3D1x_COMMONSHADER_SAMPLER_SLOT_COUNT = D3D1X_(COMMONSHADER_SAMPLER_SLOT_COUNT);
+static const int D3D1x_SIMULTANEOUS_RENDER_TARGET_COUNT = D3D1X_(SIMULTANEOUS_RENDER_TARGET_COUNT);
+static const int D3D1x_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT = D3D1X_(IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT);
+static const int D3D1x_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT = D3D1X_(COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT);
// Blob is the same
typedef ID3D10Blob ID3D1xBlob;
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp
index e8cf767..a685191 100644
--- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.cpp
@@ -70,7 +70,7 @@ bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig,
screenSize = config->D3D9.Header.RTSize;
distortionCaps = arg_distortionCaps;
- GfxState = *new GraphicsState(device);
+ GfxState = *new GraphicsState(device, distortionCaps);
CreateVertexDeclaration();
CreateDistortionShaders();
@@ -81,7 +81,7 @@ bool DistortionRenderer::Initialize(const ovrRenderAPIConfig* apiConfig,
/**************************************************************/
-void DistortionRenderer::SubmitEye(int eyeId, ovrTexture* eyeTexture)
+void DistortionRenderer::SubmitEye(int eyeId, const ovrTexture* eyeTexture)
{
//Doesn't do a lot in here??
const ovrD3D9Texture* tex = (const ovrD3D9Texture*)eyeTexture;
@@ -99,51 +99,70 @@ void DistortionRenderer::SubmitEye(int eyeId, ovrTexture* eyeTexture)
ovrHmd_GetRenderScaleAndOffset( erd.Fov,
eachEye[eyeId].TextureSize, eachEye[eyeId].RenderViewport,
eachEye[eyeId].UVScaleOffset );
-}
+ if (RState.DistortionCaps & ovrDistortionCap_FlipInput)
+ {
+ eachEye[eyeId].UVScaleOffset[0].y = -eachEye[eyeId].UVScaleOffset[0].y;
+ eachEye[eyeId].UVScaleOffset[1].y = 1.0f - eachEye[eyeId].UVScaleOffset[1].y;
+ }
+}
-/******************************************************************/
-void DistortionRenderer::EndFrame(bool swapBuffers,
- unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor)
+void DistortionRenderer::renderEndFrame()
{
- OVR_UNUSED(swapBuffers);
- OVR_UNUSED(latencyTesterDrawColor);
+ RenderBothDistortionMeshes();
- ///QUESTION : Should I be clearing the screen?
- ///QUESTION : Should I be ensuring the screen is the render target
+ if(RegisteredPostDistortionCallback)
+ RegisteredPostDistortionCallback(device);
- if (!TimeManager.NeedDistortionTimeMeasurement())
+ if(LatencyTest2Active)
{
- if (RState.DistortionCaps & ovrDistortionCap_TimeWarp)
- {
- // Wait for timewarp distortion if it is time and Gpu idle
- WaitTillTimeAndFlushGpu(TimeManager.GetFrameTiming().TimewarpPointTime);
- }
-
- RenderBothDistortionMeshes();
+ // TODO:
+ //renderLatencyPixel(LatencyTest2DrawColor);
}
- else
+}
+
+/******************************************************************/
+void DistortionRenderer::EndFrame(bool swapBuffers)
+{
+ ///QUESTION : Clear the screen?
+ ///QUESTION : Ensure the screen is the render target
+
+ // Don't spin if we are explicitly asked not to
+ if (RState.DistortionCaps & ovrDistortionCap_TimeWarp &&
+ !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits))
{
- // If needed, measure distortion time so that TimeManager can better estimate
- // latency-reducing time-warp wait timing.
- WaitUntilGpuIdle();
- double distortionStartTime = ovr_GetTimeInSeconds();
+ if (!TimeManager.NeedDistortionTimeMeasurement())
+ {
+ // Wait for timewarp distortion if it is time and Gpu idle
+ FlushGpuAndWaitTillTime(TimeManager.GetFrameTiming().TimewarpPointTime);
- RenderBothDistortionMeshes();
- WaitUntilGpuIdle();
+ renderEndFrame();
+ }
+ else
+ {
+ // If needed, measure distortion time so that TimeManager can better estimate
+ // latency-reducing time-warp wait timing.
+ WaitUntilGpuIdle();
+ double distortionStartTime = ovr_GetTimeInSeconds();
- TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime);
- }
+ renderEndFrame();
- if(latencyTesterDrawColor)
+ WaitUntilGpuIdle();
+ TimeManager.AddDistortionTimeMeasurement(ovr_GetTimeInSeconds() - distortionStartTime);
+ }
+ }
+ else
{
- ///QUESTION : Is this still to be supported?
- ///renderLatencyQuad(latencyTesterDrawColor);
+ renderEndFrame();
}
- if(latencyTester2DrawColor)
+ if(RegisteredPostDistortionCallback)
+ RegisteredPostDistortionCallback(device);
+
+ if(LatencyTestDrawColor)
{
- // TODO:
+ // TODO: Support latency tester quad
+ ///renderLatencyQuad(latencyTesterDrawColor);
}
if (swapBuffers)
@@ -159,7 +178,10 @@ void DistortionRenderer::EndFrame(bool swapBuffers,
// Force GPU to flush the scene, resulting in the lowest possible latency.
// It's critical that this flush is *after* present.
- WaitUntilGpuIdle();
+ // Doesn't need to be done if running through the Oculus driver.
+ if (RState.OurHMDInfo.InCompatibilityMode &&
+ !(RState.DistortionCaps & ovrDistortionCap_ProfileNoTimewarpSpinWaits))
+ WaitUntilGpuIdle();
}
}
@@ -174,38 +196,29 @@ void DistortionRenderer::WaitUntilGpuIdle()
if(pEventQuery!=NULL)
{
pEventQuery->Issue(D3DISSUE_END) ;
- while(S_FALSE == pEventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH)) ;
+ while(S_FALSE == pEventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH)){}
+ pEventQuery->Release();
}
}
}
-double DistortionRenderer::WaitTillTimeAndFlushGpu(double absTime)
+double DistortionRenderer::FlushGpuAndWaitTillTime(double absTime)
{
- double initialTime = ovr_GetTimeInSeconds();
+ double initialTime = ovr_GetTimeInSeconds();
if (initialTime >= absTime)
return 0.0;
WaitUntilGpuIdle();
- double newTime = initialTime;
- volatile int i;
-
- while (newTime < absTime)
- {
- for (int j = 0; j < 50; j++)
- i = 0;
- newTime = ovr_GetTimeInSeconds();
- }
-
- // How long we waited
- return newTime - initialTime;
+ return WaitTillTime(absTime);
}
-DistortionRenderer::GraphicsState::GraphicsState(IDirect3DDevice9* d)
+DistortionRenderer::GraphicsState::GraphicsState(IDirect3DDevice9* d, unsigned arg_distortionCaps)
: device(d)
, numSavedStates(0)
+, distortionCaps(arg_distortionCaps)
{
}
@@ -238,6 +251,7 @@ void DistortionRenderer::GraphicsState::Save()
RecordAndSetState(0, D3DSAMP_BORDERCOLOR, 0x000000 );
RecordAndSetState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER );
RecordAndSetState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER );
+ RecordAndSetState(0, D3DSAMP_SRGBTEXTURE, (distortionCaps & ovrDistortionCap_SRGB) ? TRUE : FALSE );
RecordAndSetState(1, D3DRS_MULTISAMPLEANTIALIAS, FALSE );
RecordAndSetState(1, D3DRS_DITHERENABLE, FALSE );
@@ -254,6 +268,7 @@ void DistortionRenderer::GraphicsState::Save()
RecordAndSetState(1, D3DRS_DEPTHBIAS , 0 );
RecordAndSetState(1, D3DRS_LIGHTING, FALSE );
RecordAndSetState(1, D3DRS_FOGENABLE, FALSE );
+ RecordAndSetState(1, D3DRS_SRGBWRITEENABLE, (distortionCaps & ovrDistortionCap_SRGB) ? TRUE : FALSE );
}
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h
index f24eb31..be5aa5f 100644
--- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_DistortionRenderer.h
@@ -29,6 +29,7 @@ limitations under the License.
#undef new
#if defined (OVR_OS_WIN32)
+#define WIN32_LEAN_AND_MEAN
#if _MSC_VER < 1700
#include <d3dx9.h>
#else
@@ -63,23 +64,23 @@ public:
virtual bool Initialize(const ovrRenderAPIConfig* apiConfig,
unsigned distortionCaps);
- virtual void SubmitEye(int eyeId, ovrTexture* eyeTexture);
+ virtual void SubmitEye(int eyeId, const ovrTexture* eyeTexture);
- virtual void EndFrame(bool swapBuffers, unsigned char* latencyTesterDrawColor, unsigned char* latencyTester2DrawColor);
+ virtual void EndFrame(bool swapBuffers);
// TBD: Make public?
void WaitUntilGpuIdle();
// Similar to ovr_WaitTillTime but it also flushes GPU.
// Note, it exits when time expires, even if GPU is not in idle state yet.
- double WaitTillTimeAndFlushGpu(double absTime);
+ double FlushGpuAndWaitTillTime(double absTime);
protected:
class GraphicsState : public CAPI::DistortionRenderer::GraphicsState
{
public:
- GraphicsState(IDirect3DDevice9* d);
+ GraphicsState(IDirect3DDevice9* d, unsigned arg_distortionCaps);
virtual void Save();
virtual void Restore();
@@ -98,6 +99,7 @@ protected:
//Keep track of how many we've done, for reverting
int numSavedStates;
IDirect3DDevice9* device;
+ unsigned distortionCaps;
};
private:
@@ -110,6 +112,7 @@ private:
void RecordAndSetState(int which, int type, DWORD newValue);
void RevertAllStates(void);
+ void renderEndFrame();
//Data, structures and pointers
IDirect3DDevice9 * device;
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_HSWDisplay.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_HSWDisplay.cpp
new file mode 100644
index 0000000..3daad5d
--- /dev/null
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_HSWDisplay.cpp
@@ -0,0 +1,433 @@
+/************************************************************************************
+
+Filename : CAPI_D3D9_HSWDisplay.cpp
+Content : Implements Health and Safety Warning system.
+Created : July 7, 2014
+Authors : Paul Pedriana
+
+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.
+
+************************************************************************************/
+
+#define OVR_D3D_VERSION 9
+#include "CAPI_D3D9_HSWDisplay.h"
+#include "../../OVR_CAPI_D3D.h"
+#undef OVR_D3D_VERSION
+
+#include <d3d9.h>
+#include "../../Kernel/OVR_File.h"
+#include "../../Kernel/OVR_SysFile.h"
+#include "../../Kernel/OVR_Math.h"
+#include "../../Kernel/OVR_Allocator.h"
+#include "../../Kernel/OVR_Color.h"
+
+#include "../Textures/healthAndSafety.tga.h"
+
+
+
+namespace OVR { namespace CAPI {
+
+
+// To do Need to move LoadTextureTgaData to a shared location.
+uint8_t* LoadTextureTgaData(OVR::File* f, uint8_t alpha, int& width, int& height);
+
+
+namespace D3D9 {
+
+// This is a temporary function implementation, and it functionality needs to be implemented in a more generic way.
+IDirect3DTexture9* LoadTextureTga(HSWRenderParams& rParams, OVR::File* f, uint8_t alpha)
+{
+ IDirect3DTexture9* pTexture = NULL;
+
+ int width, height;
+ const uint8_t* pRGBA = LoadTextureTgaData(f, alpha, width, height);
+
+ if (pRGBA)
+ {
+ // We don't have access to D3DX9 and so we currently have to do this manually instead of calling a D3DX9 utility function.
+ Ptr<IDirect3DTexture9> pTextureSysmem;
+ HRESULT hResult = rParams.Device->CreateTexture((UINT)width, (UINT)height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pTextureSysmem.GetRawRef(), NULL);
+
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("CreateTexture(D3DPOOL_SYSTEMMEM) failed. %d (%x)", hResult, hResult)); }
+ else
+ {
+ // Lock the texture so we can write this frame's texel data
+ D3DLOCKED_RECT lock;
+ hResult = pTextureSysmem->LockRect(0, &lock, NULL, D3DLOCK_NOSYSLOCK | D3DLOCK_NO_DIRTY_UPDATE);
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("LockRect failed. %d (%x)", hResult, hResult)); }
+ else
+ {
+ // Four bytes per pixel. Pitch bytes per row (will be >= w * 4).
+ uint8_t* pRow = (uint8_t*)lock.pBits;
+ const uint8_t* pSource = pRGBA;
+
+ for(int y = 0; y < height; y++, pRow += lock.Pitch, pSource += (width * 4))
+ {
+ uint8_t* pDest = pRow;
+
+ for(int x = 0, xEnd = width * 4; x < xEnd; x += 4)
+ {
+ pDest[x + 0] = pSource[x + 2];
+ pDest[x + 1] = pSource[x + 1];
+ pDest[x + 2] = pSource[x + 0];
+ pDest[x + 3] = pSource[x + 3];
+ }
+ }
+
+ pTextureSysmem->UnlockRect(0);
+
+ hResult = rParams.Device->CreateTexture((UINT)width, (UINT)height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTexture, NULL);
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("CreateTexture(D3DPOOL_DEFAULT) failed. %d (%x)", hResult, hResult)); }
+ else
+ {
+ hResult = rParams.Device->UpdateTexture(pTextureSysmem, pTexture);
+ if(FAILED(hResult))
+ {
+ HSWDISPLAY_LOG(("UpdateTexture failed. %d (%x)", hResult, hResult));
+ pTexture->Release();
+ pTexture = NULL;
+ }
+ }
+ }
+ }
+
+ OVR_FREE(const_cast<uint8_t*>(pRGBA));
+ }
+
+ return pTexture;
+}
+
+
+// Loads a texture from a memory image of a TGA file.
+IDirect3DTexture9* LoadTextureTga(HSWRenderParams& rParams, const uint8_t* pData, int dataSize, uint8_t alpha)
+{
+ MemoryFile memoryFile("", pData, dataSize);
+
+ return LoadTextureTga(rParams, &memoryFile, alpha);
+}
+
+
+// Loads a texture from a disk TGA file.
+IDirect3DTexture9* LoadTextureTga(HSWRenderParams& rParams, const char* pFilePath, uint8_t alpha)
+{
+ SysFile sysFile;
+
+ if(sysFile.Open(pFilePath, FileConstants::Open_Read | FileConstants::Open_Buffered))
+ return LoadTextureTga(rParams, &sysFile, alpha);
+
+ return NULL;
+}
+
+
+
+// To do: This needs to be promoted to a central version, possibly in CAPI_HSWDisplay.h
+struct HASWVertex
+{
+ Vector3f Pos;
+ Color C;
+ float U, V;
+
+ HASWVertex(const Vector3f& p, const Color& c = Color(64,0,0,255), float u = 0, float v = 0)
+ : Pos(p), C(c), U(u), V(v)
+ {}
+
+ HASWVertex(float x, float y, float z, const Color& c = Color(64,0,0,255), float u = 0, float v = 0)
+ : Pos(x,y,z), C(c), U(u), V(v)
+ {}
+
+ bool operator==(const HASWVertex& b) const
+ {
+ return (Pos == b.Pos) && (C == b.C) && (U == b.U) && (V == b.V);
+ }
+};
+
+#define HASWVertexD3D9Format (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
+
+
+// The texture below may conceivably be shared between HSWDisplay instances. However,
+// beware that sharing may not be possible if two HMDs are using different locales
+// simultaneously. As of this writing it's not clear if that can occur in practice.
+
+HSWDisplay::HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState)
+ : OVR::CAPI::HSWDisplay(api, hmd, renderState)
+ , RenderParams()
+{
+}
+
+bool HSWDisplay::Initialize(const ovrRenderAPIConfig* apiConfig)
+{
+ const ovrD3D9Config* config = reinterpret_cast<const ovrD3D9Config*>(apiConfig);
+
+ if(config)
+ {
+ RenderParams.Device = config->D3D9.pDevice;
+ RenderParams.SwapChain = config->D3D9.pSwapChain;
+ RenderParams.ScreenSize = config->D3D9.Header.RTSize;
+ }
+ else
+ {
+ UnloadGraphics();
+ }
+
+ return true;
+}
+
+void HSWDisplay::Shutdown()
+{
+ UnloadGraphics();
+}
+
+void HSWDisplay::DisplayInternal()
+{
+ HSWDISPLAY_LOG(("[HSWDisplay D3D9] DisplayInternal()"));
+ // We may want to call LoadGraphics here instead of within Render.
+}
+
+void HSWDisplay::DismissInternal()
+{
+ HSWDISPLAY_LOG(("[HSWDisplay D3D9] DismissInternal()"));
+ UnloadGraphics();
+}
+
+
+void HSWDisplay::UnloadGraphics()
+{
+ // RenderParams: No need to clear.
+ pTexture.Clear();
+ pVB.Clear();
+ // OrthoProjection: No need to clear.
+}
+
+
+void HSWDisplay::LoadGraphics()
+{
+ // As of this writing, we don't yet have an abstraction for Textures, Buffers, and Shaders like we do for D3D11, D3D11, and OpenGL.
+ #if defined(OVR_BUILD_DEBUG)
+ if(!pTexture)
+ pTexture = *LoadTextureTga(RenderParams, "C:\\TestPath\\TestFile.tga", 255);
+ #endif
+
+ if(!pTexture)
+ {
+ D3DCAPS9 caps;
+ RenderParams.Device->GetDeviceCaps(&caps);
+
+ if(caps.TextureCaps & (D3DPTEXTURECAPS_SQUAREONLY | D3DPTEXTURECAPS_POW2))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] Square textures allowed only.")); }
+
+ pTexture = *LoadTextureTga(RenderParams, healthAndSafety_tga, (int)sizeof(healthAndSafety_tga), 255);
+ OVR_ASSERT(pTexture);
+ }
+
+ if(!pVB)
+ {
+ HRESULT hResult = RenderParams.Device->CreateVertexBuffer(4 * sizeof(HASWVertex), NULL, HASWVertexD3D9Format, D3DPOOL_MANAGED, &pVB.GetRawRef(), NULL);
+
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] CreateVertexBuffer failed. %d (%x)", hResult, hResult)); }
+ else
+ {
+ void* pVerticesVoid;
+ hResult = pVB->Lock(0, 0, (void**)&pVerticesVoid, 0);
+
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] Lock failed. %d (%x)", hResult, hResult)); }
+ else
+ {
+ HASWVertex* pVertices = reinterpret_cast<HASWVertex*>(pVerticesVoid);
+
+ const bool flip = ((RenderState.DistortionCaps & ovrDistortionCap_FlipInput) != 0);
+ const float left = -1.0f;
+ const float top = -1.1f;
+ const float right = +1.0f;
+ const float bottom = +0.9f;
+
+ pVertices[0] = HASWVertex(left, top, 0.f, Color(255, 255, 255, 255), 0.f, flip ? 1.f : 0.f); // To do: Make this branchless
+ pVertices[1] = HASWVertex(left, bottom, 0.f, Color(255, 255, 255, 255), 0.f, flip ? 0.f : 1.f);
+ pVertices[2] = HASWVertex(right, top, 0.f, Color(255, 255, 255, 255), 1.f, flip ? 1.f : 0.f);
+ pVertices[3] = HASWVertex(right, bottom, 0.f, Color(255, 255, 255, 255), 1.f, flip ? 0.f : 1.f);
+
+ pVB->Unlock();
+ }
+ }
+ }
+
+ // Calculate ortho projection.
+ GetOrthoProjection(RenderState, OrthoProjection);
+}
+
+
+void HSWDisplay::RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture)
+{
+ if(RenderEnabled && eyeTexture)
+ {
+ // Note: The D3D9 implementation below is entirely fixed-function and isn't yet using shaders.
+ // For the time being this is sufficient, but future designs will likely necessitate moving
+ // to a system that uses programmable shaders.
+
+ // We need to render to the eyeTexture with the texture viewport.
+ // Setup rendering to the texture.
+ ovrD3D9Texture* eyeTextureD3D9 = const_cast<ovrD3D9Texture*>(reinterpret_cast<const ovrD3D9Texture*>(eyeTexture));
+ OVR_ASSERT(eyeTextureD3D9->Texture.Header.API == ovrRenderAPI_D3D9);
+
+
+ // Save previous state.
+ // To do: Merge this saved state with that done by DistortionRenderer::GraphicsState::Save(), and put them in a shared location.
+ DWORD fvfSaved;
+ RenderParams.Device->GetFVF(&fvfSaved);
+
+ Ptr<IDirect3DVertexBuffer9> pVBDSaved;
+ UINT vbOffsetSaved;
+ UINT vbStrideSaved;
+ RenderParams.Device->GetStreamSource(0, &pVBDSaved.GetRawRef(), &vbOffsetSaved, &vbStrideSaved);
+
+ Ptr<IDirect3DBaseTexture9> pTexture0Saved;
+ RenderParams.Device->GetTexture(0, &pTexture0Saved.GetRawRef());
+ Ptr<IDirect3DBaseTexture9> pTexture1Saved;
+ RenderParams.Device->GetTexture(1, &pTexture1Saved.GetRawRef());
+
+ D3DMATRIX worldMatrixSaved, viewMatrixSaved, projectionMatrixSaved, texture0MatrixSaved;
+ RenderParams.Device->GetTransform(D3DTS_WORLD, &worldMatrixSaved);
+ RenderParams.Device->GetTransform(D3DTS_VIEW, &viewMatrixSaved);
+ RenderParams.Device->GetTransform(D3DTS_PROJECTION, &projectionMatrixSaved);
+ RenderParams.Device->GetTransform(D3DTS_TEXTURE0, &texture0MatrixSaved);
+
+ Ptr<IDirect3DVertexShader9> pVertexShaderSaved;
+ RenderParams.Device->GetVertexShader(&pVertexShaderSaved.GetRawRef());
+
+ Ptr<IDirect3DPixelShader9> pPixelShaderSaved;
+ RenderParams.Device->GetPixelShader(&pPixelShaderSaved.GetRawRef());
+
+ D3DVIEWPORT9 viewportSaved;
+ RenderParams.Device->GetViewport(&viewportSaved);
+
+ Ptr<IDirect3DSurface9> pRenderTargetSaved;
+ RenderParams.Device->GetRenderTarget(0, &pRenderTargetSaved.GetRawRef());
+
+
+ // Load the graphics if not loaded already.
+ if(!pTexture)
+ LoadGraphics();
+
+ HRESULT hResult;
+
+ hResult = RenderParams.Device->BeginScene();
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] BeginScene failed. %d (%x)", hResult, hResult)); }
+
+ Ptr<IDirect3DSurface9> pDestSurface;
+ hResult = eyeTextureD3D9->D3D9.pTexture->GetSurfaceLevel(0, &pDestSurface.GetRawRef());
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] GetSurfaceLevel failed. %d (%x)", hResult, hResult)); }
+
+ hResult = RenderParams.Device->SetRenderTarget(0, pDestSurface);
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] SetRenderTarget failed. %d (%x)", hResult, hResult)); }
+
+ D3DVIEWPORT9 D3DViewport;
+ D3DViewport.X = eyeTextureD3D9->Texture.Header.RenderViewport.Pos.x;
+ D3DViewport.Y = eyeTextureD3D9->Texture.Header.RenderViewport.Pos.y;
+ D3DViewport.Width = eyeTextureD3D9->Texture.Header.RenderViewport.Size.w;
+ D3DViewport.Height = eyeTextureD3D9->Texture.Header.RenderViewport.Size.h;
+ D3DViewport.MinZ = 0;
+ D3DViewport.MaxZ = 1;
+ hResult = RenderParams.Device->SetViewport(&D3DViewport);
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] SetViewport failed. %d (%x)", hResult, hResult)); }
+
+ hResult = RenderParams.Device->SetTexture(0, pTexture);
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] SetTexture failed. %d (%x)", hResult, hResult)); }
+
+ RenderParams.Device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ RenderParams.Device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ RenderParams.Device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
+
+ RenderParams.Device->SetVertexShader(NULL);
+ RenderParams.Device->SetPixelShader(NULL);
+
+ hResult = RenderParams.Device->SetStreamSource(0, pVB, 0, sizeof(HASWVertex));
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] SetStreamSource failed. %d (%x)", hResult, hResult)); }
+
+ RenderParams.Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ RenderParams.Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+ RenderParams.Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ RenderParams.Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+ RenderParams.Device->SetRenderState(D3DRS_LIGHTING, FALSE);
+ RenderParams.Device->SetRenderState(D3DRS_ZENABLE, FALSE);
+ RenderParams.Device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ RenderParams.Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+ RenderParams.Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
+ RenderParams.Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
+
+ const float scale = HSWDISPLAY_SCALE * ((RenderState.OurHMDInfo.HmdType == HmdType_DK1) ? 0.70f : 1.f);
+ Matrix4f identityMatrix = Matrix4f::Identity();
+ Vector3f translation = OrthoProjection[eye].GetTranslation();
+ Matrix4f orthoStereoMatrix(
+ scale, 0, 0, 0,
+ 0, scale / 2, 0, 0,
+ 0, 0, HSWDISPLAY_DISTANCE, 0,
+ translation.x, translation.y, translation.z, 1
+ );
+ RenderParams.Device->SetTransform(D3DTS_WORLD, reinterpret_cast<const D3DMATRIX*>(&identityMatrix));
+ RenderParams.Device->SetTransform(D3DTS_VIEW, reinterpret_cast<const D3DMATRIX*>(&identityMatrix));
+ RenderParams.Device->SetTransform(D3DTS_PROJECTION, reinterpret_cast<const D3DMATRIX*>(&orthoStereoMatrix));
+ RenderParams.Device->SetTransform(D3DTS_TEXTURE0, reinterpret_cast<const D3DMATRIX*>(&identityMatrix));
+
+ hResult = RenderParams.Device->SetFVF(HASWVertexD3D9Format);
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] SetFVF failed. %d (%x)", hResult, hResult)); }
+
+ hResult = RenderParams.Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] DrawPrimitive failed. %d (%x)", hResult, hResult)); }
+
+ hResult = RenderParams.Device->EndScene();
+ if(FAILED(hResult))
+ { HSWDISPLAY_LOG(("[HSWDisplay D3D9] EndScene failed. %d (%x)", hResult, hResult)); }
+
+
+ // Restore previous state.
+ RenderParams.Device->SetRenderTarget(0, pRenderTargetSaved);
+ RenderParams.Device->SetViewport(&viewportSaved);
+ RenderParams.Device->SetPixelShader(pPixelShaderSaved);
+ RenderParams.Device->SetVertexShader(pVertexShaderSaved);
+ RenderParams.Device->SetTransform(D3DTS_TEXTURE0, &texture0MatrixSaved);
+ RenderParams.Device->SetTransform(D3DTS_PROJECTION, &projectionMatrixSaved);
+ RenderParams.Device->SetTransform(D3DTS_VIEW, &viewMatrixSaved);
+ RenderParams.Device->SetTransform(D3DTS_WORLD, &worldMatrixSaved);
+ RenderParams.Device->SetTexture(0, pTexture0Saved);
+ RenderParams.Device->SetTexture(1, pTexture1Saved);
+ RenderParams.Device->SetStreamSource(0, pVBDSaved, vbOffsetSaved, vbStrideSaved);
+ RenderParams.Device->SetFVF(fvfSaved);
+ }
+}
+
+
+}}} // namespace OVR::CAPI::D3D9
+
+
+
+
+
+
+
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_HSWDisplay.h b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_HSWDisplay.h
new file mode 100644
index 0000000..6fbd58f
--- /dev/null
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_HSWDisplay.h
@@ -0,0 +1,82 @@
+/************************************************************************************
+
+Filename : CAPI_D3D9_HSWDisplay.h
+Content : Implements Health and Safety Warning system.
+Created : July 7, 2014
+Authors : Paul Pedriana
+
+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_CAPI_D3D9_HSWDisplay_h
+#define OVR_CAPI_D3D9_HSWDisplay_h
+
+#if !defined(OVR_D3D_VERSION) || (OVR_D3D_VERSION != 9)
+ #error This header expects OVR_D3D_VERSION to be defined, to 9.
+#endif
+
+#include "../CAPI_HSWDisplay.h"
+#include "CAPI_D3D1X_Util.h"
+#include <d3d9.h>
+
+
+namespace OVR { namespace CAPI { namespace D3D9 {
+
+ // There currently isn't a D3D9::RenderParams, as D3D9 support is currently only very basic.
+ struct HSWRenderParams
+ {
+ IDirect3DDevice9* Device;
+ IDirect3DSwapChain9* SwapChain;
+ ovrSizei ScreenSize;
+ };
+
+ class HSWDisplay : public CAPI::HSWDisplay
+ {
+ public:
+ HSWDisplay(ovrRenderAPIType api, ovrHmd hmd, const HMDRenderState& renderState);
+
+ // Must be called before use. apiConfig is such that:
+ // const ovrD3D9Config* config = (const ovrD3D9Config*)apiConfig; or
+ bool Initialize(const ovrRenderAPIConfig* apiConfig);
+ void Shutdown();
+ void DisplayInternal();
+ void DismissInternal();
+
+ // Draws the warning to the eye texture(s). This must be done at the end of a
+ // frame but prior to executing the distortion rendering of the eye textures.
+ void RenderInternal(ovrEyeType eye, const ovrTexture* eyeTexture);
+
+ protected:
+ void LoadGraphics();
+ void UnloadGraphics();
+
+ D3D9::HSWRenderParams RenderParams;
+ Ptr<IDirect3DTexture9> pTexture;
+ Ptr<IDirect3DVertexBuffer9> pVB;
+ Matrix4f OrthoProjection[2]; // Projection for 2D.
+
+ private:
+ OVR_NON_COPYABLE(HSWDisplay)
+ };
+
+}}} // namespace OVR::CAPI::D3D9
+
+
+#endif // OVR_CAPI_D3D9_HSWDisplay_h
+
diff --git a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_Util.cpp b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_Util.cpp
index e6bdcb6..cc164df 100644
--- a/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_Util.cpp
+++ b/LibOVR/Src/CAPI/D3D1X/CAPI_D3D9_Util.cpp
@@ -32,17 +32,18 @@ limitations under the License.
namespace OVR { namespace CAPI { namespace D3D9 {
-#define PRECOMPILE_FLAG 0
+#define PRECOMPILE_FLAG 0
#if !PRECOMPILE_FLAG
//To make these, you need to run it with PRECOMPILE_FLAG, which also uses them, so good for debugging.
//Then cut and paste these from the output window.
//Then turn off the flag.
-DWORD precompiledVertexShaderSrc[95] = {4294836736,3014654,1111577667,28,127,4294836736,2,28,33024,120,68,131074,655361,88,0,104,2,131073,88,0,1415936325,1668436847,1716475477,1952805734,2880154368,196609,131073,1,0,1415936325,1668436847,1666405973,6646881,845116278,1291858015,1869767529,1952870259,693250080,1397508128,1750278220,1919247457,1836008224,1701603696,775495794,959330610,858665525,3223857,83886161,2685337601,1065353216,0,1056964608,0,33554463,2147483648,2416902144,33554463,2147614720,2416902145,33554463,2147483653,2416902146,33554463,2147549189,2416902147,33554463,2147614725,2416902148,33554433,2147680256,2699296768,67108868,3758292992,2162425856,2430861314,2699296770,67108868,3758292993,2162425856,2430861315,2699296770,67108868,3758292994,2162425856,2430861316,2699296770,67108868,3222208512,2416181248,2689597441,2686779393,33554433,3758161923,2415919105,65535,};
-DWORD precompiledVertexShaderTimewarpSrc[293] = {4294836736,4456446,1111577667,28,215,4294836736,4,28,33024,208,108,1310722,5373956,124,0,140,262146,1179652,124,0,157,131074,655361,176,0,192,2,131073,176,0,1382381893,1952543855,1164865385,2868929646,196611,262148,1,0,1382381893,1952543855,1399746409,1953653108,1702446336,1918070612,1331058019,1702061670,2880110708,196609,131073,1,0,1415936325,1668436847,1666405973,6646881,845116278,1291858015,1869767529,1952870259,693250080,1397508128,1750278220,1919247457,1836008224,1701603696,775495794,959330610,858665525,3223857,83886161,2685337601,1065353216,0,1056964608,0,33554463,2147483648,2416902144,33554463,2147549184,2416902145,33554463,2147614720,2416902146,33554463,2147483653,2416902147,33554463,2147549189,2416902148,33554463,2147614725,2416902149,33554433,2147549184,2695495684,50331650,2147549185,2164260864,2695495700,33554433,2147614720,2695495685,50331650,2147614721,2169831424,2695495701,33554433,2147745792,2695495686,50331650,2147745793,2175401984,2695495702,33554433,2148007936,2695495687,50331650,2148007937,2180972544,2695495703,67108868,2148466688,2415919105,2162425857,2162425856,67108868,2148466689,2416181251,2689597441,2684682241,50331657,2147549186,2162425856,2162425857,33554438,2147549186,2147483650,33554433,2147680259,2699296772,50331650,2147876866,2177892355,2697986068,67108868,2147549187,2415919105,2158624770,2689925124,67108868,2147549188,2415919105,2153054210,2684354564,33554433,2147680261,2699296773,50331650,2147876866,2177105925,2697199637,67108868,2147614723,2415919105,2153054210,2689925125,67108868,2147614724,2415919105,2158624770,2684354565,33554433,2147680261,2699296774,50331650,2147811333,2177171461,2697265174,67108868,2147745795,2415919105,2147483653,2689925126,67108868,2147745796,2415919105,2158624773,2684354566,33554433,2147680261,2699296775,50331650,2148073477,2166685701,2686779415,67108868,2148007939,2415919105,2147483653,2689925127,67108868,2148007940,2415919105,2164195333,2684354567,50331657,2147549189,2162425860,2162425857,50331657,2147614725,2162425859,2162425857,50331653,2147680257,2147483650,2162425861,33554433,2147680258,2699296768,67108868,3758292992,2162425858,2162425857,2699296770,67108868,2148466689,2416181252,2689597441,2684682241,50331657,2147549189,2162425860,2162425857,50331657,2147614725,2162425859,2162425857,50331657,2147549185,2162425856,2162425857,33554438,2147549185,2147483649,50331653,2147680257,2147483649,2162425861,67108868,3758292993,2162425858,2162425857,2699296770,67108868,2148466689,2416181253,2689597441,2684682241,50331657,2147549188,2162425860,2162425857,50331657,2147614724,2162425859,2162425857,50331657,2147549184,2162425856,2162425857,33554438,2147549184,2147483648,50331653,2147680256,2147483648,2162425860,67108868,3758292994,2162425858,2162425856,2699296770,67108868,3222208512,2416181248,2689597441,2686779393,33554433,3758161923,2415919106,65535,};
-DWORD precompiledPixelShaderSrc[84] = {4294902528,2228222,1111577667,28,79,4294902528,1,28,33024,72,48,3,131073,56,0,1954047316,6648437,786436,65537,1,0,861893488,1291858015,1869767529,1952870259,693250080,1397508128,1750278220,1919247457,1836008224,1701603696,775495794,959330610,858665525,3223857,83886161,2685337600,1065353216,0,0,0,33554463,2147483653,2416115712,33554463,2147549189,2416115713,33554463,2147614725,2416115714,33554463,2147680261,2415984643,33554463,2415919104,2685339648,50331714,2148466688,2430861312,2699298816,67108868,2148073472,2147483648,2690908160,2686779392,50331714,2148466689,2430861313,2699298816,33554433,2147614720,2153054209,50331714,2148466689,2430861314,2699298816,33554433,2147745792,2158624769,50331653,2148468736,2162425856,2415919107,65535,};
+DWORD precompiledVertexShaderSrc[96] = {4294836736,3080190,1111577667,28,130,4294836736,2,28,33024,123,68,131074,655361,88,0,104,2,131073,88,0,1415936325,1970230127,1432707954,1717981014,7628147,196609,131073,1,0,1415936325,1970230127,1432707954,1633899350,1979737452,1597136755,1766654000,1936683619,544499311,539578920,1280527432,1634226976,544367972,1886220099,1919249513,841890080,892939833,825437746,2868916529,83886161,2685337601,1065353216,0,1056964608,0,33554463,2147483648,2416902144,33554463,2147614720,2416902145,33554463,2147483653,2416902146,33554463,2147549189,2416902147,33554463,2147614725,2416902148,33554433,2147680256,2699296768,67108868,3758292992,2162425856,2430861314,2699296770,67108868,3758292993,2162425856,2430861315,2699296770,67108868,3758292994,2162425856,2430861316,2699296770,67108868,3222208512,2416181248,2689597441,2686779393,33554433,3758161923,2415919105,65535,};
+DWORD precompiledVertexShaderTimewarpSrc[310] = {4294836992,4587518,1111577667,28,222,4294836992,4,28,33024,215,108,1310722,5373956,124,0,140,262146,1179652,124,0,157,131074,655361,180,0,196,2,131073,180,0,1382381893,1952543855,1164865385,2868929646,196611,262148,1,0,1382381893,1952543855,1399746409,1953653108,1702446336,1867738964,1701016181,1716475477,1952805734,2880154368,196609,131073,1,0,1415936325,1970230127,1432707954,1633899350,1979737452,1597202291,1766654000,1936683619,544499311,539578920,1280527432,1634226976,544367972,1886220099,1919249513,841890080,892939833,825437746,2868916529,83886161,2685337601,1065353216,0,1056964608,0,33554463,2147483648,2416902144,33554463,2147549184,2416902145,33554463,2147614720,2416902146,33554463,2147483653,2416902147,33554463,2147549189,2416902148,33554463,2147614725,2416902149,33554463,2147483648,3759079424,33554463,2147483653,3758292993,33554463,2147549189,3758292994,33554463,2147614725,3758292995,33554463,2147680261,3758161924,33554433,2147549184,2695495684,50331650,2147549185,2164260864,2695495700,33554433,2147614720,2695495685,50331650,2147614721,2169831424,2695495701,33554433,2147745792,2695495686,50331650,2147745793,2175401984,2695495702,33554433,2148007936,2695495687,50331650,2148007937,2180972544,2695495703,67108868,2148466688,2415919105,2162425857,2162425856,67108868,2148466689,2416181251,2689597441,2684682241,50331657,2147549186,2162425856,2162425857,33554438,2147549186,2147483650,33554433,2147680259,2699296772,50331650,2147876866,2177892355,2697986068,67108868,2147549187,2415919105,2158624770,2689925124,67108868,2147549188,2415919105,2153054210,2684354564,33554433,2147680261,2699296773,50331650,2147876866,2177105925,2697199637,67108868,2147614723,2415919105,2153054210,2689925125,67108868,2147614724,2415919105,2158624770,2684354565,33554433,2147680261,2699296774,50331650,2147811333,2177171461,2697265174,67108868,2147745795,2415919105,2147483653,2689925126,67108868,2147745796,2415919105,2158624773,2684354566,33554433,2147680261,2699296775,50331650,2148073477,2166685701,2686779415,67108868,2148007939,2415919105,2147483653,2689925127,67108868,2148007940,2415919105,2164195333,2684354567,50331657,2147549189,2162425860,2162425857,50331657,2147614725,2162425859,2162425857,50331653,2147680257,2147483650,2162425861,33554433,2147680258,2699296768,67108868,3758292993,2162425858,2162425857,2699296770,67108868,2148466689,2416181252,2689597441,2684682241,50331657,2147549189,2162425860,2162425857,50331657,2147614725,2162425859,2162425857,50331657,2147549185,2162425856,2162425857,33554438,2147549185,2147483649,50331653,2147680257,2147483649,2162425861,67108868,3758292994,2162425858,2162425857,2699296770,67108868,2148466689,2416181253,2689597441,2684682241,50331657,2147549188,2162425860,2162425857,50331657,2147614724,2162425859,2162425857,50331657,2147549184,2162425856,2162425857,33554438,2147549184,2147483648,50331653,2147680256,2147483648,2162425860,67108868,3758292995,2162425858,2162425856,2699296770,67108868,3759079424,2416181248,2689597441,2686779393,33554433,3758161924,2415919106,65535,};
+DWORD precompiledPixelShaderSrc[84] = {4294902528,2228222,1111577667,28,79,4294902528,1,28,33024,72,48,3,131073,56,0,1954047316,6648437,786436,65537,1,0,861893488,1291858015,1869767529,1952870259,693250080,1397508128,1750278220,1919247457,1836008224,1701603696,775495794,959330610,858665525,3223857,83886161,2685337600,1065353216,0,0,0,33554463,2147483653,2416115712,33554463,2147549189,2416115713,33554463,2147614725,2416115714,33554463,2147680261,2415984643,33554463,2415919104,2685339648,50331714,2148466688,2430861312,2699298816,67108868,2148073472,2147483648,2690908160,2686779392,50331714,2148466689,2430861313,2699298816,33554433,2147614720,2153054209,50331714,2148466689,2430861314,2699298816,33554433,2147745792,2158624769,50331653,2148468736,2162425856,2415919107,65535,};
#else
#include "d3dcompiler.h"
+#pragma comment(lib, "C:\\Program Files (x86)\\Microsoft DirectX SDK (June 2010)\\Lib\\x86\\D3DCompiler.lib")
/***************************************************************************/
const char* VertexShaderSrc =
@@ -146,7 +147,7 @@ void DistortionRenderer::CreateDistortionShaders(void)
device->CreateVertexShader( ( DWORD* )pShaderCode->GetBufferPointer(), &vertexShader );
pShaderCode->Release();
- pShaderCode = ShaderCompile("precompiledVertexShaderTimewarpSrc",VertexShaderTimewarpSrc,"vs_2_0");
+ pShaderCode = ShaderCompile("precompiledVertexShaderTimewarpSrc",VertexShaderTimewarpSrc,"vs_3_0");
device->CreateVertexShader( ( DWORD* )pShaderCode->GetBufferPointer(), &vertexShaderTimewarp );
pShaderCode->Release();
@@ -197,11 +198,13 @@ void DistortionRenderer::Create_Distortion_Models(void)
D3DPOOL_MANAGED, &e->dxVerts, NULL );
ovrDistortionVertex * dxv; e->dxVerts->Lock( 0, 0, (void**)&dxv, 0 );
for (int v=0;v<e->numVerts;v++) dxv[v] = meshData.pVertexData[v];
+ e->dxVerts->Unlock();
device->CreateIndexBuffer( (e->numIndices)*sizeof(u_short),0, D3DFMT_INDEX16,
D3DPOOL_MANAGED, &e->dxIndices, NULL );
unsigned short* dxi; e->dxIndices->Lock( 0, 0, (void**)&dxi, 0 );
for (int i=0;i<e->numIndices;i++) dxi[i] = meshData.pIndexData[i];
+ e->dxIndices->Unlock();
ovrHmd_DestroyDistortionMesh( &meshData );
}
@@ -210,10 +213,21 @@ void DistortionRenderer::Create_Distortion_Models(void)
/**********************************************************/
void DistortionRenderer::RenderBothDistortionMeshes(void)
{
+ device->BeginScene();
+
+ D3DCOLOR clearColor = D3DCOLOR_RGBA(
+ (int)(RState.ClearColor[0] * 255.0f),
+ (int)(RState.ClearColor[1] * 255.0f),
+ (int)(RState.ClearColor[2] * 255.0f),
+ (int)(RState.ClearColor[3] * 255.0f));
+
+ device->Clear(1, NULL, D3DCLEAR_TARGET, clearColor, 0, 0);
+
for (int eye=0; eye<2; eye++)
{
FOR_EACH_EYE * e = &eachEye[eye];
D3DVIEWPORT9 vp; vp.X=0; vp.Y=0; vp.Width=screenSize.w; vp.Height=screenSize.h; vp.MinZ=0; vp.MaxZ = 1;
+
device->SetViewport(&vp);
device->SetStreamSource( 0, e->dxVerts,0, sizeof(ovrDistortionVertex) );
device->SetVertexDeclaration( vertexDecl );
@@ -249,6 +263,8 @@ void DistortionRenderer::RenderBothDistortionMeshes(void)
device->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0,0,e->numVerts,0,e->numIndices/3);
}
+
+ device->EndScene();
}
}}} \ No newline at end of file