无法在Windows上使用RenderResolutionScale属性创建EGLSurface

问题描述

我正在尝试在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)不需要该检查。