blob: 592a389f9ec874de17e93d30a59ab22521a3647c [file] [log] [blame]
//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window
// types.
#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
namespace rx
{
bool IsCoreWindow(EGLNativeWindowType window,
ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow)
{
if (!window)
{
return false;
}
ComPtr<IInspectable> win = static_cast<IInspectable *>(window);
ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWin;
if (SUCCEEDED(win.As(&coreWin)))
{
if (coreWindow != nullptr)
{
*coreWindow = coreWin;
}
return true;
}
return false;
}
bool IsSwapChainPanel(EGLNativeWindowType window,
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel)
{
if (!window)
{
return false;
}
ComPtr<IInspectable> win = static_cast<IInspectable *>(window);
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> panel;
if (SUCCEEDED(win.As(&panel)))
{
if (swapChainPanel != nullptr)
{
*swapChainPanel = panel;
}
return true;
}
return false;
}
bool IsEGLConfiguredPropertySet(EGLNativeWindowType window,
ABI::Windows::Foundation::Collections::IPropertySet **propertySet,
IInspectable **eglNativeWindow)
{
if (!window)
{
return false;
}
ComPtr<IInspectable> props = static_cast<IInspectable *>(window);
ComPtr<IPropertySet> propSet;
ComPtr<IInspectable> nativeWindow;
ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> propMap;
boolean hasEglNativeWindowPropertyKey = false;
HRESULT result = props.As(&propSet);
if (SUCCEEDED(result))
{
result = propSet.As(&propMap);
}
// Look for the presence of the EGLNativeWindowType in the property set
if (SUCCEEDED(result))
{
result = propMap->HasKey(HStringReference(EGLNativeWindowTypeProperty).Get(),
&hasEglNativeWindowPropertyKey);
}
// If the IPropertySet does not contain the required EglNativeWindowType key, the property set
// is considered invalid.
if (SUCCEEDED(result) && !hasEglNativeWindowPropertyKey)
{
ERR() << "Could not find EGLNativeWindowTypeProperty in IPropertySet. Valid "
"EGLNativeWindowTypeProperty values include ICoreWindow";
return false;
}
// The EglNativeWindowType property exists, so retreive the IInspectable that represents the
// EGLNativeWindowType
if (SUCCEEDED(result) && hasEglNativeWindowPropertyKey)
{
result =
propMap->Lookup(HStringReference(EGLNativeWindowTypeProperty).Get(), &nativeWindow);
}
if (SUCCEEDED(result))
{
if (propertySet != nullptr)
{
result = propSet.CopyTo(propertySet);
}
}
if (SUCCEEDED(result))
{
if (eglNativeWindow != nullptr)
{
result = nativeWindow.CopyTo(eglNativeWindow);
}
}
if (SUCCEEDED(result))
{
return true;
}
return false;
}
// Retrieve an optional property from a property set
HRESULT GetOptionalPropertyValue(
const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> &propertyMap,
const wchar_t *propertyName,
boolean *hasKey,
ComPtr<ABI::Windows::Foundation::IPropertyValue> &propertyValue)
{
if (!propertyMap || !hasKey)
{
return E_INVALIDARG;
}
// Assume that the value does not exist
*hasKey = false;
HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), hasKey);
if (SUCCEEDED(result) && !(*hasKey))
{
// Value does not exist, so return S_OK and set the exists parameter to false to indicate
// that a the optional property does not exist.
return S_OK;
}
if (SUCCEEDED(result))
{
result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue);
}
return result;
}
// Attempts to read an optional SIZE property value that is assumed to be in the form of
// an ABI::Windows::Foundation::Size. This function validates the Size value before returning
// it to the caller.
//
// Possible return values are:
// S_OK, valueExists == true - optional SIZE value was successfully retrieved and validated
// S_OK, valueExists == false - optional SIZE value was not found
// E_INVALIDARG, valueExists = false - optional SIZE value was malformed in the property set.
// * Incorrect property type ( must be PropertyType_Size)
// * Invalid property value (width/height must be > 0)
// Additional errors may be returned from IMap or IPropertyValue
//
HRESULT GetOptionalSizePropertyValue(
const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> &propertyMap,
const wchar_t *propertyName,
SIZE *value,
bool *valueExists)
{
ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
ABI::Windows::Foundation::PropertyType propertyType =
ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
Size sizeValue = {0, 0};
boolean hasKey = false;
if (!propertyMap || !value || !valueExists)
{
return E_INVALIDARG;
}
// Assume that the value does not exist
*valueExists = false;
*value = {0, 0};
HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue);
if (SUCCEEDED(result) && hasKey)
{
result = propertyValue->get_Type(&propertyType);
// Check if the expected Size property is of PropertyType_Size type.
if (SUCCEEDED(result) &&
propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size)
{
if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) &&
(sizeValue.Width > 0 && sizeValue.Height > 0))
{
// A valid property value exists
*value = {static_cast<long>(sizeValue.Width), static_cast<long>(sizeValue.Height)};
*valueExists = true;
result = S_OK;
}
else
{
// An invalid Size property was detected. Width/Height values must > 0
result = E_INVALIDARG;
}
}
else
{
// An invalid property type was detected. Size property must be of PropertyType_Size
result = E_INVALIDARG;
}
}
return result;
}
// Attempts to read an optional float property value that is assumed to be in the form of
// an ABI::Windows::Foundation::Single. This function validates the Single value before returning
// it to the caller.
//
// Possible return values are:
// S_OK, valueExists == true - optional Single value was successfully retrieved and validated
// S_OK, valueExists == false - optional Single value was not found
// E_INVALIDARG, valueExists = false - optional Single value was malformed in the property set.
// * Incorrect property type ( must be PropertyType_Single)
// * Invalid property value (must be > 0)
// Additional errors may be returned from IMap or IPropertyValue
//
HRESULT GetOptionalSinglePropertyValue(
const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable *>> &propertyMap,
const wchar_t *propertyName,
float *value,
bool *valueExists)
{
ComPtr<ABI::Windows::Foundation::IPropertyValue> propertyValue;
ABI::Windows::Foundation::PropertyType propertyType =
ABI::Windows::Foundation::PropertyType::PropertyType_Empty;
float scaleValue = 0.0f;
boolean hasKey = false;
if (!propertyMap || !value || !valueExists)
{
return E_INVALIDARG;
}
// Assume that the value does not exist
*valueExists = false;
*value = 0.0f;
HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue);
if (SUCCEEDED(result) && hasKey)
{
result = propertyValue->get_Type(&propertyType);
// Check if the expected Scale property is of PropertyType_Single type.
if (SUCCEEDED(result) &&
propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Single)
{
if (SUCCEEDED(propertyValue->GetSingle(&scaleValue)) && (scaleValue > 0.0f))
{
// A valid property value exists
*value = scaleValue;
*valueExists = true;
result = S_OK;
}
else
{
// An invalid scale was set
result = E_INVALIDARG;
}
}
else
{
// An invalid property type was detected. Size property must be of PropertyType_Single
result = E_INVALIDARG;
}
}
return result;
}
RECT InspectableNativeWindow::clientRect(const Size &size)
{
// We don't have to check if a swapchain scale was specified here; the default value is 1.0f
// which will have no effect.
return {0, 0, lround(size.Width * mSwapChainScale), lround(size.Height * mSwapChainScale)};
}
} // namespace rx