问题描述
我正在尝试在Windows UWP应用中创建EGLSurface。创建代码位于xaml.cpp文件中,如下所示。
当我尝试使用可选属性EglrenderResolutionScaleProperty创建曲面时,该曲面失败,并出现EGL_BAD_ALLOC错误。可以使用两种替代方法,但是我需要尝试为我的应用程序使用分辨率比例选项。
void MyClass::CreateRenderSurface()
{
if (mRenderSurface == EGL_NO_SURFACE)
{
// NOTE: in practice,I only have one of the three following implementations in the code;
// all are included together here for ease of comparison.
// 1. This works
mRenderSurface = CreateSurface(mSwapChainPanel,nullptr,nullptr);
// 2. and this works (here I hardwired the size to twice the
// the size of the window I happen to be using,because
// Windows display settings is set at 200%)
Size size;
size.Height = 1448; // hardwired value for testing,in this case window height is 724 pix
size.Width = 1908; // hardwired value for testing,in this case window width is 954 pix
mRenderSurface = CreateSurface(mSwapChainPanel,&size,nullptr);
// 3. but this fails (and this is the one I want to use)
float resolutionScale = 1.0;
mRenderSurface = CreateSurface(mSwapChainPanel,&resolutionScale);
}
}
EGLSurface MyClass::CreateSurface(SwapChainPanel^ panel,const Size* renderSurfaceSize,const float* resolutionScale)
{
if (!panel)
{
throw Exception::CreateException(E_INVALIDARG,L"SwapChainPanel parameter is invalid");
}
if (renderSurfaceSize != nullptr && resolutionScale != nullptr)
{
throw Exception::CreateException(E_INVALIDARG,L"A size and a scale can't both be specified");
}
EGL _egl = this->HelperClass->GetEGL();
EGLSurface surface = EGL_NO_SURFACE;
const EGLint surfaceAttributes[] =
{
EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER,EGL_TRUE,EGL_NONE
};
// Create a PropertySet and initialize with the EGLNativeWindowType.
PropertySet^ surfaceCreationProperties = ref new PropertySet();
surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty),panel);
// If a render surface size is specified,add it to the surface creation properties
if (renderSurfaceSize != nullptr)
{
surfaceCreationProperties->Insert(ref new String(EglrenderSurfaceSizeProperty),PropertyValue::CreateSize(*renderSurfaceSize));
}
// If a resolution scale is specified,add it to the surface creation properties
if (resolutionScale != nullptr)
{
surfaceCreationProperties->Insert(ref new String(EglrenderResolutionScaleProperty),PropertyValue::CreateSingle(*resolutionScale));
}
surface = eglCreateWindowSurface(_egl._display,_egl._config,reinterpret_cast<IInspectable*>(surfaceCreationProperties),surfaceAttributes);
EGLint err = eglGetError();
if (surface == EGL_NO_SURFACE)
{
throw Exception::CreateException(E_FAIL,L"Failed to create EGL surface");
}
return surface;
}
其中
const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
const wchar_t EglrenderSurfaceSizeProperty[] = L"EglrenderSurfaceSizeProperty";
const wchar_t EglrenderResolutionScaleProperty[] = L"EglrenderResolutionScaleProperty";
我尝试更改EGLNativeWindowType参数的类型转换(如How to create EGLSurface using C++/WinRT and ANGLE?中的方法)-这样只会造成其他问题。如前所述,该代码确实可以在基本情况下创建曲面,而在使用EglrenderResolutionScaleProperty时则无效。
我的猜测是,我提供该属性的方式失败了,因为它在合理的值(例如1.0)上失败了。
解决方法
通过首先检查swapChainPanel大小不为零来解决此问题:
void MyClass::CreateRenderSurface()
{
if (mRenderSurface == EGL_NO_SURFACE)
{
if (0 == mSwapChainPanel->ActualHeight || 0 == mSwapChainPanel->ActualWidth)
{
mRenderSurface = CreateSurface(mSwapChainPanel,nullptr,&resolutionScale);
}
}
}
(代码检查其他地方是否已创建渲染表面,并在需要时再次调用它。)
有趣的是,将nullptr用作大小和分辨率参数的原始代码(上面原始代码段的情况1)不需要该检查。