OpenGL (УГОЛ) + XAML (UWP) - PullRequest
       93

OpenGL (УГОЛ) + XAML (UWP)

0 голосов
/ 24 июня 2019

Я пытаюсь запустить код OpenGL в приложении UWP XAML.Я нашел некоторую информацию об этом, но, похоже, нет ничего лучше, чем полное прохождение.Я полностью новичок в UPW, XAML и EGL, поэтому мне удалось создать следующий код из различных учебных пособий:

#include <Windows.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include <angle_windowsstore.h>

using namespace Windows::UI::Core;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Platform;
using Windows::ApplicationModel::SuspendingEventArgs;
using Windows::ApplicationModel::Activation::LaunchActivatedEventArgs;
using Windows::Foundation::Collections::PropertySet;
using Windows::Foundation::EventHandler;

static EGLint const openGlAttributes[] = {
    EGL_RED_SIZE, 1,
    EGL_GREEN_SIZE, 1,
    EGL_BLUE_SIZE, 1,
    EGL_NONE
};

ref class MyApp sealed : Application {
private:
    SwapChainPanel^ swapChainPanel;
    CoreWindow^ coreWindow;
    EGLDisplay display;
    EGLSurface surface;
    bool stopped;

public:
    MyApp() {
        stopped = false;
    }

    virtual void OnLaunched(LaunchActivatedEventArgs^ e) override {
        auto canvas = ref new Canvas();

        auto swapChainPanel = ref new SwapChainPanel();
        swapChainPanel->Width = 800;
        swapChainPanel->Width = 600;
        canvas->Children->Append(swapChainPanel);
        canvas->SetLeft(swapChainPanel, 0);
        canvas->SetTop(swapChainPanel, 0);


        Window::Current->Content = canvas;
        Window::Current->Activate();

        coreWindow = Window::Current->CoreWindow;
        InitGL(Window::Current);

        WeakReference selfRef(this);
        Suspending += ref new SuspendingEventHandler([selfRef](Object^ sender, SuspendingEventArgs^ args) {
            auto self = selfRef.Resolve<MyApp>();
            self->stopped = true;
        });
        Resuming += ref new EventHandler<Object^>([selfRef](Object^ sender, Object^ args) {
            auto self = selfRef.Resolve<MyApp>();
            self->stopped = false;
        });

        ScheduleRendering();
    }

private:

    void InitGL(Window^ window) {
        display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        eglInitialize(display, NULL, NULL);

        EGLConfig config;
        EGLint numConfig;
        eglChooseConfig(display, openGlAttributes, &config, 1, &numConfig);

        auto surfaceCreationProperties = ref new PropertySet();
        surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), swapChainPanel);

        auto context = eglCreateContext(display, config, EGL_NO_CONTEXT, NULL);
        surface = eglCreateWindowSurface(display, config, reinterpret_cast<EGLNativeWindowType>(surfaceCreationProperties), NULL);
        eglMakeCurrent(display, surface, surface, context);
    }

    void RenderScene() {
        glClearColor(1.0, 0, 0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
        glFlush();

        eglSwapBuffers(display, surface);

        ScheduleRendering();
    }

    void ScheduleRendering() {
        if (stopped) {
            return;
        }
        WeakReference selfRef(this);
        coreWindow->Dispatcher->RunIdleAsync(ref new IdleDispatchedHandler([selfRef](IdleDispatchedHandlerArgs^ args) {
            auto self = selfRef.Resolve<MyApp>();
            self->RenderScene();
        }));
    }
};

int main(Array<String^>^ args) {
    Application::Start(ref new ApplicationInitializationCallback([](ApplicationInitializationCallbackParams^ p) {
        ref new MyApp();
    }));
    return 0;
}

Однако, он просто не работает.По крайней мере, этот код не падает.Затем я проверил InitGL в отладчике, и все вызовы EGL завершаются нормально.

В некоторых вещах я не уверен:

  1. Должен ли я инициализировать SwapChainPanel в соответствии с этимguide , или ANGLE делает это для меня?
  2. Должен ли я выполнять рендеринг в режиме ожидания, или есть что-то вроде события Paint?

1 Ответ

0 голосов
/ 27 июня 2019

Похоже, я ошибался, когда писал, что все правильно инициализируется. Этот звонок вернулся EGL_NO_SOURCE:

eglMakeCurrent(display, surface, surface, context);

Я полагаю, это из-за того, что мы должны ждать, когда SwapChainPanel инициализируется, поэтому, когда я позвонил eglMakeCurrent из Load события swapChainPanel, все начало работать. Кроме того, есть несколько вещей, которые неочевидны, например, swapChainPanel может неожиданно потерять контекст GL, и, следовательно, вам придется воссоздать его, когда что-то пойдет не так. Я нашел этот шаблон в форке Microsoft ANGLE и использовал его как источник вдохновения.

...