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