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