如何使用 C++/WinRT 和 ANGLE 创建 EGLSurface?

How to create EGLSurface using C++/WinRT and ANGLE?

我正在使用 Microsoft branch of the ANGLE project 在通用 Windows 应用程序中访问 OpenGL。 此外,我使用 C++/WinRT binding 尽可能多地使用标准 C++ 进行编码。

我从 ANGLE 项目中的一个示例开始,尝试将 C++/CX 代码转换为 C++/WinRT 代码,但我未能找到创建 EGL Surface 的部分的解决方案:

mEGLSurface = eglCreateWindowSurface(mEGLDisplay, config, /*WHERE IS MY HWND?*/, NULL);

在 C++/CX 中,他们使用以下代码,但我必须承认,我不明白他们如何从带有 CoreWindow 的 PropertySet 到 EGLNativeWindowType(在本例中为 HWND)以及如何将其转换为C++/WinRT 代码:

PropertySet^ surfaceCreationProperties = ref new PropertySet();
surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), window);

mEglSurface = eglCreateWindowSurface(mEglDisplay, config, reinterpret_cast<IInspectable*>(surfaceCreationProperties), surfaceAttributes);

编辑:当天真地将代码转换为 C++/WinRT 约定时,reinterpret_cast 给出了 'invalid cast' 错误(从 IInspectable 到 EGLNativeWindowType)。

编辑:为了完整起见,window 参数是 Windows::UI::Core::CoreWindow.

编辑:实际上 对类似问题的回答提供了很多有用的信息,我会进一步调查。

编辑:阅读之前编辑中链接的答案并查看 ANGLE 源代码中的正确位置后,我发现我的困惑是由特定于 Windows 的实现细节引起的角度的一侧。该函数并不需要传统意义上的 HWND 句柄,而更像是伪装成 HWND 的设置字典。 另外 reinterpret_cast 错误是由于我试图将对象转换为指针,愚蠢的我..

EGLNativeWindowType在ANGLE中定义如下:

#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) /* Windows Desktop */
typedef HWND    EGLNativeWindowType;
#else /* Windows Store */
#include <inspectable.h>
typedef IInspectable* EGLNativeWindowType;
#endif

因此,在通用 Windows 应用程序中使用 C++/WinRT 类型时,我必须注意不要将这些类型与其他代码使用的 C++/CX 类型混合。

我试图将 PropertySet 指针(使用 UWP 时该函数的实现所期望的)转换为 winrt::Windows::Foundation::IInspectable 指针。这不是 ANGLE 实现所期望的 C++/CX IInspectable 类型。所以我不得不直接转换为 EGLNativeWindowType:

PropertySet surfaceProperties;
surfaceProperties.Insert(EGLNativeWindowTypeProperty, window);
EGLNativeWindowType win = reinterpret_cast<EGLNativeWindowType>(&surfaceProperties);

mEGLSurface = eglCreateWindowSurface(mEGLDisplay, config, win, surfaceAttributes);

这是在 UWP 环境中尝试使用标准 C++ 时的注意事项之一。请参阅有关使用 C++/CX 代码共享 C++/WinRT 的答案:

还有一个问题是 winrt' PropertySet 与 cx' PropertySet 不兼容。

这对我有用:

PropertySet surfaceCreationProperties;
surfaceCreationProperties.Insert(EGLNativeWindowTypeProperty, panel);
EGLNativeWindowType win = static_cast<EGLNativeWindowType>(winrt::get_abi(surfaceCreationProperties));
surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, win, surfaceAttributes);