1 //
2 // Copyright 2014 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 // InspectableNativeWindow.h: Host specific implementation interface for
8 // managing IInspectable native window types.
9 
10 #ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
11 #define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
12 
13 #include "common/debug.h"
14 #include "common/platform.h"
15 
16 #include "angle_windowsstore.h"
17 
18 #include <EGL/eglplatform.h>
19 
20 #include <windows.applicationmodel.core.h>
21 #undef GetCurrentTime
22 #include <windows.ui.xaml.h>
23 #include <windows.ui.xaml.media.dxinterop.h>
24 #include <wrl.h>
25 #include <wrl/wrappers/corewrappers.h>
26 
27 using namespace Microsoft::WRL;
28 using namespace Microsoft::WRL::Wrappers;
29 using namespace ABI::Windows::Foundation;
30 using namespace ABI::Windows::Foundation::Collections;
31 
32 namespace rx
33 {
34 class InspectableNativeWindow
35 {
36   public:
InspectableNativeWindow()37     InspectableNativeWindow()
38         : mSupportsSwapChainResize(true),
39           mSwapChainSizeSpecified(false),
40           mSwapChainScaleSpecified(false),
41           mSwapChainScale(1.0f),
42           mClientRectChanged(false),
43           mClientRect({0, 0, 0, 0}),
44           mNewClientRect({0, 0, 0, 0})
45     {
46         mSizeChangedEventToken.value = 0;
47     }
~InspectableNativeWindow()48     virtual ~InspectableNativeWindow() {}
49 
50     virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0;
51     virtual HRESULT createSwapChain(ID3D11Device *device,
52                                     IDXGIFactory2 *factory,
53                                     DXGI_FORMAT format,
54                                     unsigned int width,
55                                     unsigned int height,
56                                     bool containsAlpha,
57                                     IDXGISwapChain1 **swapChain)                   = 0;
58 
getClientRect(RECT * rect)59     bool getClientRect(RECT *rect)
60     {
61         if (mClientRectChanged)
62         {
63             mClientRect = mNewClientRect;
64         }
65 
66         *rect = mClientRect;
67 
68         return true;
69     }
70 
71     // setNewClientSize is used by the WinRT size change handler. It isn't used by the rest of
72     // ANGLE.
setNewClientSize(const Size & newWindowSize)73     void setNewClientSize(const Size &newWindowSize)
74     {
75         // If the client doesn't support swapchain resizing then we should have already unregistered
76         // from size change handler
77         ASSERT(mSupportsSwapChainResize);
78 
79         if (mSupportsSwapChainResize)
80         {
81             // If the swapchain size was specified then we should ignore this call too
82             if (!mSwapChainSizeSpecified)
83             {
84                 mNewClientRect     = clientRect(newWindowSize);
85                 mClientRectChanged = true;
86 
87                 // If a scale was specified, then now is the time to apply the scale matrix for the
88                 // new swapchain size and window size
89                 if (mSwapChainScaleSpecified)
90                 {
91                     scaleSwapChain(newWindowSize, mNewClientRect);
92                 }
93             }
94 
95             // Even if the swapchain size was fixed, the window might have changed size.
96             // In this case, we should recalculate the scale matrix to account for the new window
97             // size
98             if (mSwapChainSizeSpecified)
99             {
100                 scaleSwapChain(newWindowSize, mClientRect);
101             }
102         }
103     }
104 
105   protected:
106     virtual HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) = 0;
107     RECT clientRect(const Size &size);
108 
109     bool mSupportsSwapChainResize;  // Support for IDXGISwapChain::ResizeBuffers method
110     bool mSwapChainSizeSpecified;   // If an EGLRenderSurfaceSizeProperty was specified
111     bool mSwapChainScaleSpecified;  // If an EGLRenderResolutionScaleProperty was specified
112     float mSwapChainScale;  // The scale value specified by the EGLRenderResolutionScaleProperty
113                             // property
114     RECT mClientRect;
115     RECT mNewClientRect;
116     bool mClientRectChanged;
117 
118     EventRegistrationToken mSizeChangedEventToken;
119 };
120 
121 bool IsCoreWindow(EGLNativeWindowType window,
122                   ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr);
123 bool IsSwapChainPanel(
124     EGLNativeWindowType window,
125     ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr);
126 bool IsEGLConfiguredPropertySet(
127     EGLNativeWindowType window,
128     ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr,
129     IInspectable **inspectable                                        = nullptr);
130 
131 HRESULT GetOptionalPropertyValue(
132     const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> &propertyMap,
133     const wchar_t *propertyName,
134     boolean *hasKey,
135     ComPtr<ABI::Windows::Foundation::IPropertyValue> &propertyValue);
136 
137 HRESULT GetOptionalSizePropertyValue(
138     const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> &propertyMap,
139     const wchar_t *propertyName,
140     SIZE *value,
141     bool *valueExists);
142 
143 HRESULT GetOptionalSinglePropertyValue(
144     const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> &propertyMap,
145     const wchar_t *propertyName,
146     float *value,
147     bool *valueExists);
148 }  // namespace rx
149 
150 #endif  // LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
151