1 //
2 // Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // NativeWindow11Win32.cpp: Implementation of NativeWindow11 using win32 window APIs.
8
9 #include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
10 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
11
12 #include "common/debug.h"
13
14 #include <initguid.h>
15 #include <dcomp.h>
16
17 namespace rx
18 {
19
NativeWindow11Win32(EGLNativeWindowType window,bool hasAlpha,bool directComposition)20 NativeWindow11Win32::NativeWindow11Win32(EGLNativeWindowType window,
21 bool hasAlpha,
22 bool directComposition)
23 : NativeWindow11(window),
24 mDirectComposition(directComposition),
25 mHasAlpha(hasAlpha),
26 mDevice(nullptr),
27 mCompositionTarget(nullptr),
28 mVisual(nullptr)
29 {
30 }
31
~NativeWindow11Win32()32 NativeWindow11Win32::~NativeWindow11Win32()
33 {
34 SafeRelease(mCompositionTarget);
35 SafeRelease(mDevice);
36 SafeRelease(mVisual);
37 }
38
initialize()39 bool NativeWindow11Win32::initialize()
40 {
41 return true;
42 }
43
getClientRect(LPRECT rect) const44 bool NativeWindow11Win32::getClientRect(LPRECT rect) const
45 {
46 return GetClientRect(getNativeWindow(), rect) == TRUE;
47 }
48
isIconic() const49 bool NativeWindow11Win32::isIconic() const
50 {
51 return IsIconic(getNativeWindow()) == TRUE;
52 }
53
createSwapChain(ID3D11Device * device,IDXGIFactory * factory,DXGI_FORMAT format,UINT width,UINT height,UINT samples,IDXGISwapChain ** swapChain)54 HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device,
55 IDXGIFactory *factory,
56 DXGI_FORMAT format,
57 UINT width,
58 UINT height,
59 UINT samples,
60 IDXGISwapChain **swapChain)
61 {
62 if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
63 height == 0)
64 {
65 return E_INVALIDARG;
66 }
67
68 if (mDirectComposition)
69 {
70 HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll"));
71 if (!dcomp)
72 {
73 return E_INVALIDARG;
74 }
75
76 typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)(
77 IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice);
78 PFN_DCOMPOSITION_CREATE_DEVICE createDComp =
79 reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>(
80 GetProcAddress(dcomp, "DCompositionCreateDevice"));
81 if (!createDComp)
82 {
83 return E_INVALIDARG;
84 }
85
86 if (!mDevice)
87 {
88 IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject<IDXGIDevice>(device);
89 HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice),
90 reinterpret_cast<void **>(&mDevice));
91 SafeRelease(dxgiDevice);
92
93 if (FAILED(result))
94 {
95 return result;
96 }
97 }
98
99 if (!mCompositionTarget)
100 {
101 HRESULT result =
102 mDevice->CreateTargetForHwnd(getNativeWindow(), TRUE, &mCompositionTarget);
103 if (FAILED(result))
104 {
105 return result;
106 }
107 }
108
109 if (!mVisual)
110 {
111 HRESULT result = mDevice->CreateVisual(&mVisual);
112 if (FAILED(result))
113 {
114 return result;
115 }
116 }
117
118 IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
119 DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
120 swapChainDesc.Width = width;
121 swapChainDesc.Height = height;
122 swapChainDesc.Format = format;
123 swapChainDesc.Stereo = FALSE;
124 swapChainDesc.SampleDesc.Count = 1;
125 swapChainDesc.SampleDesc.Quality = 0;
126 swapChainDesc.BufferUsage =
127 DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT;
128 swapChainDesc.BufferCount = 2;
129 swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
130 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
131 swapChainDesc.AlphaMode =
132 mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
133 swapChainDesc.Flags = 0;
134 IDXGISwapChain1 *swapChain1 = nullptr;
135 HRESULT result =
136 factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
137 if (SUCCEEDED(result))
138 {
139 *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
140 }
141 mVisual->SetContent(swapChain1);
142 mCompositionTarget->SetRoot(mVisual);
143 SafeRelease(factory2);
144 return result;
145 }
146
147 // Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a
148 // DXGI_SWAP_EFFECT_SEQUENTIAL swap chain.
149 IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
150 if (factory2 != nullptr)
151 {
152 DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
153 swapChainDesc.Width = width;
154 swapChainDesc.Height = height;
155 swapChainDesc.Format = format;
156 swapChainDesc.Stereo = FALSE;
157 swapChainDesc.SampleDesc.Count = samples;
158 swapChainDesc.SampleDesc.Quality = 0;
159 swapChainDesc.BufferUsage =
160 DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
161 swapChainDesc.BufferCount = 1;
162 swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
163 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
164 swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
165 swapChainDesc.Flags = 0;
166 IDXGISwapChain1 *swapChain1 = nullptr;
167 HRESULT result = factory2->CreateSwapChainForHwnd(device, getNativeWindow(), &swapChainDesc,
168 nullptr, nullptr, &swapChain1);
169 if (SUCCEEDED(result))
170 {
171 factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_WINDOW_CHANGES);
172 *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
173 }
174 SafeRelease(factory2);
175 return result;
176 }
177
178 DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
179 swapChainDesc.BufferCount = 1;
180 swapChainDesc.BufferDesc.Format = format;
181 swapChainDesc.BufferDesc.Width = width;
182 swapChainDesc.BufferDesc.Height = height;
183 swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
184 swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
185 swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
186 swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
187 swapChainDesc.BufferUsage =
188 DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
189 swapChainDesc.Flags = 0;
190 swapChainDesc.OutputWindow = getNativeWindow();
191 swapChainDesc.SampleDesc.Count = samples;
192 swapChainDesc.SampleDesc.Quality = 0;
193 swapChainDesc.Windowed = TRUE;
194 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
195
196 HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain);
197 if (SUCCEEDED(result))
198 {
199 factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_WINDOW_CHANGES);
200 }
201 return result;
202 }
203
commitChange()204 void NativeWindow11Win32::commitChange()
205 {
206 if (mDevice)
207 {
208 mDevice->Commit();
209 }
210 }
211
212 // static
IsValidNativeWindow(EGLNativeWindowType window)213 bool NativeWindow11Win32::IsValidNativeWindow(EGLNativeWindowType window)
214 {
215 return IsWindow(window) == TRUE;
216 }
217 } // namespace rx
218