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.cpp: NativeWindow base class for managing IInspectable native window
8 // types.
9 
10 #include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
11 #include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
12 
13 namespace rx
14 {
15 
IsCoreWindow(EGLNativeWindowType window,ComPtr<ABI::Windows::UI::Core::ICoreWindow> * coreWindow)16 bool IsCoreWindow(EGLNativeWindowType window,
17                   ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow)
18 {
19     if (!window)
20     {
21         return false;
22     }
23 
24     ComPtr<IInspectable> win = reinterpret_cast<IInspectable *>(window);
25     ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin;
26     if (SUCCEEDED(win.As(&coreWin)))
27     {
28         if (coreWindow != nullptr)
29         {
30             *coreWindow = coreWin;
31         }
32         return true;
33     }
34 
35     return false;
36 }
37 
IsSwapChainPanel(EGLNativeWindowType window,ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> * swapChainPanel)38 bool IsSwapChainPanel(EGLNativeWindowType window,
39                       ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel)
40 {
41     if (!window)
42     {
43         return false;
44     }
45 
46     ComPtr<IInspectable> win = window;
47     ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel;
48     if (SUCCEEDED(win.As(&panel)))
49     {
50         if (swapChainPanel != nullptr)
51         {
52             *swapChainPanel = panel;
53         }
54         return true;
55     }
56 
57     return false;
58 }
59 
IsEGLConfiguredPropertySet(EGLNativeWindowType window,ABI::Windows::Foundation::Collections::IPropertySet ** propertySet,IInspectable ** eglNativeWindow)60 bool IsEGLConfiguredPropertySet(EGLNativeWindowType window,
61                                 ABI::Windows::Foundation::Collections::IPropertySet **propertySet,
62                                 IInspectable **eglNativeWindow)
63 {
64     if (!window)
65     {
66         return false;
67     }
68 
69     ComPtr<IInspectable> props = window;
70     ComPtr<IPropertySet> propSet;
71     ComPtr<IInspectable> nativeWindow;
72     ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> propMap;
73     boolean hasEglNativeWindowPropertyKey = false;
74 
75     HRESULT result = props.As(&propSet);
76     if (SUCCEEDED(result))
77     {
78         result = propSet.As(&propMap);
79     }
80 
81     // Look for the presence of the EGLNativeWindowType in the property set
82     if (SUCCEEDED(result))
83     {
84         result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(),
85                                  &hasEglNativeWindowPropertyKey);
86     }
87 
88     // If the IPropertySet does not contain the required EglNativeWindowType key, the property set
89     // is considered invalid.
90     if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey)
91     {
92         ERR() << "Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid "
93                  "EGLNativeWindowTypeProperty values include ICoreWindow";
94         return false;
95     }
96 
97     // The EglNativeWindowType property exists, so retreive the IInspectable that represents the
98     // EGLNativeWindowType
99     if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey)
100     {
101         result =
102             propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow);
103     }
104 
105     if (SUCCEEDED(result))
106     {
107         if (propertySet != nullptr)
108         {
109             result = propSet.CopyTo(propertySet);
110         }
111     }
112 
113     if (SUCCEEDED(result))
114     {
115         if (eglNativeWindow != nullptr)
116         {
117             result = nativeWindow.CopyTo(eglNativeWindow);
118         }
119     }
120 
121     if (SUCCEEDED(result))
122     {
123         return true;
124     }
125 
126     return false;
127 }
128 
129 // Retrieve an optional property from a property set
GetOptionalPropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING,IInspectable * >> & propertyMap,const wchar_t * propertyName,boolean * hasKey,ComPtr<ABI::Windows::Foundation::IPropertyValue> & propertyValue)130 HRESULT GetOptionalPropertyValue(
131     const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> &propertyMap,
132     const wchar_t *propertyName,
133     boolean *hasKey,
134     ComPtr<ABI::Windows::Foundation::IPropertyValue> &propertyValue)
135 {
136     if (!propertyMap || !hasKey)
137     {
138         return E_INVALIDARG;
139     }
140 
141     // Assume that the value does not exist
142     *hasKey = false;
143 
144     HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), hasKey);
145     if (SUCCEEDED(result) && !(*hasKey))
146     {
147         // Value does not exist, so return S_OK and set the exists parameter to false to indicate
148         // that a the optional property does not exist.
149         return S_OK;
150     }
151 
152     if (SUCCEEDED(result))
153     {
154         result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue);
155     }
156 
157     return result;
158 }
159 
160 // Attempts to read an optional SIZE property value that is assumed to be in the form of
161 // an ABI::Windows::Foundation::Size.  This function validates the Size value before returning
162 // it to the caller.
163 //
164 // Possible return values are:
165 // S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated
166 // S_OK, valueExists == false - optional SIZE value was not found
167 // E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set.
168 //    * Incorrect property type ( must be PropertyType_Size)
169 //    * Invalid property value (width/height must be > 0)
170 // Additional errors may be returned from IMap or IPropertyValue
171 //
GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING,IInspectable * >> & propertyMap,const wchar_t * propertyName,SIZE * value,bool * valueExists)172 HRESULT GetOptionalSizePropertyValue(
173     const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> &propertyMap,
174     const wchar_t *propertyName,
175     SIZE *value,
176     bool *valueExists)
177 {
178     ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
179     ABI::Windows::Foundation::PropertyType propertyType =
180         ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
181     Size sizeValue = {0, 0};
182     boolean hasKey = false;
183 
184     if (!propertyMap || !value || !valueExists)
185     {
186         return E_INVALIDARG;
187     }
188 
189     // Assume that the value does not exist
190     *valueExists = false;
191     *value       = {0, 0};
192 
193     HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue);
194     if (SUCCEEDED(result) && hasKey)
195     {
196         result = propertyValue->get_Type(&propertyType);
197 
198         // Check if the expected Size property is of PropertyType_Size type.
199         if (SUCCEEDED(result) &&
200             propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size)
201         {
202             if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) &&
203                 (sizeValue.Width > 0 && sizeValue.Height > 0))
204             {
205                 // A valid property value exists
206                 *value = {static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height)};
207                 *valueExists = true;
208                 result       = S_OK;
209             }
210             else
211             {
212                 // An invalid Size property was detected. Width/Height values must > 0
213                 result = E_INVALIDARG;
214             }
215         }
216         else
217         {
218             // An invalid property type was detected. Size property must be of PropertyType_Size
219             result = E_INVALIDARG;
220         }
221     }
222 
223     return result;
224 }
225 
226 // Attempts to read an optional float property value that is assumed to be in the form of
227 // an ABI::Windows::Foundation::Single.  This function validates the Single value before returning
228 // it to the caller.
229 //
230 // Possible return values are:
231 // S_OK, valueExists == true - optional Single value was successfully retrieved and validated
232 // S_OK, valueExists == false - optional Single value was not found
233 // E_INVALIDARG, valueExists = false - optional Single value was malformed in the property set.
234 //    * Incorrect property type ( must be PropertyType_Single)
235 //    * Invalid property value (must be > 0)
236 // Additional errors may be returned from IMap or IPropertyValue
237 //
GetOptionalSinglePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING,IInspectable * >> & propertyMap,const wchar_t * propertyName,float * value,bool * valueExists)238 HRESULT GetOptionalSinglePropertyValue(
239     const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> &propertyMap,
240     const wchar_t *propertyName,
241     float *value,
242     bool *valueExists)
243 {
244     ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
245     ABI::Windows::Foundation::PropertyType propertyType =
246         ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
247     float scaleValue = 0.0f;
248     boolean hasKey   = false;
249 
250     if (!propertyMap || !value || !valueExists)
251     {
252         return E_INVALIDARG;
253     }
254 
255     // Assume that the value does not exist
256     *valueExists = false;
257     *value       = 0.0f;
258 
259     HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue);
260     if (SUCCEEDED(result) && hasKey)
261     {
262         result = propertyValue->get_Type(&propertyType);
263 
264         // Check if the expected Scale property is of PropertyType_Single type.
265         if (SUCCEEDED(result) &&
266             propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Single)
267         {
268             if (SUCCEEDED(propertyValue->GetSingle(&scaleValue)) && (scaleValue > 0.0f))
269             {
270                 // A valid property value exists
271                 *value       = scaleValue;
272                 *valueExists = true;
273                 result       = S_OK;
274             }
275             else
276             {
277                 // An invalid scale was set
278                 result = E_INVALIDARG;
279             }
280         }
281         else
282         {
283             // An invalid property type was detected. Size property must be of PropertyType_Single
284             result = E_INVALIDARG;
285         }
286     }
287 
288     return result;
289 }
290 
clientRect(const Size & size)291 RECT InspectableNativeWindow::clientRect(const Size &size)
292 {
293     // We don't have to check if a swapchain scale was specified here; the default value is 1.0f
294     // which will have no effect.
295     return {0, 0, lround(size.Width * mSwapChainScale), lround(size.Height * mSwapChainScale)};
296 }
297 }  // namespace rx
298