Render_D3D1X_Device.cpp
Go to the documentation of this file.
00001 /************************************************************************************
00002 
00003 Filename    :   Renderer_D3D1x.cpp
00004 Content     :   RenderDevice implementation  for D3DX10/11.
00005 Created     :   September 10, 2012
00006 Authors     :   Andrew Reisse
00007 
00008 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
00009 
00010 Licensed under the Apache License, Version 2.0 (the "License");
00011 you may not use this file except in compliance with the License.
00012 You may obtain a copy of the License at
00013 
00014 http://www.apache.org/licenses/LICENSE-2.0
00015 
00016 Unless required by applicable law or agreed to in writing, software
00017 distributed under the License is distributed on an "AS IS" BASIS,
00018 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019 See the License for the specific language governing permissions and
00020 limitations under the License.
00021 
00022 ************************************************************************************/
00023 
00024 #include "Kernel/OVR_Log.h"
00025 #include "Kernel/OVR_Std.h"
00026 
00027 #include "Render_D3D1X_Device.h"
00028 
00029 #include <d3dcompiler.h>
00030 
00031 #if (OVR_D3D_VERSION == 10)
00032 namespace OVR { namespace Render { namespace D3D10 {
00033 #else
00034 namespace OVR { namespace Render { namespace D3D11 {
00035 #endif
00036 
00037 static D3D1x_(INPUT_ELEMENT_DESC) ModelVertexDesc[] =
00038 {
00039     {"Position", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Pos),   D3D1x_(INPUT_PER_VERTEX_DATA), 0},
00040     {"Color",    0, DXGI_FORMAT_R8G8B8A8_UNORM,  0, offsetof(Vertex, C),     D3D1x_(INPUT_PER_VERTEX_DATA), 0},
00041     {"TexCoord", 0, DXGI_FORMAT_R32G32_FLOAT,    0, offsetof(Vertex, U),     D3D1x_(INPUT_PER_VERTEX_DATA), 0},
00042     {"TexCoord", 1, DXGI_FORMAT_R32G32_FLOAT,    0, offsetof(Vertex, U2),        D3D1x_(INPUT_PER_VERTEX_DATA), 0},
00043     {"Normal",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(Vertex, Norm),  D3D1x_(INPUT_PER_VERTEX_DATA), 0},
00044 };
00045 
00046 
00047 static const char* StdVertexShaderSrc =
00048     "float4x4 Proj;\n"
00049     "float4x4 View;\n"
00050     "struct Varyings\n"
00051     "{\n"
00052     "   float4 Position : SV_Position;\n"
00053     "   float4 Color    : COLOR0;\n"
00054     "   float2 TexCoord : TEXCOORD0;\n"
00055     "   float2 TexCoord1 : TEXCOORD1;\n"
00056     "   float3 Normal   : NORMAL;\n"
00057     "   float3 VPos     : TEXCOORD4;\n"
00058     "};\n"
00059     "void main(in float4 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord : TEXCOORD0, in float2 TexCoord1 : TEXCOORD1, in float3 Normal : NORMAL,\n"
00060     "          out Varyings ov)\n"
00061     "{\n"
00062     "   ov.Position = mul(Proj, mul(View, Position));\n"
00063     "   ov.Normal = mul(View, Normal);\n"
00064     "   ov.VPos = mul(View, Position);\n"
00065     "   ov.TexCoord = TexCoord;\n"
00066     "   ov.TexCoord1 = TexCoord1;\n"
00067     "   ov.Color = Color;\n"
00068     "}\n";
00069 
00070 static const char* DirectVertexShaderSrc =
00071     "float4x4 View : register(c4);\n"
00072     "void main(in float4 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord : TEXCOORD0, in float2 TexCoord1 : TEXCOORD1, in float3 Normal : NORMAL,\n"
00073     "          out float4 oPosition : SV_Position, out float4 oColor : COLOR, out float2 oTexCoord : TEXCOORD0, out float2 oTexCoord1 : TEXCOORD1, out float3 oNormal : NORMAL)\n"
00074     "{\n"
00075     "   oPosition = mul(View, Position);\n"
00076     "   oTexCoord = TexCoord;\n"
00077     "   oTexCoord1 = TexCoord1;\n"
00078     "   oColor = Color;\n"
00079     "   oNormal = mul(View, Normal);\n"
00080     "}\n";
00081 
00082 static const char* SolidPixelShaderSrc =
00083     "float4 Color;\n"
00084     "struct Varyings\n"
00085     "{\n"
00086     "   float4 Position : SV_Position;\n"
00087     "   float4 Color    : COLOR0;\n"
00088     "   float2 TexCoord : TEXCOORD0;\n"
00089     "};\n"
00090     "float4 main(in Varyings ov) : SV_Target\n"
00091     "{\n"
00092     "   return Color;\n"
00093     "}\n";
00094 
00095 static const char* GouraudPixelShaderSrc =
00096     "struct Varyings\n"
00097     "{\n"
00098     "   float4 Position : SV_Position;\n"
00099     "   float4 Color    : COLOR0;\n"
00100     "   float2 TexCoord : TEXCOORD0;\n"
00101     "};\n"
00102     "float4 main(in Varyings ov) : SV_Target\n"
00103     "{\n"
00104     "   return ov.Color;\n"
00105     "}\n";
00106 
00107 static const char* TexturePixelShaderSrc =
00108     "Texture2D Texture : register(t0);\n"
00109     "SamplerState Linear : register(s0);\n"
00110     "struct Varyings\n"
00111     "{\n"
00112     "   float4 Position : SV_Position;\n"
00113     "   float4 Color    : COLOR0;\n"
00114     "   float2 TexCoord : TEXCOORD0;\n"
00115     "};\n"
00116     "float4 main(in Varyings ov) : SV_Target\n"
00117     "{\n"
00118     "   float4 color2 = ov.Color * Texture.Sample(Linear, ov.TexCoord);\n"
00119     "   if (color2.a <= 0.4)\n"
00120     "           discard;\n"
00121     "   return color2;\n"
00122     "}\n";
00123 
00124 static const char* MultiTexturePixelShaderSrc =
00125     "Texture2D Texture[2] : register(t0);\n"
00126     "SamplerState Linear : register(s0);\n"
00127     "struct Varyings\n"
00128     "{\n"
00129     "   float4 Position : SV_Position;\n"
00130     "   float4 Color    : COLOR0;\n"
00131     "   float2 TexCoord : TEXCOORD0;\n"
00132     "   float2 TexCoord1 : TEXCOORD1;\n"
00133     "};\n"
00134     "float4 main(in Varyings ov) : SV_Target\n"
00135     "{\n"
00136     "float4 color1;\n"
00137     "float4 color2;\n"
00138     "   color1 = Texture[0].Sample(Linear, ov.TexCoord);\n"
00139     "   color2 = Texture[1].Sample(Linear, ov.TexCoord1);\n"
00140     "   color2.rgb = color2.rgb * lerp(1.2, 1.9, saturate(length(color2.rgb)));\n"
00141     "   color2 = color1 * color2;\n"
00142     "   if (color2.a <= 0.4)\n"
00143     "           discard;\n"
00144     "   return color2;\n"
00145     "}\n";
00146 
00147 #define LIGHTING_COMMON                 \
00148     "cbuffer Lighting : register(b1)\n" \
00149     "{\n"                               \
00150     "    float3 Ambient;\n"             \
00151     "    float3 LightPos[8];\n"         \
00152     "    float4 LightColor[8];\n"       \
00153     "    float  LightCount;\n"          \
00154     "};\n"                              \
00155     "struct Varyings\n"                 \
00156     "{\n"                                       \
00157     "   float4 Position : SV_Position;\n"       \
00158     "   float4 Color    : COLOR0;\n"            \
00159     "   float2 TexCoord : TEXCOORD0;\n"         \
00160     "   float3 Normal   : NORMAL;\n"            \
00161     "   float3 VPos     : TEXCOORD4;\n"         \
00162     "};\n"                                      \
00163     "float4 DoLight(Varyings v)\n"              \
00164     "{\n"                                       \
00165     "   float3 norm = normalize(v.Normal);\n"   \
00166     "   float3 light = Ambient;\n"              \
00167     "   for (uint i = 0; i < LightCount; i++)\n"\
00168     "   {\n"                                        \
00169     "       float3 ltp = (LightPos[i] - v.VPos);\n" \
00170     "       float  ldist = dot(ltp,ltp);\n"         \
00171     "       ltp = normalize(ltp);\n"                \
00172     "       light += saturate(LightColor[i] * v.Color.rgb * dot(norm, ltp) / sqrt(ldist));\n"\
00173     "   }\n"                                        \
00174     "   return float4(light, v.Color.a);\n"         \
00175     "}\n"
00176 
00177 static const char* LitSolidPixelShaderSrc =
00178     LIGHTING_COMMON
00179     "float4 main(in Varyings ov) : SV_Target\n"
00180     "{\n"
00181     "   return DoLight(ov) * ov.Color;\n"
00182     "}\n";
00183 
00184 static const char* LitTexturePixelShaderSrc =
00185     "Texture2D Texture : register(t0);\n"
00186     "SamplerState Linear : register(s0);\n"
00187     LIGHTING_COMMON
00188     "float4 main(in Varyings ov) : SV_Target\n"
00189     "{\n"
00190     "   return DoLight(ov) * Texture.Sample(Linear, ov.TexCoord);\n"
00191     "}\n";
00192 
00193 static const char* AlphaTexturePixelShaderSrc =
00194     "Texture2D Texture : register(t0);\n"
00195     "SamplerState Linear : register(s0);\n"
00196     "struct Varyings\n"
00197     "{\n"
00198     "   float4 Position : SV_Position;\n"
00199     "   float4 Color    : COLOR0;\n"
00200     "   float2 TexCoord : TEXCOORD0;\n"
00201     "};\n"
00202     "float4 main(in Varyings ov) : SV_Target\n"
00203     "{\n"
00204     "   return ov.Color * float4(1,1,1,Texture.Sample(Linear, ov.TexCoord).r);\n"
00205     "}\n";
00206 
00207 
00208 // ***** PostProcess Shader
00209 
00210 static const char* PostProcessVertexShaderSrc =
00211     "float4x4 View : register(c4);\n"
00212     "float4x4 Texm : register(c8);\n"
00213     "void main(in float4 Position : POSITION, in float4 Color : COLOR0, in float2 TexCoord : TEXCOORD0, in float2 TexCoord1 : TEXCOORD1,\n"
00214     "          out float4 oPosition : SV_Position, out float4 oColor : COLOR, out float2 oTexCoord : TEXCOORD0)\n"
00215     "{\n"
00216     "   oPosition = mul(View, Position);\n"
00217     "   oTexCoord = mul(Texm, float4(TexCoord,0,1));\n"
00218     "   oColor = Color;\n"
00219     "}\n";
00220 
00221 // Shader with just lens distortion correction.
00222 static const char* PostProcessPixelShaderSrc =
00223     "Texture2D Texture : register(t0);\n"
00224     "SamplerState Linear : register(s0);\n"
00225     "float2 LensCenter;\n"
00226     "float2 ScreenCenter;\n"
00227     "float2 Scale;\n"
00228     "float2 ScaleIn;\n"
00229     "float4 HmdWarpParam;\n"
00230     "\n"
00231 
00232     // Scales input texture coordinates for distortion.
00233     // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
00234     // larger due to aspect ratio.
00235     "float2 HmdWarp(float2 in01)\n"
00236     "{\n"
00237     "   float2 theta = (in01 - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
00238     "   float  rSq = theta.x * theta.x + theta.y * theta.y;\n"
00239     "   float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
00240     "                   HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
00241     "   return LensCenter + Scale * theta1;\n"
00242     "}\n"
00243 
00244     "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n"
00245     " in float2 oTexCoord : TEXCOORD0) : SV_Target\n"
00246     "{\n"
00247     "   float2 tc = HmdWarp(oTexCoord);\n"
00248     "   if (any(clamp(tc, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tc))\n"
00249     "       return 0;\n"
00250     "   return Texture.Sample(Linear, tc);\n"
00251     "}\n";
00252 
00253 // Shader with lens distortion and chromatic aberration correction.
00254 static const char* PostProcessPixelShaderWithChromAbSrc =
00255     "Texture2D Texture : register(t0);\n"
00256     "SamplerState Linear : register(s0);\n"
00257     "float2 LensCenter;\n"
00258     "float2 ScreenCenter;\n"
00259     "float2 Scale;\n"
00260     "float2 ScaleIn;\n"
00261     "float4 HmdWarpParam;\n"
00262     "float4 ChromAbParam;\n"
00263     "\n"
00264 
00265     // Scales input texture coordinates for distortion.
00266     // ScaleIn maps texture coordinates to Scales to ([-1, 1]), although top/bottom will be
00267     // larger due to aspect ratio.
00268     "float4 main(in float4 oPosition : SV_Position, in float4 oColor : COLOR,\n"
00269     "            in float2 oTexCoord : TEXCOORD0) : SV_Target\n"
00270     "{\n"
00271     "   float2 theta = (oTexCoord - LensCenter) * ScaleIn;\n" // Scales to [-1, 1]
00272     "   float  rSq = theta.x * theta.x + theta.y * theta.y;\n"
00273     "   float2 theta1 = theta * (HmdWarpParam.x + HmdWarpParam.y * rSq + "
00274     "                   HmdWarpParam.z * rSq * rSq + HmdWarpParam.w * rSq * rSq * rSq);\n"
00275     "   \n"
00276     "   // Detect whether blue texture coordinates are out of range since these will scaled out the furthest.\n"
00277     "   float2 thetaBlue = theta1 * (ChromAbParam.z + ChromAbParam.w * rSq);\n"
00278     "   float2 tcBlue = LensCenter + Scale * thetaBlue;\n"
00279     "   if (any(clamp(tcBlue, ScreenCenter-float2(0.25,0.5), ScreenCenter+float2(0.25, 0.5)) - tcBlue))\n"
00280     "       return 0;\n"
00281     "   \n"
00282     "   // Now do blue texture lookup.\n"
00283     "   float  blue = Texture.Sample(Linear, tcBlue).b;\n"
00284     "   \n"
00285     "   // Do green lookup (no scaling).\n"
00286     "   float2 tcGreen = LensCenter + Scale * theta1;\n"
00287     "   float4 greenColor = Texture.Sample(Linear, tcGreen);\n"
00288     "   float  green = greenColor.g;\n"
00289     "   float  alpha = greenColor.a;\n"
00290     "   \n"
00291     "   // Do red scale and lookup.\n"
00292     "   float2 thetaRed = theta1 * (ChromAbParam.x + ChromAbParam.y * rSq);\n"
00293     "   float2 tcRed = LensCenter + Scale * thetaRed;\n"
00294     "   float  red = Texture.Sample(Linear, tcRed).r;\n"
00295     "   \n"
00296     "   return float4(red, green, blue, alpha);\n"
00297     "}\n";
00298 
00299 
00300 static const char* VShaderSrcs[VShader_Count] =
00301 {
00302     DirectVertexShaderSrc,
00303     StdVertexShaderSrc,
00304     PostProcessVertexShaderSrc
00305 };
00306 static const char* FShaderSrcs[FShader_Count] =
00307 {
00308     SolidPixelShaderSrc,
00309     GouraudPixelShaderSrc,
00310     TexturePixelShaderSrc,
00311     AlphaTexturePixelShaderSrc,
00312     PostProcessPixelShaderSrc,
00313     PostProcessPixelShaderWithChromAbSrc,
00314     LitSolidPixelShaderSrc,
00315     LitTexturePixelShaderSrc,
00316     MultiTexturePixelShaderSrc
00317 };
00318 
00319 RenderDevice::RenderDevice(const RendererParams& p, HWND window)
00320 {
00321     RECT rc;
00322     GetClientRect(window, &rc);
00323     UINT width = rc.right - rc.left;
00324     UINT height = rc.bottom - rc.top;
00325     WindowWidth = width;
00326     WindowHeight = height;
00327     Window = window;
00328 
00329     Params = p;
00330     HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&DXGIFactory.GetRawRef()));
00331     if (FAILED(hr))    
00332         return;
00333 
00334     // Find the adapter & output (monitor) to use for fullscreen, based on the reported name of the HMD's monitor.
00335     if (Params.Display.MonitorName.GetLength() > 0)
00336     {
00337         for(UINT AdapterIndex = 0; ; AdapterIndex++)
00338         {
00339             HRESULT hr = DXGIFactory->EnumAdapters(AdapterIndex, &Adapter.GetRawRef());
00340             if (hr == DXGI_ERROR_NOT_FOUND)
00341                 break;
00342 
00343             DXGI_ADAPTER_DESC Desc;
00344             Adapter->GetDesc(&Desc);
00345 
00346             UpdateMonitorOutputs();
00347 
00348             if (FullscreenOutput)
00349                 break;
00350         }
00351 
00352         if (!FullscreenOutput)
00353             Adapter = NULL;
00354     }
00355 
00356     if (!Adapter)
00357     {
00358         DXGIFactory->EnumAdapters(0, &Adapter.GetRawRef());
00359         UpdateMonitorOutputs();
00360     }
00361 
00362     int flags = 0;
00363 
00364 #if (OVR_D3D_VERSION == 10)
00365     hr = D3D10CreateDevice(Adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, flags, D3D1x_(SDK_VERSION),
00366                            &Device.GetRawRef());
00367     Context = Device;
00368     Context->AddRef();
00369 #else //11
00370     hr = D3D11CreateDevice(Adapter, Adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE,
00371                            NULL, flags, NULL, 0, D3D1x_(SDK_VERSION),
00372                            &Device.GetRawRef(), NULL, &Context.GetRawRef());
00373 #endif
00374     if (FAILED(hr))
00375         return;
00376 
00377     if (!RecreateSwapChain())
00378         return;
00379 
00380     if (Params.Fullscreen)
00381         SwapChain->SetFullscreenState(1, FullscreenOutput);
00382 
00383     CurRenderTarget = NULL;
00384     for(int i = 0; i < Shader_Count; i++)
00385     {
00386         UniformBuffers[i] = *CreateBuffer();
00387         MaxTextureSet[i] = 0;
00388     }
00389 
00390     ID3D10Blob* vsData = CompileShader("vs_4_0", DirectVertexShaderSrc);
00391     VertexShaders[VShader_MV] = *new VertexShader(this, vsData);
00392     for(int i = 1; i < VShader_Count; i++)
00393     {
00394         VertexShaders[i] = *new VertexShader(this, CompileShader("vs_4_0", VShaderSrcs[i]));
00395     }
00396 
00397     for(int i = 0; i < FShader_Count; i++)
00398     {
00399         PixelShaders[i] = *new PixelShader(this, CompileShader("ps_4_0", FShaderSrcs[i]));
00400     }
00401 
00402     SPInt bufferSize = vsData->GetBufferSize();
00403     const void* buffer = vsData->GetBufferPointer();
00404     ID3D1xInputLayout** objRef = &ModelVertexIL.GetRawRef();
00405 
00406     HRESULT validate = Device->CreateInputLayout(ModelVertexDesc, 5, buffer, bufferSize, objRef);
00407     OVR_UNUSED(validate);
00408 
00409     Ptr<ShaderSet> gouraudShaders = *new ShaderSet();
00410     gouraudShaders->SetShader(VertexShaders[VShader_MVP]);
00411     gouraudShaders->SetShader(PixelShaders[FShader_Gouraud]);
00412     DefaultFill = *new ShaderFill(gouraudShaders);
00413 
00414 #if (OVR_D3D_VERSION == 10)
00415     D3D1x_(BLEND_DESC) bm;
00416     memset(&bm, 0, sizeof(bm));
00417     bm.BlendEnable[0] = true;
00418     bm.BlendOp      = bm.BlendOpAlpha   = D3D1x_(BLEND_OP_ADD);
00419     bm.SrcBlend     = bm.SrcBlendAlpha  = D3D1x_(BLEND_SRC_ALPHA);
00420     bm.DestBlend    = bm.DestBlendAlpha = D3D1x_(BLEND_INV_SRC_ALPHA);
00421     bm.RenderTargetWriteMask[0]         = D3D1x_(COLOR_WRITE_ENABLE_ALL);
00422     Device->CreateBlendState(&bm, &BlendState.GetRawRef());
00423 #else
00424     D3D1x_(BLEND_DESC) bm;
00425     memset(&bm, 0, sizeof(bm));
00426     bm.RenderTarget[0].BlendEnable = true;
00427     bm.RenderTarget[0].BlendOp     = bm.RenderTarget[0].BlendOpAlpha    = D3D1x_(BLEND_OP_ADD);
00428     bm.RenderTarget[0].SrcBlend    = bm.RenderTarget[0].SrcBlendAlpha   = D3D1x_(BLEND_SRC_ALPHA);
00429     bm.RenderTarget[0].DestBlend   = bm.RenderTarget[0].DestBlendAlpha  = D3D1x_(BLEND_INV_SRC_ALPHA);
00430     bm.RenderTarget[0].RenderTargetWriteMask = D3D1x_(COLOR_WRITE_ENABLE_ALL);
00431     Device->CreateBlendState(&bm, &BlendState.GetRawRef());
00432 #endif
00433 
00434     D3D1x_(RASTERIZER_DESC) rs;
00435     memset(&rs, 0, sizeof(rs));
00436     rs.AntialiasedLineEnable = true;
00437     rs.CullMode = D3D1x_(CULL_BACK);
00438     // rs.CullMode = D3D1x_(CULL_NONE);
00439     rs.DepthClipEnable = true;
00440     rs.FillMode = D3D1x_(FILL_SOLID);
00441     Device->CreateRasterizerState(&rs, &Rasterizer.GetRawRef());
00442 
00443     QuadVertexBuffer = *CreateBuffer();
00444     const Render::Vertex QuadVertices[] =
00445     { Vertex(Vector3f(0, 1, 0)), Vertex(Vector3f(1, 1, 0)),
00446       Vertex(Vector3f(0, 0, 0)), Vertex(Vector3f(1, 0, 0)) };
00447     QuadVertexBuffer->Data(Buffer_Vertex, QuadVertices, sizeof(QuadVertices));
00448 
00449     SetDepthMode(0, 0);
00450 }
00451 
00452 RenderDevice::~RenderDevice()
00453 {
00454     if (SwapChain && Params.Fullscreen)
00455     {
00456         SwapChain->SetFullscreenState(false, NULL);
00457     }
00458 }
00459 
00460 
00461 // Implement static initializer function to create this class.
00462 Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd)
00463 {
00464     return new RenderDevice(rp, (HWND)oswnd);
00465 }
00466 
00467 
00468 // Fallback monitor enumeration in case newly plugged in monitor wasn't detected.
00469 // Added originally for the FactoryTest app.
00470 // New Outputs don't seem to be detected unless adapter is re-created, but that would also
00471 // require us to re-initialize D3D10 (recreating objects, etc). This bypasses that for "fake"
00472 // fullscreen modes.
00473 BOOL CALLBACK MonitorEnumFunc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
00474 {
00475     RenderDevice* renderer = (RenderDevice*)dwData;
00476 
00477     MONITORINFOEX monitor;
00478     monitor.cbSize = sizeof(monitor);
00479 
00480     if (::GetMonitorInfo(hMonitor, &monitor) && monitor.szDevice[0])
00481     {
00482         DISPLAY_DEVICE dispDev;
00483         memset(&dispDev, 0, sizeof(dispDev));
00484         dispDev.cb = sizeof(dispDev);
00485 
00486         if (::EnumDisplayDevices(monitor.szDevice, 0, &dispDev, 0))
00487         {
00488             if (strstr(String(dispDev.DeviceName).ToCStr(), renderer->GetParams().Display.MonitorName.ToCStr()))
00489             {
00490                 renderer->FSDesktopX = monitor.rcMonitor.left;
00491                 renderer->FSDesktopY = monitor.rcMonitor.top;
00492                 return FALSE;
00493             }
00494         }
00495     }
00496 
00497     return TRUE;
00498 }
00499 
00500 
00501 void RenderDevice::UpdateMonitorOutputs(bool needRecreate)
00502 {
00503     HRESULT hr;
00504 
00505     if (needRecreate)
00506     {
00507         // need to recreate DXGIFactory and Adapter in order 
00508         // to get latest info about monitors.
00509         if (SwapChain)
00510         {
00511             SwapChain->SetFullscreenState(FALSE, NULL);
00512             SwapChain->Release();
00513             SwapChain = NULL;
00514         }
00515 
00516         DXGIFactory = NULL;
00517         Adapter = NULL;
00518         hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&DXGIFactory.GetRawRef()));
00519         if (FAILED(hr))    
00520             return;
00521         DXGIFactory->EnumAdapters(0, &Adapter.GetRawRef());
00522     }
00523 
00524     bool deviceNameFound = false;
00525 
00526     for(UINT OutputIndex = 0; ; OutputIndex++)
00527     {
00528         Ptr<IDXGIOutput> Output;
00529         hr = Adapter->EnumOutputs(OutputIndex, &Output.GetRawRef());
00530         if (hr == DXGI_ERROR_NOT_FOUND)
00531         {
00532             break;
00533         }
00534 
00535         DXGI_OUTPUT_DESC OutDesc;
00536         Output->GetDesc(&OutDesc);
00537 
00538         MONITORINFOEX monitor;
00539         monitor.cbSize = sizeof(monitor);
00540         if (::GetMonitorInfo(OutDesc.Monitor, &monitor) && monitor.szDevice[0])
00541         {
00542             DISPLAY_DEVICE dispDev;
00543             memset(&dispDev, 0, sizeof(dispDev));
00544             dispDev.cb = sizeof(dispDev);
00545 
00546             if (::EnumDisplayDevices(monitor.szDevice, 0, &dispDev, 0))
00547             {
00548                 if (strstr(String(dispDev.DeviceName).ToCStr(), Params.Display.MonitorName.ToCStr()))
00549                 {
00550                     deviceNameFound = true;
00551                     FullscreenOutput = Output;
00552                     FSDesktopX = monitor.rcMonitor.left;
00553                     FSDesktopY = monitor.rcMonitor.top;
00554                     break;
00555                 }
00556             }
00557         }
00558     }
00559 
00560     if (!deviceNameFound && !Params.Display.MonitorName.IsEmpty())
00561     {
00562         EnumDisplayMonitors(0, 0, MonitorEnumFunc, (LPARAM)this);
00563     }
00564 }
00565 
00566 bool RenderDevice::RecreateSwapChain()
00567 {
00568     DXGI_SWAP_CHAIN_DESC scDesc;
00569     memset(&scDesc, 0, sizeof(scDesc));
00570     scDesc.BufferCount = 1;
00571     scDesc.BufferDesc.Width = WindowWidth;
00572     scDesc.BufferDesc.Height = WindowHeight;
00573     scDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
00574     scDesc.BufferDesc.RefreshRate.Numerator = 60;
00575     scDesc.BufferDesc.RefreshRate.Denominator = 1;
00576     scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
00577     scDesc.OutputWindow = Window;
00578     scDesc.SampleDesc.Count = Params.Multisample;
00579     scDesc.SampleDesc.Quality = 0;
00580     scDesc.Windowed = Params.Fullscreen != Display_Fullscreen;
00581     scDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
00582 
00583         if (SwapChain)
00584         {
00585                 SwapChain->SetFullscreenState(FALSE, NULL);
00586                 SwapChain->Release();
00587                 SwapChain = NULL;
00588         }
00589 
00590     Ptr<IDXGISwapChain> newSC;
00591     if (FAILED(DXGIFactory->CreateSwapChain(Device, &scDesc, &newSC.GetRawRef())))
00592         return false;    
00593     SwapChain = newSC;
00594 
00595     BackBuffer = NULL;
00596     BackBufferRT = NULL;
00597     HRESULT hr = SwapChain->GetBuffer(0, __uuidof(ID3D1xTexture2D), (void**)&BackBuffer.GetRawRef());
00598     if (FAILED(hr))
00599         return false;
00600 
00601     hr = Device->CreateRenderTargetView(BackBuffer, NULL, &BackBufferRT.GetRawRef());
00602     if (FAILED(hr))
00603         return false;
00604 
00605     Texture* depthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
00606     CurDepthBuffer = depthBuffer;
00607     if (CurRenderTarget == NULL)
00608     {
00609         Context->OMSetRenderTargets(1, &BackBufferRT.GetRawRef(), depthBuffer->TexDsv);
00610     }
00611     return true;
00612 }
00613 
00614 bool RenderDevice::SetParams(const RendererParams& newParams)
00615 {
00616     String oldMonitor = Params.Display.MonitorName;
00617 
00618     Params = newParams;
00619     if (newParams.Display.MonitorName != oldMonitor)
00620     {
00621         UpdateMonitorOutputs(true);
00622     }
00623 
00624     // Cause this to be recreated with the new multisample mode.
00625     pSceneColorTex = NULL;
00626     return RecreateSwapChain();
00627 }
00628 
00629 void RenderDevice::SetWindowSize(int w, int h)
00630 {
00631     if (w == WindowWidth && h == WindowHeight)
00632         return;
00633 
00634     WindowWidth  = w;
00635     WindowHeight = h;
00636     Context->OMSetRenderTargets(0, NULL, NULL);
00637     BackBuffer   = NULL;
00638     BackBufferRT = NULL;
00639     if (SwapChain)
00640     {
00641         SwapChain->ResizeBuffers(2, WindowWidth, WindowHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
00642         SwapChain->GetBuffer(0, __uuidof(ID3D1xTexture2D), (void**)&BackBuffer.GetRawRef());
00643     }
00644     Device->CreateRenderTargetView(BackBuffer, NULL, &BackBufferRT.GetRawRef());
00645 }
00646 
00647 bool RenderDevice::SetFullscreen(DisplayMode fullscreen)
00648 {
00649     if (fullscreen == Params.Fullscreen)
00650     {
00651         return true;
00652     }
00653 
00654     if (Params.Fullscreen == Display_FakeFullscreen)
00655     {
00656         SetWindowLong(Window, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS);
00657         SetWindowPos(Window, NULL, PreFullscreenX, PreFullscreenY,
00658                      PreFullscreenW, PreFullscreenH, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
00659     }
00660 
00661     if (fullscreen == Display_FakeFullscreen)
00662     {
00663         // Get WINDOWPLACEMENT before changing style to get OVERLAPPED coordinates,
00664         // which we will restore.
00665         WINDOWPLACEMENT wp;
00666         wp.length = sizeof(wp);
00667         GetWindowPlacement(Window, &wp);
00668         PreFullscreenW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
00669         PreFullscreenH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
00670         PreFullscreenX = wp.rcNormalPosition.left;
00671         PreFullscreenY = wp.rcNormalPosition.top;
00672         // Warning: SetWindowLong sends message computed based on old size (incorrect).
00673         // A proper work-around would be to mask that message out during window frame change in Platform.
00674         SetWindowLong(Window, GWL_STYLE, WS_OVERLAPPED | WS_VISIBLE | WS_CLIPSIBLINGS);
00675         SetWindowPos(Window, NULL, FSDesktopX, FSDesktopY, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED);
00676 
00677         // Relocate cursor into the window to avoid losing focus on first click.
00678         POINT oldCursor;
00679         if (GetCursorPos(&oldCursor) &&
00680                 ((oldCursor.x < FSDesktopX) || (oldCursor.x > (FSDesktopX + PreFullscreenW)) ||
00681                  (oldCursor.y < FSDesktopY) || (oldCursor.x > (FSDesktopY + PreFullscreenH))))
00682         {
00683             // TBD: FullScreen window logic should really be in platform; it causes world rotation
00684             // in relative mouse mode.
00685             ::SetCursorPos(FSDesktopX, FSDesktopY);
00686         }
00687     }
00688     else
00689     {
00690         HRESULT hr = SwapChain->SetFullscreenState(fullscreen, fullscreen ? FullscreenOutput : NULL);
00691         if (FAILED(hr))
00692         {
00693             return false;
00694         }
00695     }
00696 
00697     Params.Fullscreen = fullscreen;
00698     return true;
00699 }
00700 
00701 void RenderDevice::SetMultipleViewports(int n, const Viewport* vps)
00702 {
00703     if (n > 2)
00704     {
00705         n = 2;
00706     }
00707     for(int i = 0; i < n; i++)
00708     {
00709 #if (OVR_D3D_VERSION == 10)
00710         Viewports[i].Width = vps[i].w;
00711         Viewports[i].Height = vps[i].h;
00712         Viewports[i].MinDepth = 0;
00713         Viewports[i].MaxDepth = 1;
00714         Viewports[i].TopLeftX = vps[i].x;
00715         Viewports[i].TopLeftY = vps[i].y;
00716 #else
00717         Viewports[i].Width = (float)vps[i].w;
00718         Viewports[i].Height = (float)vps[i].h;
00719         Viewports[i].MinDepth = 0;
00720         Viewports[i].MaxDepth = 1;
00721         Viewports[i].TopLeftX = (float)vps[i].x;
00722         Viewports[i].TopLeftY = (float)vps[i].y;
00723 #endif
00724     }
00725     NumViewports = n;
00726     Context->RSSetViewports(n, Viewports);
00727 }
00728 
00729 static int GetDepthStateIndex(bool enable, bool write, RenderDevice::CompareFunc func)
00730 {
00731     if (!enable)
00732     {
00733         return 0;
00734     }
00735     return 1 + int(func) * 2 + write;
00736 }
00737 
00738 void RenderDevice::SetDepthMode(bool enable, bool write, CompareFunc func)
00739 {
00740     int index = GetDepthStateIndex(enable, write, func);
00741     if (DepthStates[index])
00742     {
00743         CurDepthState = DepthStates[index];
00744         Context->OMSetDepthStencilState(DepthStates[index], 0);
00745         return;
00746     }
00747 
00748     D3D1x_(DEPTH_STENCIL_DESC) dss;
00749     memset(&dss, 0, sizeof(dss));
00750     dss.DepthEnable = enable;
00751     switch(func)
00752     {
00753     case Compare_Always:  dss.DepthFunc = D3D1x_(COMPARISON_ALWAYS);  break;
00754     case Compare_Less:    dss.DepthFunc = D3D1x_(COMPARISON_LESS);    break;
00755     case Compare_Greater: dss.DepthFunc = D3D1x_(COMPARISON_GREATER); break;
00756     default:
00757         assert(0);
00758     }
00759     dss.DepthWriteMask = write ? D3D1x_(DEPTH_WRITE_MASK_ALL) : D3D1x_(DEPTH_WRITE_MASK_ZERO);
00760     Device->CreateDepthStencilState(&dss, &DepthStates[index].GetRawRef());
00761     Context->OMSetDepthStencilState(DepthStates[index], 0);
00762     CurDepthState = DepthStates[index];
00763 }
00764 
00765 Texture* RenderDevice::GetDepthBuffer(int w, int h, int ms)
00766 {
00767     for(unsigned i = 0; i < DepthBuffers.GetSize(); i++)
00768     {
00769         if (w == DepthBuffers[i]->Width && h == DepthBuffers[i]->Height &&
00770             ms == DepthBuffers[i]->Samples)
00771             return DepthBuffers[i];
00772     }
00773 
00774     Ptr<Texture> newDepth = *CreateTexture(Texture_Depth | Texture_RenderTarget | ms, w, h, NULL);
00775     if (newDepth == NULL)
00776     {
00777         OVR_DEBUG_LOG(("Failed to get depth buffer."));
00778         return NULL;
00779     }
00780 
00781     DepthBuffers.PushBack(newDepth);
00782     return newDepth.GetPtr();
00783 }
00784 
00785 void RenderDevice::Clear(float r, float g, float b, float a, float depth)
00786 {
00787     const float color[] = {r, g, b, a};
00788 
00789         // save state that is affected by clearing this way
00790     ID3D1xDepthStencilState* oldDepthState = CurDepthState;
00791         StandardUniformData      clearUniforms;
00792 
00793     SetDepthMode(true, true, Compare_Always);
00794                 
00795     Context->IASetInputLayout(ModelVertexIL);
00796 #if (OVR_D3D_VERSION == 10)
00797     Context->GSSetShader(NULL);
00798 #else
00799     Context->GSSetShader(NULL, NULL, 0);
00800 #endif
00801     //Shader<Shader_Geometry,ID3D1xGeometryShader> NullGS(this,(ID3D1xGeometryShader*)NULL);
00802     //NullGS.Set(Prim_TriangleStrip);
00803 
00804     ID3D1xShaderResourceView* sv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
00805     if (MaxTextureSet[Shader_Fragment])
00806     {
00807         Context->PSSetShaderResources(0, MaxTextureSet[Shader_Fragment], sv);
00808     }
00809 
00810     ID3D1xBuffer* vertexBuffer = QuadVertexBuffer->GetBuffer();
00811     UINT vertexStride = sizeof(Vertex);
00812     UINT vertexOffset = 0;
00813     Context->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);
00814 
00815     clearUniforms.View = Matrix4f(2, 0, 0, 0,
00816                                     0, 2, 0, 0,
00817                                     0, 0, 0, 0,
00818                                     -1, -1, depth, 1);
00819     UniformBuffers[Shader_Vertex]->Data(Buffer_Uniform, &clearUniforms, sizeof(clearUniforms));
00820 
00821     ID3D1xBuffer* vertexConstants = UniformBuffers[Shader_Vertex]->GetBuffer();
00822     Context->VSSetConstantBuffers(0, 1, &vertexConstants);
00823     Context->IASetPrimitiveTopology(D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP));
00824     VertexShaders[VShader_MV]->Set(Prim_TriangleStrip);
00825     PixelShaders[FShader_Solid]->Set(Prim_TriangleStrip);
00826 
00827     UniformBuffers[Shader_Pixel]->Data(Buffer_Uniform, color, sizeof(color));
00828     PixelShaders[FShader_Solid]->SetUniformBuffer(UniformBuffers[Shader_Pixel]);
00829 
00830     if (NumViewports > 1)
00831     {
00832         for(int i = 0; i < NumViewports; i++)
00833         {
00834             Context->RSSetViewports(1, &Viewports[i]);
00835             Context->OMSetBlendState(NULL, NULL, 0xffffffff);
00836             Context->Draw(4, 0);
00837         }
00838         Context->RSSetViewports(NumViewports, Viewports);
00839     }
00840     else
00841     {
00842                 Context->OMSetBlendState(NULL, NULL, 0xffffffff);
00843                 Context->Draw(4, 0);
00844     }
00845 
00846     // reset
00847     CurDepthState = oldDepthState;
00848     Context->OMSetDepthStencilState(CurDepthState, 0);
00849 }
00850 
00851 // Buffers
00852 
00853 Buffer* RenderDevice::CreateBuffer()
00854 {
00855     return new Buffer(this);
00856 }
00857 
00858 Buffer::~Buffer()
00859 {
00860 }
00861 
00862 bool   Buffer::Data(int use, const void *buffer, size_t size)
00863 {
00864     if (D3DBuffer && Size >= size)
00865     {
00866         if (Dynamic)
00867         {
00868             if (!buffer)
00869                 return true;
00870 
00871             void* v = Map(0, size, Map_Discard);
00872             if (v)
00873             {
00874                 memcpy(v, buffer, size);
00875                 Unmap(v);
00876                 return true;
00877             }
00878         }
00879         else
00880         {
00881             Ren->Context->UpdateSubresource(D3DBuffer, 0, NULL, buffer, 0, 0);
00882             return true;
00883         }
00884     }
00885     if (D3DBuffer)
00886     {
00887         D3DBuffer = NULL;
00888         Size = 0;
00889         Use = 0;
00890         Dynamic = 0;
00891     }
00892 
00893     D3D1x_(BUFFER_DESC) desc;
00894     memset(&desc, 0, sizeof(desc));
00895     if (use & Buffer_ReadOnly)
00896     {
00897         desc.Usage = D3D1x_(USAGE_IMMUTABLE);
00898         desc.CPUAccessFlags = 0;
00899     }
00900     else
00901     {
00902         desc.Usage = D3D1x_(USAGE_DYNAMIC);
00903         desc.CPUAccessFlags = D3D1x_(CPU_ACCESS_WRITE);
00904         Dynamic = 1;
00905     }
00906 
00907     switch(use & Buffer_TypeMask)
00908     {
00909     case Buffer_Vertex:  desc.BindFlags = D3D1x_(BIND_VERTEX_BUFFER); break;
00910     case Buffer_Index:   desc.BindFlags = D3D1x_(BIND_INDEX_BUFFER);  break;
00911     case Buffer_Uniform:
00912         desc.BindFlags = D3D1x_(BIND_CONSTANT_BUFFER);
00913         size += ((size + 15) & ~15) - size;
00914         break;
00915     case Buffer_Feedback:
00916         desc.BindFlags = D3D1x_(BIND_STREAM_OUTPUT);
00917         desc.Usage     = D3D1x_(USAGE_DEFAULT);
00918         desc.CPUAccessFlags = 0;
00919         size += ((size + 15) & ~15) - size;
00920         break;
00921     }
00922 
00923     desc.ByteWidth = (unsigned)size;
00924 
00925     D3D1x_(SUBRESOURCE_DATA) sr;
00926     sr.pSysMem = buffer;
00927     sr.SysMemPitch = 0;
00928     sr.SysMemSlicePitch = 0;
00929 
00930     HRESULT hr = Ren->Device->CreateBuffer(&desc, buffer ? &sr : NULL, &D3DBuffer.GetRawRef());
00931     if (SUCCEEDED(hr))
00932     {
00933         Use = use;
00934         Size = desc.ByteWidth;
00935         return 1;
00936     }
00937     return 0;
00938 }
00939 
00940 void*  Buffer::Map(size_t start, size_t size, int flags)
00941 {
00942     OVR_UNUSED(size);
00943 
00944     D3D1x_(MAP) mapFlags = D3D1x_(MAP_WRITE);
00945     if (flags & Map_Discard)    
00946         mapFlags = D3D1x_(MAP_WRITE_DISCARD);    
00947     if (flags & Map_Unsynchronized)    
00948         mapFlags = D3D1x_(MAP_WRITE_NO_OVERWRITE);    
00949 
00950 #if (OVR_D3D_VERSION == 10)
00951     void* map;
00952     if (SUCCEEDED(D3DBuffer->Map(mapFlags, 0, &map)))    
00953         return ((char*)map) + start;    
00954     else    
00955         return NULL;
00956 #else
00957     D3D1x_(MAPPED_SUBRESOURCE) map;
00958     if (SUCCEEDED(Ren->Context->Map(D3DBuffer, 0, mapFlags, 0, &map)))    
00959         return ((char*)map.pData) + start;    
00960     else    
00961         return NULL;    
00962 #endif
00963 }
00964 
00965 bool   Buffer::Unmap(void *m)
00966 {
00967     OVR_UNUSED(m);
00968 
00969 #if (OVR_D3D_VERSION == 10)
00970     D3DBuffer->Unmap();
00971 #else
00972     Ren->Context->Unmap(D3DBuffer, 0);
00973 #endif
00974     return true;
00975 }
00976 
00977 
00978 // Shaders
00979 
00980 #if (OVR_D3D_VERSION == 10)
00981 template<> bool Shader<Render::Shader_Vertex, ID3D10VertexShader>::Load(void* shader, size_t size)
00982 {
00983     return SUCCEEDED(Ren->Device->CreateVertexShader(shader, size, &D3DShader));
00984 }
00985 template<> bool Shader<Render::Shader_Pixel, ID3D10PixelShader>::Load(void* shader, size_t size)
00986 {
00987     return SUCCEEDED(Ren->Device->CreatePixelShader(shader, size, &D3DShader));
00988 }
00989 template<> bool Shader<Render::Shader_Geometry, ID3D10GeometryShader>::Load(void* shader, size_t size)
00990 {
00991     return SUCCEEDED(Ren->Device->CreateGeometryShader(shader, size, &D3DShader));
00992 }
00993 
00994 template<> void Shader<Render::Shader_Vertex, ID3D10VertexShader>::Set(PrimitiveType) const
00995 {
00996     Ren->Context->VSSetShader(D3DShader);
00997 }
00998 template<> void Shader<Render::Shader_Pixel, ID3D10PixelShader>::Set(PrimitiveType) const
00999 {
01000     Ren->Context->PSSetShader(D3DShader);
01001 }
01002 template<> void Shader<Render::Shader_Geometry, ID3D10GeometryShader>::Set(PrimitiveType) const
01003 {
01004     Ren->Context->GSSetShader(D3DShader);
01005 }
01006 
01007 #else // 11
01008 template<> bool Shader<Render::Shader_Vertex, ID3D11VertexShader>::Load(void* shader, size_t size)
01009 {
01010     return SUCCEEDED(Ren->Device->CreateVertexShader(shader, size, NULL, &D3DShader));
01011 }
01012 template<> bool Shader<Render::Shader_Pixel, ID3D11PixelShader>::Load(void* shader, size_t size)
01013 {
01014     return SUCCEEDED(Ren->Device->CreatePixelShader(shader, size, NULL, &D3DShader));
01015 }
01016 template<> bool Shader<Render::Shader_Geometry, ID3D11GeometryShader>::Load(void* shader, size_t size)
01017 {
01018     return SUCCEEDED(Ren->Device->CreateGeometryShader(shader, size, NULL, &D3DShader));
01019 }
01020 
01021 template<> void Shader<Render::Shader_Vertex, ID3D11VertexShader>::Set(PrimitiveType) const
01022 {
01023     Ren->Context->VSSetShader(D3DShader, NULL, 0);
01024 }
01025 template<> void Shader<Render::Shader_Pixel, ID3D11PixelShader>::Set(PrimitiveType) const
01026 {
01027     Ren->Context->PSSetShader(D3DShader, NULL, 0);
01028 }
01029 template<> void Shader<Render::Shader_Geometry, ID3D11GeometryShader>::Set(PrimitiveType) const
01030 {
01031     Ren->Context->GSSetShader(D3DShader, NULL, 0);
01032 }
01033 #endif
01034 
01035 template<> void Shader<Render::Shader_Vertex, ID3D1xVertexShader>::SetUniformBuffer(Render::Buffer* buffer, int i)
01036 {
01037     Ren->Context->VSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef());
01038 }
01039 template<> void Shader<Render::Shader_Pixel, ID3D1xPixelShader>::SetUniformBuffer(Render::Buffer* buffer, int i)
01040 {
01041     Ren->Context->PSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef());
01042 }
01043 template<> void Shader<Render::Shader_Geometry, ID3D1xGeometryShader>::SetUniformBuffer(Render::Buffer* buffer, int i)
01044 {
01045     Ren->Context->GSSetConstantBuffers(i, 1, &((Buffer*)buffer)->D3DBuffer.GetRawRef());
01046 }
01047 
01048 ID3D10Blob* RenderDevice::CompileShader(const char* profile, const char* src, const char* mainName)
01049 {
01050     ID3D10Blob* shader;
01051     ID3D10Blob* errors;
01052     HRESULT hr = D3DCompile(src, strlen(src), NULL, NULL, NULL, mainName, profile,
01053                             0, 0, &shader, &errors);
01054     if (FAILED(hr))
01055     {
01056         OVR_DEBUG_LOG(("Compiling D3D shader for %s failed\n%s\n\n%s",
01057                        profile, src, errors->GetBufferPointer()));
01058         OutputDebugStringA((char*)errors->GetBufferPointer());
01059         return NULL;
01060     }
01061     if (errors)
01062     {
01063         errors->Release();
01064     }
01065     return shader;
01066 }
01067 
01068 
01069 ShaderBase::ShaderBase(RenderDevice* r, ShaderStage stage)
01070     : Render::Shader(stage), Ren(r), UniformData(0)
01071 {
01072 }
01073 ShaderBase::~ShaderBase()
01074 {
01075     if (UniformData)
01076     {
01077         OVR_FREE(UniformData);
01078     }
01079 }
01080 
01081 bool ShaderBase::SetUniform(const char* name, int n, const float* v)
01082 {
01083     for(unsigned i = 0; i < UniformInfo.GetSize(); i++)
01084         if (!strcmp(UniformInfo[i].Name.ToCStr(), name))
01085         {
01086             memcpy(UniformData + UniformInfo[i].Offset, v, n * sizeof(float));
01087             return 1;
01088         }
01089     return 0;
01090 }
01091 
01092 void ShaderBase::InitUniforms(ID3D10Blob* s)
01093 {
01094     ID3D10ShaderReflection* ref = NULL;
01095     D3D10ReflectShader(s->GetBufferPointer(), s->GetBufferSize(), &ref);
01096     ID3D10ShaderReflectionConstantBuffer* buf = ref->GetConstantBufferByIndex(0);
01097     D3D10_SHADER_BUFFER_DESC bufd;
01098     if (FAILED(buf->GetDesc(&bufd)))
01099     {
01100         UniformsSize = 0;
01101         if (UniformData)
01102         {
01103             OVR_FREE(UniformData);
01104             UniformData = 0;
01105         }
01106         return;
01107     }
01108 
01109     for(unsigned i = 0; i < bufd.Variables; i++)
01110     {
01111         ID3D10ShaderReflectionVariable* var = buf->GetVariableByIndex(i);
01112         if (var)
01113         {
01114             D3D10_SHADER_VARIABLE_DESC vd;
01115             if (SUCCEEDED(var->GetDesc(&vd)))
01116             {
01117                 Uniform u;
01118                 u.Name = vd.Name;
01119                 u.Offset = vd.StartOffset;
01120                 u.Size = vd.Size;
01121                 UniformInfo.PushBack(u);
01122             }
01123         }
01124     }
01125 
01126     UniformsSize = bufd.Size;
01127     UniformData = (unsigned char*)OVR_ALLOC(bufd.Size);
01128 }
01129 
01130 void ShaderBase::UpdateBuffer(Buffer* buf)
01131 {
01132     if (UniformsSize)
01133     {
01134         buf->Data(Buffer_Uniform, UniformData, UniformsSize);
01135     }
01136 }
01137 
01138 void RenderDevice::SetCommonUniformBuffer(int i, Render::Buffer* buffer)
01139 {
01140     CommonUniforms[i] = (Buffer*)buffer;
01141 
01142     Context->PSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef());
01143     Context->VSSetConstantBuffers(1, 1, &CommonUniforms[1]->D3DBuffer.GetRawRef());
01144 }
01145 
01146 Render::Shader *RenderDevice::LoadBuiltinShader(ShaderStage stage, int shader)
01147 {
01148     switch(stage)
01149     {
01150     case Shader_Vertex:
01151         return VertexShaders[shader];
01152     case Shader_Pixel:
01153         return PixelShaders[shader];
01154     default:
01155         return NULL;
01156     }
01157 }
01158 
01159 ShaderBase* RenderDevice::CreateStereoShader(PrimitiveType prim, Render::Shader* vs)
01160 {
01161     if (pStereoShaders[prim])
01162     {
01163         return pStereoShaders[prim];
01164     }
01165 
01166     OVR_UNUSED(vs);
01167     const char* varyings =
01168         "   float4 Position : SV_Position;\n"
01169         "   float4 Color    : COLOR0;\n"
01170         "   float2 TexCoord : TEXCOORD0;\n"
01171         "   float3 Normal   : NORMAL;\n";
01172     const char* copyVaryings =
01173         "       o.Color = iv[i].Color;\n"
01174         "       o.Normal = iv[i].Normal;\n"
01175         "       o.TexCoord = iv[i].TexCoord;\n";
01176 
01177     StringBuffer src =
01178         "float4x4 Proj[2]     : register(c0);\n"
01179         "float4   ViewOffset  : register(c8);\n"
01180         "struct Varyings\n"
01181         "{\n";
01182     src += varyings;
01183     src += "};\n"
01184            "struct OutVaryings\n"
01185            "{\n";
01186     src += varyings;
01187     src +=
01188         "   float3 VPos     : TEXCOORD4;\n"
01189         "   uint   Viewport : SV_ViewportArrayIndex;\n"
01190         "};\n";
01191 
01192     if (prim == Prim_Lines)
01193         src +=
01194             "[maxvertexcount(4)]\n"
01195             "void main(line Varyings iv[2], inout LineStream<OutVaryings> v)\n";
01196     else
01197         src +=
01198             "[maxvertexcount(6)]\n"
01199             "void main(triangle Varyings iv[3], inout TriangleStream<OutVaryings> v)\n";
01200 
01201     char ivsize[6];
01202     OVR_sprintf(ivsize, 6, "%d", (prim == Prim_Lines) ? 2 : 3);
01203 
01204     src +=
01205         "{\n"
01206         "   OutVaryings o;\n"
01207         "   for (uint i = 0; i < ";
01208     src += ivsize;
01209     src += "; i++)\n"
01210            "   {\n"
01211            "       o.Position = mul(Proj[0], iv[i].Position - ViewOffset);\n"
01212            "       o.VPos = iv[i].Position;\n"
01213            "       o.Viewport = 0;\n";
01214     src += copyVaryings;
01215     src +=
01216         "       v.Append(o);\n"
01217         "   }\n"
01218         "   v.RestartStrip();\n"
01219         "   for (uint i = 0; i < ";
01220     src += ivsize;
01221     src += "; i++)\n"
01222            "   {\n"
01223            "       o.Position = mul(Proj[1], iv[i].Position + ViewOffset);\n"
01224            "       o.VPos = iv[i].Position;\n"
01225            "       o.Viewport = 1;\n";
01226     src += copyVaryings;
01227     src +=
01228         "       v.Append(o);\n"
01229         "   }\n"
01230         "   v.RestartStrip();\n"
01231         "}\n";
01232 
01233     pStereoShaders[prim] = *new GeomShader(this, CompileShader("gs_4_0", src.ToCStr()));
01234     return pStereoShaders[prim];
01235 }
01236 
01237 Fill* RenderDevice::CreateSimpleFill(int flags)
01238 {
01239     OVR_UNUSED(flags);
01240     return DefaultFill;
01241 }
01242 
01243 // Textures
01244 
01245 ID3D1xSamplerState* RenderDevice::GetSamplerState(int sm)
01246 {
01247     if (SamplerStates[sm])    
01248         return SamplerStates[sm];
01249 
01250     D3D1x_(SAMPLER_DESC) ss;
01251     memset(&ss, 0, sizeof(ss));
01252     if (sm & Sample_Clamp)    
01253         ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_CLAMP);    
01254     else if (sm & Sample_ClampBorder)    
01255         ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_BORDER);    
01256     else    
01257         ss.AddressU = ss.AddressV = ss.AddressW = D3D1x_(TEXTURE_ADDRESS_WRAP);
01258     
01259     if (sm & Sample_Nearest)
01260     {
01261         ss.Filter = D3D1x_(FILTER_MIN_MAG_MIP_POINT);
01262     }
01263     else if (sm & Sample_Anisotropic)
01264     {
01265         ss.Filter = D3D1x_(FILTER_ANISOTROPIC);
01266         ss.MaxAnisotropy = 8;
01267     }
01268     else
01269     {
01270         ss.Filter = D3D1x_(FILTER_MIN_MAG_MIP_LINEAR);
01271     }
01272     ss.MaxLOD = 15;
01273     Device->CreateSamplerState(&ss, &SamplerStates[sm].GetRawRef());
01274     return SamplerStates[sm];
01275 }
01276 
01277 Texture::Texture(RenderDevice* ren, int fmt, int w, int h) : Ren(ren), Tex(NULL), TexSv(NULL), TexRtv(NULL), TexDsv(NULL), Width(w), Height(h)
01278 {
01279     OVR_UNUSED(fmt);
01280     Sampler = Ren->GetSamplerState(0);
01281 }
01282 
01283 Texture::~Texture()
01284 {
01285 }
01286 
01287 void Texture::Set(int slot, Render::ShaderStage stage) const
01288 {
01289     Ren->SetTexture(stage, slot, this);
01290 }
01291 
01292 void Texture::SetSampleMode(int sm)
01293 {
01294     Sampler = Ren->GetSamplerState(sm);
01295 }
01296 
01297 void RenderDevice::SetTexture(Render::ShaderStage stage, int slot, const Texture* t)
01298 {
01299     if (MaxTextureSet[stage] <= slot)
01300         MaxTextureSet[stage] = slot + 1;    
01301 
01302     ID3D1xShaderResourceView* sv = t ? t->TexSv : NULL;
01303     switch(stage)
01304     {
01305     case Shader_Fragment:
01306         Context->PSSetShaderResources(slot, 1, &sv);
01307         if (t)
01308         {
01309             Context->PSSetSamplers(slot, 1, &t->Sampler.GetRawRef());
01310         }
01311         break;
01312 
01313     case Shader_Vertex:
01314         Context->VSSetShaderResources(slot, 1, &sv);
01315         break;
01316     }
01317 }
01318 
01319 void RenderDevice::GenerateSubresourceData(
01320     unsigned imageWidth, unsigned imageHeight, int format, unsigned imageDimUpperLimit,
01321     const void* rawBytes, D3D1x_(SUBRESOURCE_DATA)* subresData,
01322     unsigned& largestMipWidth, unsigned& largestMipHeight, unsigned& byteSize, unsigned& effectiveMipCount)
01323 {
01324     largestMipWidth  = 0;
01325     largestMipHeight = 0;
01326 
01327     unsigned sliceLen   = 0;
01328     unsigned rowLen     = 0;
01329     unsigned numRows    = 0;
01330     const byte* mipBytes = static_cast<const byte*>(rawBytes);
01331 
01332     unsigned index        = 0;
01333     unsigned subresWidth  = imageWidth;
01334     unsigned subresHeight = imageHeight;
01335     unsigned numMips      = effectiveMipCount;
01336 
01337     for(unsigned i = 0; i < numMips; i++)
01338     {
01339         unsigned bytesPerBlock = 0;
01340         if (format == DXGI_FORMAT_BC1_UNORM)
01341         {
01342             bytesPerBlock = 8;
01343         }
01344         else if (format == DXGI_FORMAT_BC3_UNORM)
01345         {
01346             bytesPerBlock = 16;
01347         }
01348 
01349         unsigned blockWidth = 0;
01350         blockWidth = (subresWidth + 3) / 4;
01351         if (blockWidth < 1)
01352         {
01353             blockWidth = 1;
01354         }
01355 
01356         unsigned blockHeight = 0;
01357         blockHeight = (subresHeight + 3) / 4;
01358         if (blockHeight < 1)
01359         {
01360             blockHeight = 1;
01361         }
01362 
01363         rowLen = blockWidth * bytesPerBlock;
01364         numRows = blockHeight;
01365         sliceLen = rowLen * numRows;
01366 
01367         if (imageDimUpperLimit == 0 || (effectiveMipCount == 1) ||
01368             (subresWidth <= imageDimUpperLimit && subresHeight <= imageDimUpperLimit))
01369         {
01370             if(!largestMipWidth)
01371             {
01372                 largestMipWidth = subresWidth;
01373                 largestMipHeight = subresHeight;
01374             }
01375 
01376             subresData[index].pSysMem = (const void*)mipBytes;
01377             subresData[index].SysMemPitch = static_cast<UINT>(rowLen);
01378             subresData[index].SysMemSlicePitch = static_cast<UINT>(sliceLen);
01379             byteSize += sliceLen;
01380             ++index;
01381         }
01382         else
01383         {
01384             effectiveMipCount--;
01385         }
01386 
01387         mipBytes += sliceLen;
01388 
01389         subresWidth = subresWidth >> 1;
01390         subresHeight = subresHeight >> 1;
01391         if (subresWidth <= 0)
01392         {
01393             subresWidth = 1;
01394         }
01395         if (subresHeight <= 0)
01396         {
01397             subresHeight = 1;
01398         }
01399     }
01400 }
01401 
01402 #define _256Megabytes 268435456
01403 #define _512Megabytes 536870912
01404 
01405 Texture* RenderDevice::CreateTexture(int format, int width, int height, const void* data, int mipcount)
01406 {
01407     UPInt gpuMemorySize = 0;
01408     {
01409         IDXGIDevice* pDXGIDevice;
01410         Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
01411         IDXGIAdapter * pDXGIAdapter;
01412         pDXGIDevice->GetAdapter(&pDXGIAdapter);
01413         DXGI_ADAPTER_DESC adapterDesc;
01414         pDXGIAdapter->GetDesc(&adapterDesc);
01415         gpuMemorySize = adapterDesc.DedicatedVideoMemory;
01416         pDXGIAdapter->Release();
01417         pDXGIDevice->Release();
01418     }
01419  
01420     unsigned imageDimUpperLimit = 0;
01421     if (gpuMemorySize <= _256Megabytes)
01422     {
01423         imageDimUpperLimit = 512;
01424     }    
01425     else if (gpuMemorySize <= _512Megabytes)
01426     {
01427         imageDimUpperLimit = 1024;
01428     } 
01429 
01430     if (format == Texture_DXT1 || format == Texture_DXT5)
01431     {
01432         int      convertedFormat   = (format == Texture_DXT1) ? DXGI_FORMAT_BC1_UNORM : DXGI_FORMAT_BC3_UNORM;
01433         unsigned largestMipWidth   = 0;
01434         unsigned largestMipHeight  = 0;
01435         unsigned effectiveMipCount = mipcount;
01436         unsigned textureSize       = 0;
01437 
01438 #ifdef OVR_DEFINE_NEW
01439 #undef new
01440 #endif
01441         
01442         D3D1x_(SUBRESOURCE_DATA)* subresData = (D3D1x_(SUBRESOURCE_DATA)*)
01443                                                 OVR_ALLOC(sizeof(D3D1x_(SUBRESOURCE_DATA)) * mipcount);
01444         GenerateSubresourceData(width, height, convertedFormat, imageDimUpperLimit, data, subresData, largestMipWidth,
01445                                 largestMipHeight, textureSize, effectiveMipCount);
01446         TotalTextureMemoryUsage += textureSize;
01447 
01448 #ifdef OVR_DEFINE_NEW
01449 #define new OVR_DEFINE_NEW
01450 #endif
01451 
01452         if (!Device || !subresData)
01453         {
01454             return NULL;
01455         }
01456         int samples = (Texture_RGBA & Texture_SamplesMask);
01457         if (samples < 1)
01458         {
01459             samples = 1;
01460         }
01461 
01462         Texture* NewTex = new Texture(this, format, largestMipWidth, largestMipHeight);
01463         NewTex->Samples = samples;
01464 
01465         D3D1x_(TEXTURE2D_DESC) desc;
01466         desc.Width      = largestMipWidth;
01467         desc.Height     = largestMipHeight;
01468         desc.MipLevels  = effectiveMipCount;
01469         desc.ArraySize  = 1;
01470         desc.Format     = static_cast<DXGI_FORMAT>(convertedFormat);
01471         desc.SampleDesc.Count = samples;
01472         desc.SampleDesc.Quality = 0;
01473         desc.Usage      = D3D1x_(USAGE_DEFAULT);
01474         desc.BindFlags  = D3D1x_(BIND_SHADER_RESOURCE);
01475         desc.CPUAccessFlags = 0;
01476         desc.MiscFlags  = 0;
01477 
01478         HRESULT hr = Device->CreateTexture2D(&desc, static_cast<D3D1x_(SUBRESOURCE_DATA)*>(subresData),
01479                                              &NewTex->Tex.GetRawRef());
01480         OVR_FREE(subresData);
01481 
01482         if (SUCCEEDED(hr) && NewTex != 0)
01483         {
01484             D3D1x_(SHADER_RESOURCE_VIEW_DESC) SRVDesc;
01485             memset(&SRVDesc, 0, sizeof(SRVDesc));
01486             SRVDesc.Format = static_cast<DXGI_FORMAT>(format);
01487             SRVDesc.ViewDimension = D3D_SRV_DIMENSION_TEXTURE2D;
01488             SRVDesc.Texture2D.MipLevels = desc.MipLevels;
01489 
01490             hr = Device->CreateShaderResourceView(NewTex->Tex, NULL, &NewTex->TexSv.GetRawRef());
01491 
01492             if (FAILED(hr))
01493             {
01494                 NewTex->Release();
01495                 return NULL;
01496             }
01497             return NewTex;
01498         }
01499 
01500         return NULL;
01501     }
01502     else
01503     {
01504         DXGI_FORMAT d3dformat;
01505         int         bpp;
01506         switch(format & Texture_TypeMask)
01507         {
01508         case Texture_RGBA:
01509             bpp = 4;
01510             d3dformat = DXGI_FORMAT_R8G8B8A8_UNORM;
01511             break;
01512         case Texture_R:
01513             bpp = 1;
01514             d3dformat = DXGI_FORMAT_R8_UNORM;
01515             break;
01516         case Texture_Depth:
01517             bpp = 0;
01518             d3dformat = DXGI_FORMAT_D32_FLOAT;
01519             break;
01520         default:
01521             return NULL;
01522         }
01523 
01524         int samples = (format & Texture_SamplesMask);
01525         if (samples < 1)
01526         {
01527             samples = 1;
01528         }
01529 
01530         Texture* NewTex = new Texture(this, format, width, height);
01531         NewTex->Samples = samples;
01532 
01533         D3D1x_(TEXTURE2D_DESC) dsDesc;
01534         dsDesc.Width     = width;
01535         dsDesc.Height    = height;
01536         dsDesc.MipLevels = (format == (Texture_RGBA | Texture_GenMipmaps) && data) ? GetNumMipLevels(width, height) : 1;
01537         dsDesc.ArraySize = 1;
01538         dsDesc.Format    = d3dformat;
01539         dsDesc.SampleDesc.Count = samples;
01540         dsDesc.SampleDesc.Quality = 0;
01541         dsDesc.Usage     = D3D1x_(USAGE_DEFAULT);
01542         dsDesc.BindFlags = D3D1x_(BIND_SHADER_RESOURCE);
01543         dsDesc.CPUAccessFlags = 0;
01544         dsDesc.MiscFlags      = 0;
01545 
01546         if (format & Texture_RenderTarget)
01547         {
01548             if ((format & Texture_TypeMask) == Texture_Depth)
01549                 // We don't use depth textures, and creating them in d3d10 requires different options.
01550             {
01551                 dsDesc.BindFlags = D3D1x_(BIND_DEPTH_STENCIL);
01552             }
01553             else
01554             {
01555                 dsDesc.BindFlags |= D3D1x_(BIND_RENDER_TARGET);
01556             }
01557         }
01558 
01559         HRESULT hr = Device->CreateTexture2D(&dsDesc, NULL, &NewTex->Tex.GetRawRef());
01560         if (FAILED(hr))
01561         {
01562             OVR_DEBUG_LOG_TEXT(("Failed to create 2D D3D texture."));
01563             NewTex->Release();
01564             return NULL;
01565         }
01566         if (dsDesc.BindFlags & D3D1x_(BIND_SHADER_RESOURCE))
01567         {
01568             Device->CreateShaderResourceView(NewTex->Tex, NULL, &NewTex->TexSv.GetRawRef());
01569         }
01570 
01571         if (data)
01572         {
01573             Context->UpdateSubresource(NewTex->Tex, 0, NULL, data, width * bpp, width * height * bpp);
01574             if (format == (Texture_RGBA | Texture_GenMipmaps))
01575             {
01576                 int srcw = width, srch = height;
01577                 int level = 0;
01578                 UByte* mipmaps = NULL;
01579                 do
01580                 {
01581                     level++;
01582                     int mipw = srcw >> 1;
01583                     if (mipw < 1)
01584                     {
01585                         mipw = 1;
01586                     }
01587                     int miph = srch >> 1;
01588                     if (miph < 1)
01589                     {
01590                         miph = 1;
01591                     }
01592                     if (mipmaps == NULL)
01593                     {
01594                         mipmaps = (UByte*)OVR_ALLOC(mipw * miph * 4);
01595                     }
01596                     FilterRgba2x2(level == 1 ? (const UByte*)data : mipmaps, srcw, srch, mipmaps);
01597                     Context->UpdateSubresource(NewTex->Tex, level, NULL, mipmaps, mipw * bpp, miph * bpp);
01598                     srcw = mipw;
01599                     srch = miph;
01600                 }
01601                 while(srcw > 1 || srch > 1);
01602 
01603                 if (mipmaps != NULL)
01604                 {
01605                     OVR_FREE(mipmaps);
01606                 }
01607             }
01608         }
01609 
01610         if (format & Texture_RenderTarget)
01611         {
01612             if ((format & Texture_TypeMask) == Texture_Depth)
01613             {
01614                 Device->CreateDepthStencilView(NewTex->Tex, NULL, &NewTex->TexDsv.GetRawRef());
01615             }
01616             else
01617             {
01618                 Device->CreateRenderTargetView(NewTex->Tex, NULL, &NewTex->TexRtv.GetRawRef());
01619             }
01620         }
01621 
01622         return NewTex;
01623     }
01624 }
01625 
01626 // Rendering
01627 
01628 void RenderDevice::BeginRendering()
01629 {
01630     Context->RSSetState(Rasterizer);
01631 }
01632 
01633 void RenderDevice::SetRenderTarget(Render::Texture* color, Render::Texture* depth, Render::Texture* stencil)
01634 {
01635     OVR_UNUSED(stencil);
01636 
01637     CurRenderTarget = (Texture*)color;
01638     if (color == NULL)
01639     {
01640         Texture* newDepthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
01641         if (newDepthBuffer == NULL)
01642         {
01643             OVR_DEBUG_LOG(("New depth buffer creation failed."));
01644         }
01645         if (newDepthBuffer != NULL)
01646         {
01647             CurDepthBuffer = GetDepthBuffer(WindowWidth, WindowHeight, Params.Multisample);
01648             Context->OMSetRenderTargets(1, &BackBufferRT.GetRawRef(), CurDepthBuffer->TexDsv);
01649         }
01650         return;
01651     }
01652     if (depth == NULL)
01653     {
01654         depth = GetDepthBuffer(color->GetWidth(), color->GetHeight(), CurRenderTarget->Samples);
01655     }
01656 
01657     ID3D1xShaderResourceView* sv[8] = {0, 0, 0, 0, 0, 0, 0, 0};
01658     if (MaxTextureSet[Shader_Fragment])
01659     {
01660         Context->PSSetShaderResources(0, MaxTextureSet[Shader_Fragment], sv);
01661     }
01662     memset(MaxTextureSet, 0, sizeof(MaxTextureSet));
01663 
01664     CurDepthBuffer = (Texture*)depth;
01665     Context->OMSetRenderTargets(1, &((Texture*)color)->TexRtv.GetRawRef(), ((Texture*)depth)->TexDsv);
01666 }
01667 
01668 
01669 void RenderDevice::SetWorldUniforms(const Matrix4f& proj)
01670 {
01671     StdUniforms.Proj = proj.Transposed();
01672     // Shader constant buffers cannot be partially updated.
01673 }
01674 
01675 
01676 void RenderDevice::Render(const Matrix4f& matrix, Model* model)
01677 {
01678     // Store data in buffers if not already
01679     if (!model->VertexBuffer)
01680     {
01681         Ptr<Buffer> vb = *CreateBuffer();
01682         vb->Data(Buffer_Vertex, &model->Vertices[0], model->Vertices.GetSize() * sizeof(Vertex));
01683         model->VertexBuffer = vb;
01684     }
01685     if (!model->IndexBuffer)
01686     {
01687         Ptr<Buffer> ib = *CreateBuffer();
01688         ib->Data(Buffer_Index, &model->Indices[0], model->Indices.GetSize() * 2);
01689         model->IndexBuffer = ib;
01690     }
01691 
01692     Render(model->Fill ? model->Fill : DefaultFill,
01693            model->VertexBuffer, model->IndexBuffer,
01694            matrix, 0, (unsigned)model->Indices.GetSize(), model->GetPrimType());
01695 }
01696 
01697 void RenderDevice::RenderWithAlpha(     const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
01698                                                                         const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
01699 {
01700         Context->OMSetBlendState(BlendState, NULL, 0xffffffff);
01701     Render(fill, vertices, indices, matrix, offset, count, rprim);
01702     Context->OMSetBlendState(NULL, NULL, 0xffffffff);
01703 }
01704 
01705 void RenderDevice::Render(const Fill* fill, Render::Buffer* vertices, Render::Buffer* indices,
01706                           const Matrix4f& matrix, int offset, int count, PrimitiveType rprim)
01707 {
01708     Context->IASetInputLayout(ModelVertexIL);
01709     if (indices)
01710     {
01711         Context->IASetIndexBuffer(((Buffer*)indices)->GetBuffer(), DXGI_FORMAT_R16_UINT, 0);
01712     }
01713 
01714     ID3D1xBuffer* vertexBuffer = ((Buffer*)vertices)->GetBuffer();
01715     UINT vertexStride = sizeof(Vertex);
01716     UINT vertexOffset = offset;
01717     Context->IASetVertexBuffers(0, 1, &vertexBuffer, &vertexStride, &vertexOffset);
01718 
01719     ShaderSet* shaders = ((ShaderFill*)fill)->GetShaders();
01720 
01721     ShaderBase* vshader = ((ShaderBase*)shaders->GetShader(Shader_Vertex));
01722     unsigned char* vertexData = vshader->UniformData;
01723     if (vertexData)
01724     {
01725         StandardUniformData* stdUniforms = (StandardUniformData*) vertexData;
01726         stdUniforms->View = matrix.Transposed();
01727         stdUniforms->Proj = StdUniforms.Proj;
01728         UniformBuffers[Shader_Vertex]->Data(Buffer_Uniform, vertexData, vshader->UniformsSize);
01729         vshader->SetUniformBuffer(UniformBuffers[Shader_Vertex]);
01730     }
01731 
01732     for(int i = Shader_Vertex + 1; i < Shader_Count; i++)
01733         if (shaders->GetShader(i))
01734         {
01735             ((ShaderBase*)shaders->GetShader(i))->UpdateBuffer(UniformBuffers[i]);
01736             ((ShaderBase*)shaders->GetShader(i))->SetUniformBuffer(UniformBuffers[i]);
01737         }
01738 
01739     D3D1x_(PRIMITIVE_TOPOLOGY) prim;
01740     switch(rprim)
01741     {
01742     case Prim_Triangles:
01743         prim = D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLELIST);
01744         break;
01745     case Prim_Lines:
01746         prim = D3D1x_(PRIMITIVE_TOPOLOGY_LINELIST);
01747         break;
01748     case Prim_TriangleStrip:
01749         prim = D3D1x_(PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
01750         break;
01751     default:
01752         assert(0);
01753         return;
01754     }
01755     Context->IASetPrimitiveTopology(prim);
01756 
01757     fill->Set(rprim);
01758     if (ExtraShaders)
01759     {
01760         ExtraShaders->Set(rprim);
01761     }
01762 
01763     if (indices)
01764     {
01765         Context->DrawIndexed(count, 0, 0);
01766     }
01767     else
01768     {
01769         Context->Draw(count, 0);
01770     }
01771 }
01772 
01773 UPInt RenderDevice::QueryGPUMemorySize()
01774 {
01775         IDXGIDevice* pDXGIDevice;
01776         Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice);
01777         IDXGIAdapter * pDXGIAdapter;
01778         pDXGIDevice->GetAdapter(&pDXGIAdapter);
01779         DXGI_ADAPTER_DESC adapterDesc;
01780         pDXGIAdapter->GetDesc(&adapterDesc);
01781         return adapterDesc.DedicatedVideoMemory;
01782 }
01783 
01784 
01785 void RenderDevice::Present()
01786 {
01787     SwapChain->Present(0, 0);
01788 }
01789 
01790 void RenderDevice::ForceFlushGPU()
01791 {
01792     D3D1x_QUERY_DESC queryDesc = { D3D1x_(QUERY_EVENT), 0 };
01793     Ptr<ID3D1xQuery> query;
01794     BOOL             done = FALSE;
01795 
01796     if (Device->CreateQuery(&queryDesc, &query.GetRawRef()) == S_OK)
01797     {
01798 
01799 #if (OVR_D3D_VERSION == 10)
01800         // Begin() not used for EVENT query.
01801         query->End();
01802         // GetData will returns S_OK for both done == TRUE or FALSE.
01803         // Exit on failure to avoid infinite loop.
01804         do { }
01805         while(!done && !FAILED(query->GetData(&done, sizeof(BOOL), 0)));
01806 #else
01807         Context->End(query);
01808         do { }
01809         while(!done && !FAILED(Context->GetData(query, &done, sizeof(BOOL), 0)));
01810 #endif
01811 
01812     }
01813 }
01814 
01815 
01816 void RenderDevice::FillRect(float left, float top, float right, float bottom, Color c)
01817 {
01818     Context->OMSetBlendState(BlendState, NULL, 0xffffffff);
01819     OVR::Render::RenderDevice::FillRect(left, top, right, bottom, c);
01820     Context->OMSetBlendState(NULL, NULL, 0xffffffff);
01821 }
01822 
01823 void RenderDevice::FillGradientRect(float left, float top, float right, float bottom, Color col_top, Color col_btm)
01824 {
01825     Context->OMSetBlendState(BlendState, NULL, 0xffffffff);
01826     OVR::Render::RenderDevice::FillGradientRect(left, top, right, bottom, col_top, col_btm);
01827     Context->OMSetBlendState(NULL, NULL, 0xffffffff);
01828 }
01829 
01830 void RenderDevice::RenderText(const struct Font* font, const char* str, float x, float y, float size, Color c)
01831 {
01832         Context->OMSetBlendState(BlendState, NULL, 0xffffffff);
01833         OVR::Render::RenderDevice::RenderText(font, str, x, y, size, c);
01834         Context->OMSetBlendState(NULL, NULL, 0xffffffff);
01835 }
01836 
01837 void RenderDevice::RenderImage(float left, float top, float right, float bottom, ShaderFill* image)
01838 {
01839     Context->OMSetBlendState(BlendState, NULL, 0xffffffff);
01840     OVR::Render::RenderDevice::RenderImage(left, top, right, bottom, image);
01841     Context->OMSetBlendState(NULL, NULL, 0xffffffff);
01842 }
01843 
01844 }}}
01845 


oculus_sdk
Author(s):
autogenerated on Mon Oct 6 2014 03:01:19