Как создать контекст OpenGL 3.3 или 4.x через EGL

Я заинтересован в создании приложения OpenGL, которое не зависит от X11. Как я видел, это должно быть возможно через EGL. Примеры есть даже в инете. Но как я могу контролировать контекстную версию? Приведенный ниже пример кода создает контекст OpenGL (на пути) с версией 2.1, но на моем компьютере он показывает, что самая высокая поддерживаемая версия OpenGL — 3.3 (такой контекст можно создать с помощью glXCreateContextAttribsARB с использованием GLX и xlib на X-сервере). Итак, мой вопрос: могу ли я каким-то образом создать контекст OpenGL с более высокой версией через EGL, и если да, то как?

Пример кода:

#include <wayland-client.h>
#include <wayland-egl.h>
#include <EGL/egl.h>
#include <GL/gl.h>
#include <string.h>
#include <stdio.h>

#define WIDTH 256
#define HEIGHT 256

static struct wl_display *display;
static struct wl_compositor *compositor = NULL;
static struct wl_shell *shell = NULL;
static EGLDisplay egl_display;
static char running = 1;

struct window {
    EGLContext egl_context;
    struct wl_surface *surface;
    struct wl_shell_surface *shell_surface;
    struct wl_egl_window *egl_window;
    EGLSurface egl_surface;
};

// listeners
static void registry_add_object (void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) {
    if (!strcmp(interface,"wl_compositor")) {
        compositor = wl_registry_bind (registry, name, &wl_compositor_interface, 0);
    }
    else if (!strcmp(interface,"wl_shell")) {
        shell = wl_registry_bind (registry, name, &wl_shell_interface, 0);
    }
}
static void registry_remove_object (void *data, struct wl_registry *registry, uint32_t name) {

}
static struct wl_registry_listener registry_listener = {&registry_add_object, &registry_remove_object};

static void shell_surface_ping (void *data, struct wl_shell_surface *shell_surface, uint32_t serial) {
    wl_shell_surface_pong (shell_surface, serial);
}
static void shell_surface_configure (void *data, struct wl_shell_surface *shell_surface, uint32_t edges, int32_t width, int32_t height) {
    struct window *window = data;
    wl_egl_window_resize (window->egl_window, width, height, 0, 0);
}
static void shell_surface_popup_done (void *data, struct wl_shell_surface *shell_surface) {

}
static struct wl_shell_surface_listener shell_surface_listener = {&shell_surface_ping, &shell_surface_configure, &shell_surface_popup_done};

static void create_window (struct window *window, int32_t width, int32_t height) {
    eglBindAPI (EGL_OPENGL_API);
    EGLint attributes[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
    EGL_NONE};
    EGLConfig config;
    EGLint num_config;
    eglChooseConfig (egl_display, attributes, &config, 1, &num_config);
    window->egl_context = eglCreateContext (egl_display, config, EGL_NO_CONTEXT, NULL);

    window->surface = wl_compositor_create_surface (compositor);
    window->shell_surface = wl_shell_get_shell_surface (shell, window->surface);
    wl_shell_surface_add_listener (window->shell_surface, &shell_surface_listener, window);
    wl_shell_surface_set_toplevel (window->shell_surface);
    window->egl_window = wl_egl_window_create (window->surface, width, height);
    window->egl_surface = eglCreateWindowSurface (egl_display, config, window->egl_window, NULL);
    eglMakeCurrent (egl_display, window->egl_surface, window->egl_surface, window->egl_context);
}
static void delete_window (struct window *window) {
    eglDestroySurface (egl_display, window->egl_surface);
    wl_egl_window_destroy (window->egl_window);
    wl_shell_surface_destroy (window->shell_surface);
    wl_surface_destroy (window->surface);
    eglDestroyContext (egl_display, window->egl_context);
}
static void draw_window (struct window *window) {
    glClearColor (0.0, 1.0, 0.0, 1.0);
    glClear (GL_COLOR_BUFFER_BIT);

    printf("%s\n", glGetString(GL_VERSION));

    eglSwapBuffers (egl_display, window->egl_surface);
}

int main () {
    display = wl_display_connect (NULL);
    struct wl_registry *registry = wl_display_get_registry (display);
    wl_registry_add_listener (registry, &registry_listener, NULL);
    wl_display_dispatch (display);

    egl_display = eglGetDisplay (display);
    eglInitialize (egl_display, NULL, NULL);

    struct window window;
    create_window (&window, WIDTH, HEIGHT);

    while (running) {
        wl_display_dispatch_pending (display);
        draw_window (&window);
    }

    delete_window (&window);
    eglTerminate (egl_display);
    wl_display_disconnect (display);
    return 0;
}

Источник: https://github.com/eyelash/tutorials


person thefunkyjunky    schedule 23.12.2015    source источник
comment
Накладывает ли EGL ограничение на 3.3 или в его документации указано, что он будет поддерживать любую версию?   -  person Xirema    schedule 23.12.2015
comment
Я никогда не видел такого ограничения, но я не смог найти ни одной функции или параметра, позволяющих мне контролировать версию созданного контекста OpenGL. Однако такие опции существуют для OpenGL ES. Вот что заставило меня подумать, что для OpenGL тоже может быть вариант.   -  person thefunkyjunky    schedule 23.12.2015


Ответы (1)


EGL изначально разрабатывался только для OpenGL ES. Поддержка настольного OpenGL была добавлена ​​​​в EGL 1.4 (выпущена в 2008 г.). Однако в то время еще не существовало различия между «устаревшими» контекстами GL, контекстами с прямой совместимостью и профилями OpenGL, такими как ядро ​​и совместимость, поэтому EGL 1.4 не включает средства для запроса любого из них. Единственное, на что вы можете положиться, это то, что вы получаете контекст GL, совместимый с «устаревшим» GL 1.x/2.x. Это не означает, что он также не может создать профиль совместимости более высокой версии — вы просто не можете на это полагаться и не можете его контролировать.

Возможность запросить контекст GL, совместимый с конкретной версией, или реализовать определенный профиль, впервые была предоставлена ​​файлом EGL_KHR_create_context расширение EGL в 2012 году, функционально очень похожее на WGL/glX аналоги для классические API привязки GL для настольных компьютеров. Эта функциональность также была добавлена ​​в ядро ​​EGL версии 1.5.

Это означает, что вам нужна реализация, поддерживающая EGL 1.5 или 1.4 с этим расширением, чтобы иметь возможность надежно создавать современные контексты OpenGL контролируемым образом, указав

  • EGL_CONTEXT_MAJOR_VERSION, EGL_CONTEXT_MINOR_VERSION
  • EGL_CONTEXT_FLAGS
  • EGL_CONTEXT_OPENGL_PROFILE_MASK

атрибуты (или их эквиваленты расширения с суффиксом _KHR, которые в конечном итоге имеют те же значения - последние просто определены в elgext.h, а основные версии находятся в egl.h для версии 1.5) при создании контекста.

person derhass    schedule 23.12.2015