2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
8 #include "RenderSystemDX.h"
10 #include "application/Application.h"
13 #if defined(TARGET_WINDOWS_DESKTOP)
14 #include "cores/RetroPlayer/process/windows/RPProcessInfoWin.h"
15 #include "cores/RetroPlayer/rendering/VideoRenderers/RPWinRenderer.h"
17 #include "cores/VideoPlayer/DVDCodecs/DVDFactoryCodec.h"
18 #include "cores/VideoPlayer/DVDCodecs/Video/DXVA.h"
19 #if defined(TARGET_WINDOWS_STORE)
20 #include "cores/VideoPlayer/Process/windows/ProcessInfoWin10.h"
22 #include "cores/VideoPlayer/Process/windows/ProcessInfoWin.h"
24 #include "cores/VideoPlayer/VideoRenderers/RenderFactory.h"
25 #include "cores/VideoPlayer/VideoRenderers/WinRenderer.h"
26 #include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
27 #include "guilib/D3DResource.h"
28 #include "guilib/GUIShaderDX.h"
29 #include "guilib/GUITextureD3D.h"
30 #include "guilib/GUIWindowManager.h"
31 #include "utils/MathUtils.h"
32 #include "utils/log.h"
34 #include <DirectXPackedVector.h>
37 #include <libavutil/pixfmt.h>
41 using namespace DirectX
;
42 using namespace DirectX::PackedVector
;
43 using namespace Microsoft::WRL
;
44 using namespace std::chrono_literals
;
46 CRenderSystemDX::CRenderSystemDX() : CRenderSystemBase()
50 memset(&m_viewPort
, 0, sizeof m_viewPort
);
51 memset(&m_scissor
, 0, sizeof m_scissor
);
54 CRenderSystemDX::~CRenderSystemDX() = default;
56 bool CRenderSystemDX::InitRenderSystem()
60 // check various device capabilities
63 if (!CreateStates() || !InitGUIShader())
66 m_bRenderCreated
= true;
67 m_deviceResources
->RegisterDeviceNotify(this);
69 // register platform dependent objects
70 #if defined(TARGET_WINDOWS_STORE)
71 VIDEOPLAYER::CProcessInfoWin10::Register();
73 VIDEOPLAYER::CProcessInfoWin::Register();
75 CDVDFactoryCodec::ClearHWAccels();
76 DXVA::CDecoder::Register();
77 VIDEOPLAYER::CRendererFactory::ClearRenderer();
78 CWinRenderer::Register();
79 #if defined(TARGET_WINDOWS_DESKTOP)
80 RETRO::CRPProcessInfoWin::Register();
81 RETRO::CRPProcessInfoWin::RegisterRendererFactory(new RETRO::CWinRendererFactory
);
83 m_viewPort
= m_deviceResources
->GetScreenViewport();
86 auto outputSize
= m_deviceResources
->GetOutputSize();
87 // set camera to center of screen
88 CPoint camPoint
= { outputSize
.Width
* 0.5f
, outputSize
.Height
* 0.5f
};
89 SetCameraPosition(camPoint
, outputSize
.Width
, outputSize
.Height
);
91 const DXGI_ADAPTER_DESC AIdentifier
= m_deviceResources
->GetAdapterDesc();
92 m_RenderRenderer
= KODI::PLATFORM::WINDOWS::FromW(AIdentifier
.Description
);
94 for (uint32_t decimal
= m_deviceResources
->GetDeviceFeatureLevel() >> 8, round
= 0; decimal
> 0; decimal
>>= 4, ++round
)
95 version
+= (decimal
% 16) * std::pow(10, round
);
96 m_RenderVersion
= StringUtils::Format("{:.1f}", static_cast<float>(version
) / 10.0f
);
98 CGUITextureD3D::Register();
103 void CRenderSystemDX::OnResize()
105 if (!m_bRenderCreated
)
108 auto outputSize
= m_deviceResources
->GetOutputSize();
110 // set camera to center of screen
111 CPoint camPoint
= { outputSize
.Width
* 0.5f
, outputSize
.Height
* 0.5f
};
112 SetCameraPosition(camPoint
, outputSize
.Width
, outputSize
.Height
);
114 CheckInterlacedStereoView();
117 bool CRenderSystemDX::IsFormatSupport(DXGI_FORMAT format
, unsigned int usage
) const
119 ComPtr
<ID3D11Device1
> pD3DDev
= m_deviceResources
->GetD3DDevice();
121 pD3DDev
->CheckFormatSupport(format
, &supported
);
122 return (supported
& usage
) != 0;
125 bool CRenderSystemDX::DestroyRenderSystem()
127 std::unique_lock
<CCriticalSection
> lock(m_resourceSection
);
133 m_pGUIShader
= nullptr;
135 m_rightEyeTex
.Release();
136 m_BlendEnableState
= nullptr;
137 m_BlendDisableState
= nullptr;
138 m_RSScissorDisable
= nullptr;
139 m_RSScissorEnable
= nullptr;
140 m_depthStencilState
= nullptr;
145 void CRenderSystemDX::CheckInterlacedStereoView()
147 RENDER_STEREO_MODE stereoMode
= CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode();
149 if ( m_rightEyeTex
.Get()
150 && RENDER_STEREO_MODE_INTERLACED
!= stereoMode
151 && RENDER_STEREO_MODE_CHECKERBOARD
!= stereoMode
)
153 m_rightEyeTex
.Release();
156 if ( !m_rightEyeTex
.Get()
157 && ( RENDER_STEREO_MODE_INTERLACED
== stereoMode
158 || RENDER_STEREO_MODE_CHECKERBOARD
== stereoMode
))
160 const auto outputSize
= m_deviceResources
->GetOutputSize();
161 DXGI_FORMAT texFormat
= m_deviceResources
->GetBackBuffer().GetFormat();
162 if (!m_rightEyeTex
.Create(outputSize
.Width
, outputSize
.Height
, 1, D3D11_USAGE_DEFAULT
, texFormat
))
164 CLog::Log(LOGERROR
, "{} - Failed to create right eye buffer.", __FUNCTION__
);
165 CServiceBroker::GetWinSystem()->GetGfxContext().SetStereoMode(RENDER_STEREO_MODE_SPLIT_HORIZONTAL
); // try fallback to split horizontal
168 m_deviceResources
->Unregister(&m_rightEyeTex
); // we will handle its health
172 bool CRenderSystemDX::CreateStates()
174 auto m_pD3DDev
= m_deviceResources
->GetD3DDevice();
175 auto m_pContext
= m_deviceResources
->GetD3DContext();
180 m_BlendEnableState
= nullptr;
181 m_BlendDisableState
= nullptr;
183 // Initialize the description of the stencil state.
184 D3D11_DEPTH_STENCIL_DESC depthStencilDesc
= {};
186 // Set up the description of the stencil state.
187 depthStencilDesc
.DepthEnable
= false;
188 depthStencilDesc
.DepthWriteMask
= D3D11_DEPTH_WRITE_MASK_ALL
;
189 depthStencilDesc
.DepthFunc
= D3D11_COMPARISON_NEVER
;
190 depthStencilDesc
.StencilEnable
= false;
191 depthStencilDesc
.StencilReadMask
= 0xFF;
192 depthStencilDesc
.StencilWriteMask
= 0xFF;
194 // Stencil operations if pixel is front-facing.
195 depthStencilDesc
.FrontFace
.StencilFailOp
= D3D11_STENCIL_OP_KEEP
;
196 depthStencilDesc
.FrontFace
.StencilDepthFailOp
= D3D11_STENCIL_OP_INCR
;
197 depthStencilDesc
.FrontFace
.StencilPassOp
= D3D11_STENCIL_OP_KEEP
;
198 depthStencilDesc
.FrontFace
.StencilFunc
= D3D11_COMPARISON_ALWAYS
;
200 // Stencil operations if pixel is back-facing.
201 depthStencilDesc
.BackFace
.StencilFailOp
= D3D11_STENCIL_OP_KEEP
;
202 depthStencilDesc
.BackFace
.StencilDepthFailOp
= D3D11_STENCIL_OP_DECR
;
203 depthStencilDesc
.BackFace
.StencilPassOp
= D3D11_STENCIL_OP_KEEP
;
204 depthStencilDesc
.BackFace
.StencilFunc
= D3D11_COMPARISON_ALWAYS
;
206 // Create the depth stencil state.
207 HRESULT hr
= m_pD3DDev
->CreateDepthStencilState(&depthStencilDesc
, &m_depthStencilState
);
211 // Set the depth stencil state.
212 m_pContext
->OMSetDepthStencilState(m_depthStencilState
.Get(), 0);
214 D3D11_RASTERIZER_DESC rasterizerState
;
215 rasterizerState
.CullMode
= D3D11_CULL_NONE
;
216 rasterizerState
.FillMode
= D3D11_FILL_SOLID
;// DEBUG - D3D11_FILL_WIREFRAME
217 rasterizerState
.FrontCounterClockwise
= false;
218 rasterizerState
.DepthBias
= 0;
219 rasterizerState
.DepthBiasClamp
= 0.0f
;
220 rasterizerState
.DepthClipEnable
= true;
221 rasterizerState
.SlopeScaledDepthBias
= 0.0f
;
222 rasterizerState
.ScissorEnable
= false;
223 rasterizerState
.MultisampleEnable
= false;
224 rasterizerState
.AntialiasedLineEnable
= false;
226 if (FAILED(m_pD3DDev
->CreateRasterizerState(&rasterizerState
, &m_RSScissorDisable
)))
229 rasterizerState
.ScissorEnable
= true;
230 if (FAILED(m_pD3DDev
->CreateRasterizerState(&rasterizerState
, &m_RSScissorEnable
)))
233 m_pContext
->RSSetState(m_RSScissorDisable
.Get()); // by default
235 D3D11_BLEND_DESC blendState
= {};
236 blendState
.RenderTarget
[0].BlendEnable
= true;
237 blendState
.RenderTarget
[0].SrcBlend
= D3D11_BLEND_SRC_ALPHA
; // D3D11_BLEND_SRC_ALPHA;
238 blendState
.RenderTarget
[0].DestBlend
= D3D11_BLEND_INV_SRC_ALPHA
; // D3D11_BLEND_INV_SRC_ALPHA;
239 blendState
.RenderTarget
[0].BlendOp
= D3D11_BLEND_OP_ADD
;
240 blendState
.RenderTarget
[0].SrcBlendAlpha
= D3D11_BLEND_ONE
;
241 blendState
.RenderTarget
[0].DestBlendAlpha
= D3D11_BLEND_INV_SRC_ALPHA
;
242 blendState
.RenderTarget
[0].BlendOpAlpha
= D3D11_BLEND_OP_ADD
;
243 blendState
.RenderTarget
[0].RenderTargetWriteMask
= D3D11_COLOR_WRITE_ENABLE_ALL
;
245 m_pD3DDev
->CreateBlendState(&blendState
, &m_BlendEnableState
);
247 blendState
.RenderTarget
[0].BlendEnable
= false;
248 m_pD3DDev
->CreateBlendState(&blendState
, &m_BlendDisableState
);
251 m_pContext
->OMSetBlendState(m_BlendEnableState
.Get(), nullptr, 0xFFFFFFFF);
252 m_BlendEnabled
= true;
257 void CRenderSystemDX::PresentRender(bool rendered
, bool videoLayer
)
259 if (!m_bRenderCreated
)
263 && ( m_stereoMode
== RENDER_STEREO_MODE_INTERLACED
264 || m_stereoMode
== RENDER_STEREO_MODE_CHECKERBOARD
))
266 auto m_pContext
= m_deviceResources
->GetD3DContext();
268 // all views prepared, let's merge them before present
269 m_pContext
->OMSetRenderTargets(1, m_deviceResources
->GetBackBuffer().GetAddressOfRTV(), m_deviceResources
->GetDSV());
271 auto outputSize
= m_deviceResources
->GetOutputSize();
272 CRect destRect
= { 0.0f
, 0.0f
, float(outputSize
.Width
), float(outputSize
.Height
) };
274 SHADER_METHOD method
= RENDER_STEREO_MODE_INTERLACED
== m_stereoMode
275 ? SHADER_METHOD_RENDER_STEREO_INTERLACED_RIGHT
276 : SHADER_METHOD_RENDER_STEREO_CHECKERBOARD_RIGHT
;
277 SetAlphaBlendEnable(true);
278 CD3DTexture::DrawQuad(destRect
, 0, &m_rightEyeTex
, nullptr, method
);
279 CD3DHelper::PSClearShaderResources(m_pContext
);
282 // time for decoder that may require the context
284 std::unique_lock
<CCriticalSection
> lock(m_decoderSection
);
285 XbmcThreads::EndTime
<> timer
;
287 while (!m_decodingTimer
.IsTimePast() && !timer
.IsTimePast())
289 m_decodingEvent
.wait(lock
, 1ms
);
293 PresentRenderImpl(rendered
);
296 void CRenderSystemDX::RequestDecodingTime()
298 std::unique_lock
<CCriticalSection
> lock(m_decoderSection
);
299 m_decodingTimer
.Set(3ms
);
302 void CRenderSystemDX::ReleaseDecodingTime()
304 std::unique_lock
<CCriticalSection
> lock(m_decoderSection
);
305 m_decodingTimer
.SetExpired();
306 m_decodingEvent
.notify();
309 bool CRenderSystemDX::BeginRender()
311 if (!m_bRenderCreated
)
314 m_limitedColorRange
= CServiceBroker::GetWinSystem()->UseLimitedColor();
315 m_inScene
= m_deviceResources
->Begin();
319 bool CRenderSystemDX::EndRender()
323 if (!m_bRenderCreated
)
329 bool CRenderSystemDX::ClearBuffers(KODI::UTILS::COLOR::Color color
)
331 if (!m_bRenderCreated
)
335 CD3DHelper::XMStoreColor(fColor
, color
);
336 ID3D11RenderTargetView
* pRTView
= m_deviceResources
->GetBackBuffer().GetRenderTarget();
338 if ( m_stereoMode
!= RENDER_STEREO_MODE_OFF
339 && m_stereoMode
!= RENDER_STEREO_MODE_MONO
)
341 // if stereo anaglyph/tab/sbs, data was cleared when left view was rendered
342 if (m_stereoView
== RENDER_STEREO_VIEW_RIGHT
)
344 // execute command's queue
345 m_deviceResources
->FinishCommandList();
347 // do not clear RT for anaglyph modes
348 if ( m_stereoMode
== RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA
349 || m_stereoMode
== RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
350 || m_stereoMode
== RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE
)
354 // for interlaced/checkerboard clear view for right texture
355 else if (m_stereoMode
== RENDER_STEREO_MODE_INTERLACED
356 || m_stereoMode
== RENDER_STEREO_MODE_CHECKERBOARD
)
358 pRTView
= m_rightEyeTex
.GetRenderTarget();
363 if (pRTView
== nullptr)
366 auto outputSize
= m_deviceResources
->GetOutputSize();
367 CRect
clRect(0.0f
, 0.0f
,
368 static_cast<float>(outputSize
.Width
),
369 static_cast<float>(outputSize
.Height
));
371 // Unlike Direct3D 9, D3D11 ClearRenderTargetView always clears full extent of the resource view.
372 // Viewport and scissor settings are not applied. So clear RT by drawing full sized rect with clear color
373 if (m_ScissorsEnabled
&& m_scissor
!= clRect
)
375 bool alphaEnabled
= m_BlendEnabled
;
377 SetAlphaBlendEnable(false);
379 CGUITextureD3D::DrawQuad(clRect
, color
);
382 SetAlphaBlendEnable(true);
385 m_deviceResources
->ClearRenderTarget(pRTView
, fColor
);
387 m_deviceResources
->ClearDepthStencil();
391 void CRenderSystemDX::CaptureStateBlock()
393 if (!m_bRenderCreated
)
397 void CRenderSystemDX::ApplyStateBlock()
399 if (!m_bRenderCreated
)
402 auto m_pContext
= m_deviceResources
->GetD3DContext();
404 m_pContext
->RSSetState(m_ScissorsEnabled
? m_RSScissorEnable
.Get() : m_RSScissorDisable
.Get());
405 m_pContext
->OMSetDepthStencilState(m_depthStencilState
.Get(), 0);
406 float factors
[4] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
};
407 m_pContext
->OMSetBlendState(m_BlendEnabled
? m_BlendEnableState
.Get() : m_BlendDisableState
.Get(), factors
, 0xFFFFFFFF);
409 m_pGUIShader
->ApplyStateBlock();
412 void CRenderSystemDX::SetCameraPosition(const CPoint
&camera
, int screenWidth
, int screenHeight
, float stereoFactor
)
414 if (!m_bRenderCreated
)
417 // grab the viewport dimensions and location
418 float w
= m_viewPort
.Width
* 0.5f
;
419 float h
= m_viewPort
.Height
* 0.5f
;
421 XMFLOAT2 offset
= XMFLOAT2(camera
.x
- screenWidth
*0.5f
, camera
.y
- screenHeight
*0.5f
);
423 // world view. Until this is moved onto the GPU (via a vertex shader for instance), we set it to the identity here.
424 m_pGUIShader
->SetWorld(XMMatrixIdentity());
426 // Initialize the view matrix camera view.
427 // Multiply the Y coord by -1 then translate so that everything is relative to the camera position.
428 XMMATRIX flipY
= XMMatrixScaling(1.0, -1.0f
, 1.0f
);
429 XMMATRIX translate
= XMMatrixTranslation(-(w
+ offset
.x
- stereoFactor
), -(h
+ offset
.y
), 2 * h
);
430 m_pGUIShader
->SetView(XMMatrixMultiply(translate
, flipY
));
432 // projection onto screen space
433 m_pGUIShader
->SetProjection(XMMatrixPerspectiveOffCenterLH((-w
- offset
.x
)*0.5f
, (w
- offset
.x
)*0.5f
, (-h
+ offset
.y
)*0.5f
, (h
+ offset
.y
)*0.5f
, h
, 100 * h
));
436 void CRenderSystemDX::Project(float &x
, float &y
, float &z
)
438 if (!m_bRenderCreated
)
441 m_pGUIShader
->Project(x
, y
, z
);
444 CRect
CRenderSystemDX::GetBackBufferRect()
446 auto outputSize
= m_deviceResources
->GetOutputSize();
447 return CRect(0.f
, 0.f
, static_cast<float>(outputSize
.Width
), static_cast<float>(outputSize
.Height
));
450 void CRenderSystemDX::GetViewPort(CRect
& viewPort
)
452 if (!m_bRenderCreated
)
455 viewPort
.x1
= m_viewPort
.TopLeftX
;
456 viewPort
.y1
= m_viewPort
.TopLeftY
;
457 viewPort
.x2
= m_viewPort
.TopLeftX
+ m_viewPort
.Width
;
458 viewPort
.y2
= m_viewPort
.TopLeftY
+ m_viewPort
.Height
;
461 void CRenderSystemDX::SetViewPort(const CRect
& viewPort
)
463 if (!m_bRenderCreated
)
466 m_viewPort
.MinDepth
= 0.0f
;
467 m_viewPort
.MaxDepth
= 1.0f
;
468 m_viewPort
.TopLeftX
= viewPort
.x1
;
469 m_viewPort
.TopLeftY
= viewPort
.y1
;
470 m_viewPort
.Width
= viewPort
.x2
- viewPort
.x1
;
471 m_viewPort
.Height
= viewPort
.y2
- viewPort
.y1
;
473 m_deviceResources
->SetViewPort(m_viewPort
);
474 m_pGUIShader
->SetViewPort(m_viewPort
);
477 void CRenderSystemDX::RestoreViewPort()
479 if (!m_bRenderCreated
)
482 m_deviceResources
->SetViewPort(m_viewPort
);
483 m_pGUIShader
->SetViewPort(m_viewPort
);
486 bool CRenderSystemDX::ScissorsCanEffectClipping()
488 if (!m_bRenderCreated
)
491 return m_pGUIShader
!= nullptr && m_pGUIShader
->HardwareClipIsPossible();
494 CRect
CRenderSystemDX::ClipRectToScissorRect(const CRect
&rect
)
496 if (!m_bRenderCreated
)
499 float xFactor
= m_pGUIShader
->GetClipXFactor();
500 float xOffset
= m_pGUIShader
->GetClipXOffset();
501 float yFactor
= m_pGUIShader
->GetClipYFactor();
502 float yOffset
= m_pGUIShader
->GetClipYOffset();
504 return CRect(rect
.x1
* xFactor
+ xOffset
,
505 rect
.y1
* yFactor
+ yOffset
,
506 rect
.x2
* xFactor
+ xOffset
,
507 rect
.y2
* yFactor
+ yOffset
);
510 void CRenderSystemDX::SetScissors(const CRect
& rect
)
512 if (!m_bRenderCreated
)
515 auto m_pContext
= m_deviceResources
->GetD3DContext();
518 CD3D11_RECT
scissor(MathUtils::round_int(rect
.x1
)
519 , MathUtils::round_int(rect
.y1
)
520 , MathUtils::round_int(rect
.x2
)
521 , MathUtils::round_int(rect
.y2
));
523 m_pContext
->RSSetScissorRects(1, &scissor
);
524 m_pContext
->RSSetState(m_RSScissorEnable
.Get());
525 m_ScissorsEnabled
= true;
528 void CRenderSystemDX::ResetScissors()
530 if (!m_bRenderCreated
)
533 auto m_pContext
= m_deviceResources
->GetD3DContext();
534 auto outputSize
= m_deviceResources
->GetOutputSize();
536 m_scissor
.SetRect(0.0f
, 0.0f
,
537 static_cast<float>(outputSize
.Width
),
538 static_cast<float>(outputSize
.Height
));
540 m_pContext
->RSSetState(m_RSScissorDisable
.Get());
541 m_ScissorsEnabled
= false;
544 void CRenderSystemDX::OnDXDeviceLost()
546 CRenderSystemDX::DestroyRenderSystem();
549 void CRenderSystemDX::OnDXDeviceRestored()
551 CRenderSystemDX::InitRenderSystem();
554 void CRenderSystemDX::SetStereoMode(RENDER_STEREO_MODE mode
, RENDER_STEREO_VIEW view
)
556 CRenderSystemBase::SetStereoMode(mode
, view
);
558 if (!m_bRenderCreated
)
561 auto m_pContext
= m_deviceResources
->GetD3DContext();
563 UINT writeMask
= D3D11_COLOR_WRITE_ENABLE_ALL
;
564 if(m_stereoMode
== RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
)
566 if(m_stereoView
== RENDER_STEREO_VIEW_LEFT
)
567 writeMask
= D3D11_COLOR_WRITE_ENABLE_RED
;
568 else if(m_stereoView
== RENDER_STEREO_VIEW_RIGHT
)
569 writeMask
= D3D11_COLOR_WRITE_ENABLE_BLUE
| D3D11_COLOR_WRITE_ENABLE_GREEN
;
571 if(m_stereoMode
== RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA
)
573 if(m_stereoView
== RENDER_STEREO_VIEW_LEFT
)
574 writeMask
= D3D11_COLOR_WRITE_ENABLE_GREEN
;
575 else if(m_stereoView
== RENDER_STEREO_VIEW_RIGHT
)
576 writeMask
= D3D11_COLOR_WRITE_ENABLE_BLUE
| D3D11_COLOR_WRITE_ENABLE_RED
;
578 if (m_stereoMode
== RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE
)
580 if (m_stereoView
== RENDER_STEREO_VIEW_LEFT
)
581 writeMask
= D3D11_COLOR_WRITE_ENABLE_RED
| D3D11_COLOR_WRITE_ENABLE_GREEN
;
582 else if (m_stereoView
== RENDER_STEREO_VIEW_RIGHT
)
583 writeMask
= D3D11_COLOR_WRITE_ENABLE_BLUE
;
585 if ( RENDER_STEREO_MODE_INTERLACED
== m_stereoMode
586 || RENDER_STEREO_MODE_CHECKERBOARD
== m_stereoMode
)
588 if (m_stereoView
== RENDER_STEREO_VIEW_RIGHT
)
590 m_pContext
->OMSetRenderTargets(1, m_rightEyeTex
.GetAddressOfRTV(), m_deviceResources
->GetDSV());
593 else if (RENDER_STEREO_MODE_HARDWAREBASED
== m_stereoMode
)
595 m_deviceResources
->SetStereoIdx(m_stereoView
== RENDER_STEREO_VIEW_RIGHT
? 1 : 0);
597 m_pContext
->OMSetRenderTargets(1, m_deviceResources
->GetBackBuffer().GetAddressOfRTV(), m_deviceResources
->GetDSV());
600 auto m_pD3DDev
= m_deviceResources
->GetD3DDevice();
602 D3D11_BLEND_DESC desc
;
603 m_BlendEnableState
->GetDesc(&desc
);
604 // update blend state
605 if (desc
.RenderTarget
[0].RenderTargetWriteMask
!= writeMask
)
607 m_BlendDisableState
= nullptr;
608 m_BlendEnableState
= nullptr;
610 desc
.RenderTarget
[0].RenderTargetWriteMask
= writeMask
;
611 m_pD3DDev
->CreateBlendState(&desc
, &m_BlendEnableState
);
613 desc
.RenderTarget
[0].BlendEnable
= false;
614 m_pD3DDev
->CreateBlendState(&desc
, &m_BlendDisableState
);
616 float blendFactors
[] = { 0.0f
, 0.0f
, 0.0f
, 0.0f
};
617 m_pContext
->OMSetBlendState(m_BlendEnabled
? m_BlendEnableState
.Get() : m_BlendDisableState
.Get(), blendFactors
, 0xFFFFFFFF);
621 bool CRenderSystemDX::SupportsStereo(RENDER_STEREO_MODE mode
) const
625 case RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
:
626 case RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA
:
627 case RENDER_STEREO_MODE_ANAGLYPH_YELLOW_BLUE
:
628 case RENDER_STEREO_MODE_INTERLACED
:
629 case RENDER_STEREO_MODE_CHECKERBOARD
:
631 case RENDER_STEREO_MODE_HARDWAREBASED
:
632 return m_deviceResources
->IsStereoAvailable();
634 return CRenderSystemBase::SupportsStereo(mode
);
638 void CRenderSystemDX::FlushGPU() const
640 if (!m_bRenderCreated
)
643 m_deviceResources
->FinishCommandList();
644 m_deviceResources
->GetImmediateContext()->Flush();
647 bool CRenderSystemDX::InitGUIShader()
650 m_pGUIShader
= nullptr;
652 m_pGUIShader
= new CGUIShaderDX();
653 if (!m_pGUIShader
->Initialize())
655 CLog::LogF(LOGERROR
, "Failed to initialize GUI shader.");
659 m_pGUIShader
->ApplyStateBlock();
663 void CRenderSystemDX::SetAlphaBlendEnable(bool enable
)
665 if (!m_bRenderCreated
)
668 m_deviceResources
->GetD3DContext()->OMSetBlendState(enable
? m_BlendEnableState
.Get() : m_BlendDisableState
.Get(), nullptr, 0xFFFFFFFF);
669 m_BlendEnabled
= enable
;
672 CD3DTexture
& CRenderSystemDX::GetBackBuffer()
674 if (m_stereoView
== RENDER_STEREO_VIEW_RIGHT
&& m_rightEyeTex
.Get())
675 return m_rightEyeTex
;
677 return m_deviceResources
->GetBackBuffer();
680 void CRenderSystemDX::CheckDeviceCaps()
682 const auto feature_level
= m_deviceResources
->GetDeviceFeatureLevel();
683 if (feature_level
< D3D_FEATURE_LEVEL_9_3
)
684 m_maxTextureSize
= D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION
;
685 else if (feature_level
< D3D_FEATURE_LEVEL_10_0
)
686 m_maxTextureSize
= D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION
;
687 else if (feature_level
< D3D_FEATURE_LEVEL_11_0
)
688 m_maxTextureSize
= D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION
;
690 // 11_x and greater feature level. Limit this size to avoid memory overheads
691 m_maxTextureSize
= D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION
>> 1;
694 bool CRenderSystemDX::SupportsNPOT(bool dxt
) const
697 // At feature levels 9_1, 9_2 and 9_3, the display device supports the use
698 // of 2D textures with dimensions that are not powers of two under two conditions:
699 // 1) only one MIP-map level for each texture can be created - we are using both 1 and 0 mipmap levels
700 // 2) no wrap sampler modes for textures are allowed - we are using clamp everywhere
701 // At feature levels 10_0, 10_1 and 11_0, the display device unconditionally supports the use of 2D textures with dimensions that are not powers of two.
702 // taking in account first condition we setup caps NPOT for FE > 9.x only
703 return m_deviceResources
->GetDeviceFeatureLevel() > D3D_FEATURE_LEVEL_9_3
? true : false;