example codes
// gcc -o eglwayland eglwayland.c `pkg-config --cflags --libs wayland-egl egl glesv2` #include <stdlib.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include <wayland-client.h> #include <wayland-server.h> #include <wayland-client-protocol.h> #include <wayland-egl.h> // Wayland EGL MUST be included before EGL headers #include <EGL/egl.h> #include <EGL/eglplatform.h> #include <GLES2/gl2.h> struct _escontext { /// Native System informations EGLNativeDisplayType native_display; EGLNativeWindowType native_window; uint16_t window_width, window_height; /// EGL display EGLDisplay display; /// EGL context EGLContext context; /// EGL surface EGLSurface surface; }; void CreateNativeWindow(char* title, int width, int height); EGLBoolean CreateEGLContext(); EGLBoolean CreateWindowWithEGLContext(char *title, int width, int height); void RefreshWindow(); struct wl_compositor *compositor = NULL; struct wl_surface *surface; struct wl_egl_window *egl_window; struct wl_region *region; struct wl_shell *shell; struct wl_shell_surface *shell_surface; struct _escontext ESContext = { .native_display = NULL, .window_width = 0, .window_height = 0, .native_window = 0, .display = NULL, .context = NULL, .surface = NULL }; #define TRUE 1 #define FALSE 0 #define WINDOW_WIDTH 1920 #define WINDOW_HEIGHT 1080 void CreateNativeWindow(char *title, int width, int height) { region = wl_compositor_create_region(compositor); wl_region_add(region, 0, 0, width, height); wl_surface_set_opaque_region(surface, region); struct wl_egl_window *egl_window = wl_egl_window_create(surface, width, height); if (egl_window == EGL_NO_SURFACE) { printf("No window !?\n"); exit(1); } else printf("Window created !\n"); ESContext.window_width = width; ESContext.window_height = height; ESContext.native_window = egl_window; } EGLBoolean CreateEGLContext () { EGLint numConfigs; EGLint majorVersion; EGLint minorVersion; EGLContext context; EGLSurface surface; EGLConfig config; EGLint attribute_list[] = {EGL_SURFACE_TYPE, // this must be first EGL_WINDOW_BIT | EGL_PBUFFER_BIT , EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE}; EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE }; EGLDisplay display = eglGetDisplay( ESContext.native_display ); if ( display == EGL_NO_DISPLAY ) { printf("No EGL Display...\n"); return EGL_FALSE; } // Initialize EGL if ( !eglInitialize(display, &majorVersion, &minorVersion) ) { printf("No Initialisation... %d \n", eglGetError()); return EGL_FALSE; } // Get configs if ( (eglGetConfigs(display, NULL, 0, &numConfigs) != EGL_TRUE) || (numConfigs == 0)) { printf("No get configuration...\n"); return EGL_FALSE; } // Choose config if ( (eglChooseConfig(display, attribute_list, &config, 1, &numConfigs) != EGL_TRUE) || (numConfigs != 1)) { printf("No choose configuration...\n"); return EGL_FALSE; } // Create a surface surface = eglCreateWindowSurface(display, config, ESContext.native_window, NULL); if ( surface == EGL_NO_SURFACE ) { printf("No surface...\n"); return EGL_FALSE; } // Create a GL context context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs ); if ( context == EGL_NO_CONTEXT ) { printf("No context...\n"); return EGL_FALSE; } // Make the context current if ( !eglMakeCurrent(display, surface, surface, context) ) { printf("Could not make the current window current !\n"); return EGL_FALSE; } printf("Context created \n"); ESContext.display = display; ESContext.surface = surface; ESContext.context = context; return EGL_TRUE; } void shell_surface_ping (void *data, struct wl_shell_surface *shell_surface, uint32_t serial) { wl_shell_surface_pong(shell_surface, serial); } 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(ESContext.native_window, width, height, 0, 0); } 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 }; EGLBoolean CreateWindowWithEGLContext(char *title, int width, int height) { CreateNativeWindow(title, width, height); return CreateEGLContext(); } void draw() { glClearColor(0.7, 0.1, 0.5, 0.2); glClear(GL_COLOR_BUFFER_BIT); } unsigned long last_click = 0; void RefreshWindow() { eglSwapBuffers(ESContext.display, ESContext.surface); } static void global_registry_handler (void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { printf("Got a registry event for %s id %d\n", interface, id); if (strcmp(interface, "wl_compositor") == 0) compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); else if (strcmp(interface, "wl_shell") == 0) shell = wl_registry_bind(registry, id, &wl_shell_interface, 1); } static void global_registry_remover (void *data, struct wl_registry *registry, uint32_t id) { printf("Got a registry losing event for %d\n", id); } const struct wl_registry_listener listener = { global_registry_handler, global_registry_remover }; static void get_server_references() { struct wl_display * display = wl_display_connect(NULL); if (display == NULL) { printf("Can't connect to wayland display !?\n"); exit(1); } printf("Got a display !"); struct wl_registry *wl_registry = wl_display_get_registry(display); wl_registry_add_listener(wl_registry, &listener, NULL); // This call the attached listener global_registry_handler wl_display_dispatch(display); wl_display_roundtrip(display); // If at this point, global_registry_handler didn't set the // compositor, nor the shell, bailout ! if (compositor == NULL || shell == NULL) { printf("No compositor !? No Shell !! There's NOTHING in here !\n"); exit(1); } else { printf("Okay, we got a compositor and a shell... That's something !\n"); ESContext.native_display = display; } } void destroy_window() { eglDestroySurface(ESContext.display, ESContext.surface); wl_egl_window_destroy(ESContext.native_window); wl_shell_surface_destroy(shell_surface); wl_surface_destroy(surface); eglDestroyContext(ESContext.display, ESContext.context); } int main() { get_server_references(); surface = wl_compositor_create_surface(compositor); if (surface == NULL) { printf("No Compositor surface ! Yay....\n"); exit(1); } else printf("Got a compositor surface !\n"); shell_surface = wl_shell_get_shell_surface(shell, surface); wl_shell_surface_set_toplevel(shell_surface); if (!CreateWindowWithEGLContext("Nya", 1280, 720)) { printf("Fail create EGL Context\n"); exit(0); } while (1) { wl_display_dispatch_pending(ESContext.native_display); draw(); RefreshWindow(); } wl_display_disconnect(ESContext.native_display); printf("Display disconnected !\n"); exit(0); }
compile command
source env.shgcc -o eglwayland eglwayland.c
pkg-config --cflags --libs wayland-egl egl glesv2
start weston
weston &run example
./eglwaylandnotes
egl APIs normal usage:eglGetDisplay
eglInitialize
eglChooseConfig
eglCreateWindowSurface
eglCreateContext
eglMakeCurrent
// gl draw
// gl draw
eglSwapBuffers