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