wl-egl.c (5466B)
1 #include <wayland-client.h> 2 #include "xdg-shell.h" 3 4 #include <wayland-egl.h> 5 #include <EGL/egl.h> 6 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 struct wl_display *display; 12 struct wl_compositor *compositor; 13 struct xdg_wm_base *wm_base; 14 EGLDisplay egl_display; 15 char running; 16 17 #define DEFAULT_WIDTH 256 18 #define DEFAULT_HEIGHT 256 19 20 struct window { 21 EGLContext egl_context; 22 struct wl_surface *surface; 23 struct xdg_surface *xdg_surface; 24 struct xdg_toplevel *xdg_toplevel; 25 struct wl_egl_window *egl_window; 26 EGLSurface egl_surface; 27 }; 28 29 static void 30 wm_base_ping(void *data, struct xdg_wm_base *wm_base, uint32_t serial) 31 { 32 xdg_wm_base_pong(wm_base, serial); 33 } 34 35 static const struct xdg_wm_base_listener xdg_wm_base_listener = { 36 .ping = wm_base_ping, 37 }; 38 39 static void 40 registry_add_global(void *data, struct wl_registry *registry, uint32_t name, char const *interface, uint32_t version) 41 { 42 if (!strcmp(interface, wl_compositor_interface.name)) { 43 compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 6); 44 } else if (!strcmp(interface, xdg_wm_base_interface.name)) { 45 wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 6); 46 xdg_wm_base_add_listener(wm_base, &xdg_wm_base_listener, NULL); 47 } 48 } 49 50 static void 51 registry_remove_global(void *data, struct wl_registry *registry, uint32_t name) 52 { 53 } 54 55 static const struct wl_registry_listener registry_listener = { 56 .global = registry_add_global, 57 .global_remove = registry_remove_global, 58 }; 59 60 static void 61 xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) 62 { 63 xdg_surface_ack_configure(xdg_surface, serial); 64 } 65 66 static const struct xdg_surface_listener xdg_surface_listener = { 67 .configure = xdg_surface_configure, 68 }; 69 70 static void 71 xdg_toplevel_configure(void *data, struct xdg_toplevel *toplevel, 72 int32_t width, int32_t height, struct wl_array *states) 73 { 74 fprintf(stderr, "xdg_toplevel_configure: width: %d, height: %d\n", width, height); 75 76 struct window *window = data; 77 78 wl_egl_window_resize(window->egl_window, 79 width ? width : DEFAULT_WIDTH, 80 height ? height : DEFAULT_HEIGHT, 81 0, 0); 82 83 fprintf(stderr, "Created egl_window\n"); 84 } 85 86 static void 87 xdg_toplevel_close(void *data, struct xdg_toplevel *toplevel) 88 { 89 running = 0; 90 91 fprintf(stderr, "Closing egl_window\n"); 92 } 93 94 static void 95 xdg_toplevel_configure_bounds(void *data, struct xdg_toplevel *toplevel, 96 int32_t width, int32_t height) 97 { 98 fprintf(stderr, "xdg_toplevel_configure_bounds: width: %d, height: %d\n", width, height); 99 100 struct window *window = data; 101 102 wl_egl_window_resize(window->egl_window, width, height, 0, 0); 103 104 fprintf(stderr, "Resized egl_window\n"); 105 } 106 107 static void 108 xdg_toplevel_wm_capabilities(void *data, struct xdg_toplevel *toplevel, 109 struct wl_array *caps) 110 { 111 } 112 113 static const struct xdg_toplevel_listener xdg_toplevel_listener = { 114 .configure = xdg_toplevel_configure, 115 .close = xdg_toplevel_close, 116 .configure_bounds = xdg_toplevel_configure_bounds, 117 .wm_capabilities = xdg_toplevel_wm_capabilities, 118 }; 119 120 void 121 create_egl_window(struct window *window) 122 { 123 EGLint major, minor; 124 eglInitialize(egl_display, &major, &minor); 125 126 fprintf(stderr, "EGL version: %d.%d\n", major, minor); 127 128 eglBindAPI(EGL_OPENGL_API); 129 130 EGLint attrs[] = { 131 EGL_RED_SIZE, 8, 132 EGL_GREEN_SIZE, 8, 133 EGL_BLUE_SIZE, 8, 134 EGL_ALPHA_SIZE, 8, 135 EGL_NONE, 136 }; 137 138 EGLConfig config; 139 EGLint num_config; 140 eglChooseConfig(egl_display, attrs, &config, 1, &num_config); 141 142 window->egl_context = eglCreateContext(egl_display, config, EGL_NO_CONTEXT, NULL); 143 144 window->surface = wl_compositor_create_surface(compositor); 145 window->egl_window = wl_egl_window_create(window->surface, DEFAULT_WIDTH, DEFAULT_HEIGHT); 146 147 window->xdg_surface = xdg_wm_base_get_xdg_surface(wm_base, window->surface); 148 xdg_surface_add_listener(window->xdg_surface, &xdg_surface_listener, NULL); 149 150 window->xdg_toplevel = xdg_surface_get_toplevel(window->xdg_surface); 151 xdg_toplevel_add_listener(window->xdg_toplevel, &xdg_toplevel_listener, window); 152 153 xdg_toplevel_set_title(window->xdg_toplevel, "wl-egl-example"); 154 155 wl_surface_commit(window->surface); 156 wl_display_roundtrip(display); 157 158 window->egl_surface = eglCreateWindowSurface(egl_display, config, window->egl_window, NULL); 159 if (window->egl_surface == EGL_NO_SURFACE) { 160 fprintf(stderr, "Failed to create surface!\n"); 161 exit(EXIT_FAILURE); 162 } 163 164 eglMakeCurrent(egl_display, window->egl_surface, window->egl_surface, window->egl_context); 165 } 166 167 void 168 destroy_egl_window(struct window *window) 169 { 170 eglDestroySurface(egl_display, window->egl_surface); 171 wl_egl_window_destroy(window->egl_window); 172 xdg_toplevel_destroy(window->xdg_toplevel); 173 xdg_surface_destroy(window->xdg_surface); 174 wl_surface_destroy(window->surface); 175 eglDestroyContext(egl_display, window->egl_context); 176 } 177 178 void 179 draw(struct window *window) 180 { 181 eglSwapBuffers(egl_display, window->egl_surface); 182 } 183 184 int 185 main(void) 186 { 187 fprintf(stderr, "Hello, World!\n"); 188 189 display = wl_display_connect(NULL); 190 191 struct wl_registry *registry = wl_display_get_registry(display); 192 wl_registry_add_listener(registry, ®istry_listener, NULL); 193 wl_display_roundtrip(display); 194 195 egl_display = eglGetDisplay(display); 196 197 struct window window; 198 create_egl_window(&window); 199 200 running = 1; 201 while (running) { 202 wl_display_dispatch_pending(display); 203 draw(&window); 204 } 205 206 destroy_egl_window(&window); 207 208 eglTerminate(egl_display); 209 wl_display_disconnect(display); 210 211 fprintf(stderr, "Goodbye, World!\n"); 212 213 return 0; 214 }