summaryrefslogtreecommitdiffstats
path: root/xbmc/rendering/dx/DirectXHelper.h
blob: bb51ca6fd784bc6e155853187254747dc5d9db08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
 *  Copyright (C) 2005-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#pragma once

#include "commons/Exception.h"
#include "dxerr.h"

#include "platform/win32/CharsetConverter.h"

#include <d3d11_4.h>
#include <ppltasks.h> // For create_task

enum PCI_Vendors
{
  PCIV_AMD = 0x1002,
  PCIV_NVIDIA = 0x10DE,
  PCIV_Intel = 0x8086,
};

namespace DX
{
#define RATIONAL_TO_FLOAT(rational) ((rational.Denominator != 0) ? \
  static_cast<float>(rational.Numerator) / static_cast<float>(rational.Denominator) : 0.0f)

  namespace DisplayMetrics
  {
    // High resolution displays can require a lot of GPU and battery power to render.
    // High resolution phones, for example, may suffer from poor battery life if
    // games attempt to render at 60 frames per second at full fidelity.
    // The decision to render at full fidelity across all platforms and form factors
    // should be deliberate.
    static const bool SupportHighResolutions = true;

    // The default thresholds that define a "high resolution" display. If the thresholds
    // are exceeded and SupportHighResolutions is false, the dimensions will be scaled
    // by 50%.
    static const float Dpi100 = 96.0f;    // 100% of standard desktop display.
    static const float DpiThreshold = 192.0f;    // 200% of standard desktop display.
    static const float WidthThreshold = 1920.0f;  // 1080p width.
    static const float HeightThreshold = 1080.0f;  // 1080p height.
  };

  inline void BreakIfFailed(HRESULT hr)
  {
    if (FAILED(hr))
    {
      // Set a breakpoint on this line to catch Win32 API errors.
#if _DEBUG && !defined(TARGET_WINDOWS_STORE)
      DebugBreak();
#endif
      throw new XbmcCommons::UncheckedException(__FUNCTION__, "Unhandled error");
    }
  }

  // Converts a length in device-independent pixels (DIPs) to a length in physical pixels.
  inline float ConvertDipsToPixels(float dips, float dpi)
  {
	  static const float dipsPerInch = DisplayMetrics::Dpi100;
	  return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer.
  }

  inline float ConvertPixelsToDips(float pixels, float dpi)
  {
	  static const float dipsPerInch = DisplayMetrics::Dpi100;
	  return floorf(pixels / (dpi / dipsPerInch) + 0.5f); // Round to nearest integer.
  }

  inline float RationalToFloat(DXGI_RATIONAL rational)
  {
    return RATIONAL_TO_FLOAT(rational);
  }

  inline void GetRefreshRatio(uint32_t refresh, uint32_t *num, uint32_t *den)
  {
    int i = (((refresh + 1) % 24) == 0 || ((refresh + 1) % 30) == 0) ? 1 : 0;
    *num = (refresh + i) * 1000;
    *den = 1000 + i;
  }

  inline std::string GetErrorDescription(HRESULT hr)
  {
    using namespace KODI::PLATFORM::WINDOWS;

    WCHAR buff[2048];
    DXGetErrorDescriptionW(hr, buff, 2048);

    return FromW(StringUtils::Format(L"{:X} - {} ({})", hr, DXGetErrorStringW(hr), buff));
  }

  inline std::string GetFeatureLevelDescription(D3D_FEATURE_LEVEL featureLevel)
  {
    uint32_t fl_major = (featureLevel & 0xF000u) >> 12;
    uint32_t fl_minor = (featureLevel & 0x0F00u) >> 8;

    return StringUtils::Format("D3D_FEATURE_LEVEL_{}_{}", fl_major, fl_minor);
  }

  inline std::string GetGFXProviderName(UINT vendorId)
  {
    std::string name;
    switch (vendorId)
    {
      case PCIV_AMD:
        name = "AMD";
        break;
      case PCIV_Intel:
        name = "Intel";
        break;
      case PCIV_NVIDIA:
        name = "NVIDIA";
        break;
    }

    return name;
  }

  template <typename T> struct SizeGen
  {
    SizeGen<T>() { Width = Height = 0; }
    SizeGen<T>(T width, T height) { Width = width; Height = height; }

    bool operator !=(const SizeGen<T> &size) const
    {
      return Width != size.Width || Height != size.Height;
    }

    const SizeGen<T> &operator -=(const SizeGen<T> &size)
    {
      Width -= size.Width;
      Height -= size.Height;
      return *this;
    };

    const SizeGen<T> &operator +=(const SizeGen<T> &size)
    {
      Width += size.Width;
      Height += size.Height;
      return *this;
    };

    const SizeGen<T> &operator -=(const T &size)
    {
      Width -= size;
      Height -= size;
      return *this;
    };

    const SizeGen<T> &operator +=(const T &size)
    {
      Width += size;
      Height += size;
      return *this;
    };

    T Width, Height;
  };

#if defined(_DEBUG)
	// Check for SDK Layer support.
	inline bool SdkLayersAvailable()
	{
		HRESULT hr = D3D11CreateDevice(
			nullptr,
			D3D_DRIVER_TYPE_NULL,       // There is no need to create a real hardware device.
			nullptr,
			D3D11_CREATE_DEVICE_DEBUG,  // Check for the SDK layers.
			nullptr,                    // Any feature level will do.
			0,
			D3D11_SDK_VERSION,          // Always set this to D3D11_SDK_VERSION for Windows Store apps.
			nullptr,                    // No need to keep the D3D device reference.
			nullptr,                    // No need to know the feature level.
			nullptr                     // No need to keep the D3D device context reference.
			);

		return SUCCEEDED(hr);
	}
#endif
}

#ifdef TARGET_WINDOWS_DESKTOP
namespace winrt
{
  namespace Windows
  {
    namespace Foundation
    {
      typedef DX::SizeGen<float>  Size;
      typedef DX::SizeGen<int>    SizeInt;
    }
  }
}
#endif