0

I'm trying to create an EGLSurface in a Windows UWP app. The creation code is in a xaml.cpp file, as shown below.

When I try creating the surface using the optional property EGLRenderResolutionScaleProperty, it fails with an EGL_BAD_ALLOC error. Two alternate approaches work, but I need to try to use the resolution scale option for my app.

    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, nullptr, &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;
    }
    

where

const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty";
const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty";
const wchar_t EGLRenderResolutionScaleProperty[] = L"EGLRenderResolutionScaleProperty";

I have tried changing the cast of the EGLNativeWindowType argument (as in How to create EGLSurface using C++/WinRT and ANGLE?) - that only creates other problems. As indicated, this code does work to create a surface in the basic case, just not when using the EGLRenderResolutionScaleProperty.

My guess is that something about the way I'm supplying that property is failing, because it fails on what should be reasonable values (e.g., 1.0).

bphi
  • 1,015
  • 6
  • 16

1 Answers1

0

Solved this by first checking that swapChainPanel size is not zero:

void MyClass::CreateRenderSurface()
{
    if (mRenderSurface == EGL_NO_SURFACE)
    {
        if (0 == mSwapChainPanel->ActualHeight || 0 == mSwapChainPanel->ActualWidth)
        {
            mRenderSurface = CreateSurface(mSwapChainPanel, nullptr, &resolutionScale);
        }
    }
}

(The code checks elsewhere whether the render surface has been created, and will call this again if needed.)

Interestingly, the original code that used nullptr for both size and resolution arguments (case 1 in original snippet above) didn't need that check.

bphi
  • 1,015
  • 6
  • 16