1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39
40 #include "qwindowsdirect2dcontext.h"
41 #include "qwindowsdirect2dhelpers.h"
42 #include "qwindowsdirect2dintegration.h"
43
44 #include <d3d11_1.h>
45 #include <d2d1_1.h>
46 #include <d2d1_1helper.h>
47 #include <dxgi1_2.h>
48 #include <wrl.h>
49 #include <dwrite.h>
50
51 using Microsoft::WRL::ComPtr;
52
53 QT_BEGIN_NAMESPACE
54
55 class QWindowsDirect2DContextPrivate
56 {
57 public:
init()58 bool init()
59 {
60 HRESULT hr;
61
62 D3D_FEATURE_LEVEL level;
63
64 D3D_DRIVER_TYPE typeAttempts[] = {
65 D3D_DRIVER_TYPE_HARDWARE,
66 D3D_DRIVER_TYPE_WARP
67 };
68 const int ntypes = int(sizeof(typeAttempts) / sizeof(typeAttempts[0]));
69
70 for (int i = 0; i < ntypes; i++) {
71 hr = D3D11CreateDevice(nullptr,
72 typeAttempts[i],
73 nullptr,
74 D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_BGRA_SUPPORT,
75 nullptr,
76 0,
77 D3D11_SDK_VERSION,
78 &d3dDevice,
79 &level,
80 &d3dDeviceContext);
81
82 if (SUCCEEDED(hr))
83 break;
84 }
85
86 if (FAILED(hr)) {
87 qWarning("%s: Could not create Direct3D Device: %#lx", __FUNCTION__, hr);
88 return false;
89 }
90
91 ComPtr<IDXGIDevice1> dxgiDevice;
92 ComPtr<IDXGIAdapter> dxgiAdapter;
93
94 hr = d3dDevice.As(&dxgiDevice);
95 if (FAILED(hr)) {
96 qWarning("%s: DXGI Device interface query failed on D3D Device: %#lx", __FUNCTION__, hr);
97 return false;
98 }
99
100 // Ensure that DXGI doesn't queue more than one frame at a time.
101 dxgiDevice->SetMaximumFrameLatency(1);
102
103 hr = dxgiDevice->GetAdapter(&dxgiAdapter);
104 if (FAILED(hr)) {
105 qWarning("%s: Failed to probe DXGI Device for parent DXGI Adapter: %#lx", __FUNCTION__, hr);
106 return false;
107 }
108
109 hr = dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory));
110 if (FAILED(hr)) {
111 qWarning("%s: Failed to probe DXGI Adapter for parent DXGI Factory: %#lx", __FUNCTION__, hr);
112 return false;
113 }
114
115 D2D1_FACTORY_OPTIONS options = {};
116
117 #ifdef QT_D2D_DEBUG_OUTPUT
118 qDebug("Turning on Direct2D debugging messages");
119 options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
120 #endif // QT_D2D_DEBUG_OUTPUT
121
122 hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, options, d2dFactory.GetAddressOf());
123 if (FAILED(hr)) {
124 qWarning("%s: Could not create Direct2D Factory: %#lx", __FUNCTION__, hr);
125 return false;
126 }
127
128 hr = d2dFactory->CreateDevice(dxgiDevice.Get(), &d2dDevice);
129 if (FAILED(hr)) {
130 qWarning("%s: Could not create D2D Device: %#lx", __FUNCTION__, hr);
131 return false;
132 }
133
134 hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
135 static_cast<IUnknown **>(&directWriteFactory));
136 if (FAILED(hr)) {
137 qWarning("%s: Could not create DirectWrite factory: %#lx", __FUNCTION__, hr);
138 return false;
139 }
140
141 hr = directWriteFactory->GetGdiInterop(&directWriteGdiInterop);
142 if (FAILED(hr)) {
143 qWarning("%s: Could not create DirectWrite GDI Interop: %#lx", __FUNCTION__, hr);
144 return false;
145 }
146
147 return true;
148 }
149
150 ComPtr<ID3D11Device> d3dDevice;
151 ComPtr<ID2D1Factory1> d2dFactory;
152 ComPtr<ID2D1Device> d2dDevice;
153 ComPtr<IDXGIFactory2> dxgiFactory;
154 ComPtr<ID3D11DeviceContext> d3dDeviceContext;
155 ComPtr<IDWriteFactory> directWriteFactory;
156 ComPtr<IDWriteGdiInterop> directWriteGdiInterop;
157 };
158
QWindowsDirect2DContext()159 QWindowsDirect2DContext::QWindowsDirect2DContext()
160 : d_ptr(new QWindowsDirect2DContextPrivate)
161 {
162 }
163
164 QWindowsDirect2DContext::~QWindowsDirect2DContext() = default;
165
init()166 bool QWindowsDirect2DContext::init()
167 {
168 Q_D(QWindowsDirect2DContext);
169 return d->init();
170 }
171
instance()172 QWindowsDirect2DContext *QWindowsDirect2DContext::instance()
173 {
174 return QWindowsDirect2DIntegration::instance()->direct2DContext();
175 }
176
d3dDevice() const177 ID3D11Device *QWindowsDirect2DContext::d3dDevice() const
178 {
179 Q_D(const QWindowsDirect2DContext);
180 return d->d3dDevice.Get();
181 }
182
d2dDevice() const183 ID2D1Device *QWindowsDirect2DContext::d2dDevice() const
184 {
185 Q_D(const QWindowsDirect2DContext);
186 return d->d2dDevice.Get();
187 }
188
d2dFactory() const189 ID2D1Factory1 *QWindowsDirect2DContext::d2dFactory() const
190 {
191 Q_D(const QWindowsDirect2DContext);
192 return d->d2dFactory.Get();
193 }
194
dxgiFactory() const195 IDXGIFactory2 *QWindowsDirect2DContext::dxgiFactory() const
196 {
197 Q_D(const QWindowsDirect2DContext);
198 return d->dxgiFactory.Get();
199 }
200
d3dDeviceContext() const201 ID3D11DeviceContext *QWindowsDirect2DContext::d3dDeviceContext() const
202 {
203 Q_D(const QWindowsDirect2DContext);
204 return d->d3dDeviceContext.Get();
205 }
206
dwriteFactory() const207 IDWriteFactory *QWindowsDirect2DContext::dwriteFactory() const
208 {
209 Q_D(const QWindowsDirect2DContext);
210 return d->directWriteFactory.Get();
211 }
212
dwriteGdiInterop() const213 IDWriteGdiInterop *QWindowsDirect2DContext::dwriteGdiInterop() const
214 {
215 Q_D(const QWindowsDirect2DContext);
216 return d->directWriteGdiInterop.Get();
217 }
218
219 QT_END_NAMESPACE
220