2015-12-23 6 views
4

Я заинтересован в создании приложения OpenGL, которое не зависит от X11. Как я видел, это должно быть возможно через EGL. В Интернете есть даже примеры. Но как я могу контролировать контекстную версию? Пример кода ниже создает контекст OpenGL (на wayland) с версией 2.1, но на моем компьютере он показывает, что самая высокая версия OpenGL поддерживается 3,3 (такой контекст может быть создан с помощью glXCreateContextAttribsARB с использованием GLX и xlib на X-сервере). Поэтому мой вопрос: могу ли я каким-то образом создать контекст OpenGL с более высокой версией через EGL, и если да, то как?Как создать контекст OpenGL 3.3 или 4.x через 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

+0

Является ли EGL лимит в 3,3, или в его документации говорится, что он поддерживает любую версию? – Xirema

+0

Я никогда не видел такого ограничения, но я не мог найти никакой функции или параметра, чтобы позволить мне управлять версией созданного контекста OpenGL. Однако такие варианты существуют для OpenGL ES. Именно это заставило меня подумать, что для OpenGL тоже может быть вариант. – thefunkyjunky

ответ

8

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 аналогов для классического рабочего стола GL API привязки. Эта функциональность также была добавлена ​​в ядро ​​EGL version 1.5.

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

  • EGL_CONTEXT_MAJOR_VERSION, EGL_CONTEXT_MINOR_VERSION
  • EGL_CONTEXT_FLAGS
  • EGL_CONTEXT_OPENGL_PROFILE_MASK

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