[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / rendering / dx / RenderSystemDX.cpp
blob071d2116ad5d1cc09413f82578af180e438750b6
1 /*
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.
7 */
8 #include "RenderSystemDX.h"
10 #include "application/Application.h"
12 #include <mutex>
13 #if defined(TARGET_WINDOWS_DESKTOP)
14 #include "cores/RetroPlayer/process/windows/RPProcessInfoWin.h"
15 #include "cores/RetroPlayer/rendering/VideoRenderers/RPWinRenderer.h"
16 #endif
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"
21 #else
22 #include "cores/VideoPlayer/Process/windows/ProcessInfoWin.h"
23 #endif
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>
36 extern "C" {
37 #include <libavutil/pixfmt.h>
40 using namespace KODI;
41 using namespace DirectX;
42 using namespace DirectX::PackedVector;
43 using namespace Microsoft::WRL;
44 using namespace std::chrono_literals;
46 CRenderSystemDX::CRenderSystemDX() : CRenderSystemBase()
48 m_bVSync = true;
50 memset(&m_viewPort, 0, sizeof m_viewPort);
51 memset(&m_scissor, 0, sizeof m_scissor);
54 CRenderSystemDX::~CRenderSystemDX() = default;
56 bool CRenderSystemDX::InitRenderSystem()
58 m_bVSync = true;
60 // check various device capabilities
61 CheckDeviceCaps();
63 if (!CreateStates() || !InitGUIShader())
64 return false;
66 m_bRenderCreated = true;
67 m_deviceResources->RegisterDeviceNotify(this);
69 // register platform dependent objects
70 #if defined(TARGET_WINDOWS_STORE)
71 VIDEOPLAYER::CProcessInfoWin10::Register();
72 #else
73 VIDEOPLAYER::CProcessInfoWin::Register();
74 #endif
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);
82 #endif
83 m_viewPort = m_deviceResources->GetScreenViewport();
84 RestoreViewPort();
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);
93 uint32_t version = 0;
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();
100 return true;
103 void CRenderSystemDX::OnResize()
105 if (!m_bRenderCreated)
106 return;
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();
120 UINT supported;
121 pD3DDev->CheckFormatSupport(format, &supported);
122 return (supported & usage) != 0;
125 bool CRenderSystemDX::DestroyRenderSystem()
127 std::unique_lock<CCriticalSection> lock(m_resourceSection);
129 if (m_pGUIShader)
131 m_pGUIShader->End();
132 delete m_pGUIShader;
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;
142 return true;
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
167 else
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();
177 if (!m_pD3DDev)
178 return false;
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);
208 if(FAILED(hr))
209 return false;
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)))
227 return false;
229 rasterizerState.ScissorEnable = true;
230 if (FAILED(m_pD3DDev->CreateRasterizerState(&rasterizerState, &m_RSScissorEnable)))
231 return false;
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);
250 // by default
251 m_pContext->OMSetBlendState(m_BlendEnableState.Get(), nullptr, 0xFFFFFFFF);
252 m_BlendEnabled = true;
254 return true;
257 void CRenderSystemDX::PresentRender(bool rendered, bool videoLayer)
259 if (!m_bRenderCreated)
260 return;
262 if ( rendered
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;
286 timer.Set(5ms);
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)
312 return false;
314 m_limitedColorRange = CServiceBroker::GetWinSystem()->UseLimitedColor();
315 m_inScene = m_deviceResources->Begin();
316 return m_inScene;
319 bool CRenderSystemDX::EndRender()
321 m_inScene = false;
323 if (!m_bRenderCreated)
324 return false;
326 return true;
329 bool CRenderSystemDX::ClearBuffers(KODI::UTILS::COLOR::Color color)
331 if (!m_bRenderCreated)
332 return false;
334 float fColor[4];
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)
352 pRTView = nullptr;
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)
364 return true;
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;
376 if (alphaEnabled)
377 SetAlphaBlendEnable(false);
379 CGUITextureD3D::DrawQuad(clRect, color);
381 if (alphaEnabled)
382 SetAlphaBlendEnable(true);
384 else
385 m_deviceResources->ClearRenderTarget(pRTView, fColor);
387 m_deviceResources->ClearDepthStencil();
388 return true;
391 void CRenderSystemDX::CaptureStateBlock()
393 if (!m_bRenderCreated)
394 return;
397 void CRenderSystemDX::ApplyStateBlock()
399 if (!m_bRenderCreated)
400 return;
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)
415 return;
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)
439 return;
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)
453 return;
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)
464 return;
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)
480 return;
482 m_deviceResources->SetViewPort(m_viewPort);
483 m_pGUIShader->SetViewPort(m_viewPort);
486 bool CRenderSystemDX::ScissorsCanEffectClipping()
488 if (!m_bRenderCreated)
489 return false;
491 return m_pGUIShader != nullptr && m_pGUIShader->HardwareClipIsPossible();
494 CRect CRenderSystemDX::ClipRectToScissorRect(const CRect &rect)
496 if (!m_bRenderCreated)
497 return CRect();
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)
513 return;
515 auto m_pContext = m_deviceResources->GetD3DContext();
517 m_scissor = rect;
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)
531 return;
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)
559 return;
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
623 switch (mode)
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:
630 return true;
631 case RENDER_STEREO_MODE_HARDWAREBASED:
632 return m_deviceResources->IsStereoAvailable();
633 default:
634 return CRenderSystemBase::SupportsStereo(mode);
638 void CRenderSystemDX::FlushGPU() const
640 if (!m_bRenderCreated)
641 return;
643 m_deviceResources->FinishCommandList();
644 m_deviceResources->GetImmediateContext()->Flush();
647 bool CRenderSystemDX::InitGUIShader()
649 delete m_pGUIShader;
650 m_pGUIShader = nullptr;
652 m_pGUIShader = new CGUIShaderDX();
653 if (!m_pGUIShader->Initialize())
655 CLog::LogF(LOGERROR, "Failed to initialize GUI shader.");
656 return false;
659 m_pGUIShader->ApplyStateBlock();
660 return true;
663 void CRenderSystemDX::SetAlphaBlendEnable(bool enable)
665 if (!m_bRenderCreated)
666 return;
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;
689 else
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
696 // MSDN says:
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;