diff options
author | Phil Jones <philj56@gmail.com> | 2021-10-26 17:27:15 +0100 |
---|---|---|
committer | Phil Jones <philj56@gmail.com> | 2021-10-26 17:27:15 +0100 |
commit | c1e7ea47b25cdf7bf316ce522f9aa438b0b657c7 (patch) | |
tree | ca3893b63ea927c88eb2eac0b47f7438ff199dc4 | |
parent | 7a640bd0622caf8a3354934d0400e8c361cdeee3 (diff) |
Initial functional EGL example.
-rw-r--r-- | src/main.c | 134 |
1 files changed, 23 insertions, 111 deletions
@@ -1,4 +1,5 @@ #include <assert.h> +#include <wayland-egl.h> #include <epoxy/egl.h> #include <epoxy/gl.h> #include <errno.h> @@ -6,116 +7,22 @@ #include <limits.h> #include <stdbool.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <time.h> #include <unistd.h> #include <wayland-client.h> -#include <wayland-egl.h> #include <xkbcommon/xkbcommon.h> #include "client.h" #include "egl.h" #include "xdg-shell-client-protocol.h" -/* Shared memory support code */ -static void -randname(char *buf) -{ - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - long r = ts.tv_nsec; - for (int i = 0; i < 6; ++i) { - buf[i] = 'A'+(r&15)+(r&16)*2; - r >>= 5; - } -} - -static int -create_shm_file(void) -{ - int retries = 100; - do { - char name[] = "/wl_shm-XXXXXX"; - randname(name + sizeof(name) - 7); - --retries; - int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd >= 0) { - shm_unlink(name); - return fd; - } - } while (retries > 0 && errno == EEXIST); - return -1; -} - -static int -allocate_shm_file(size_t size) +void draw_frame(struct client_state *state) { - int fd = create_shm_file(); - if (fd < 0) - return -1; - int ret; - do { - ret = ftruncate(fd, size); - } while (ret < 0 && errno == EINTR); - if (ret < 0) { - close(fd); - return -1; - } - return fd; -} - -/* Wayland code */ - -static void -wl_buffer_release(void *data, struct wl_buffer *wl_buffer) -{ - /* Sent by the compositor when it's no longer using this buffer */ - wl_buffer_destroy(wl_buffer); -} - -static const struct wl_buffer_listener wl_buffer_listener = { - .release = wl_buffer_release, -}; - -static struct wl_buffer * -draw_frame(struct client_state *state) -{ - const int width = state->width, height = state->height; - int stride = width * 4; - int size = stride * height; - - int fd = allocate_shm_file(size); - if (fd == -1) { - return NULL; - } - - uint32_t *data = mmap(NULL, size, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) { - close(fd); - return NULL; - } - - struct wl_shm_pool *pool = wl_shm_create_pool(state->wl_shm, fd, size); - struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, - width, height, stride, WL_SHM_FORMAT_XRGB8888); - wl_shm_pool_destroy(pool); - close(fd); - - /* Draw checkerboxed background */ - int offset = (int)state->offset % 8; - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - if (((x + offset) + (y + offset) / 8 * 8) % 16 < 8) - data[y * width + x] = 0xFF666666; - else - data[y * width + x] = 0xFFEEEEEE; - } - } - - munmap(data, size); - wl_buffer_add_listener(buffer, &wl_buffer_listener, NULL); - return buffer; + glClearColor(rand() / (double)RAND_MAX, rand() / (double)RAND_MAX, rand() / (double)RAND_MAX, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + eglSwapBuffers(state->egl.display, state->egl.surface); } static void @@ -128,8 +35,14 @@ xdg_toplevel_configure(void *data, /* Compositor is deferring to us */ return; } - state->width = width; - state->height = height; + + if (width != state->width || height != state->height) { + state->width = width; + state->height = height; + printf("Resize: %d x %d\n", width, height); + wl_egl_window_resize(state->egl.window, width, height, 0, 0); + draw_frame(state); + } } static void @@ -148,12 +61,7 @@ static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { - struct client_state *state = data; xdg_surface_ack_configure(xdg_surface, serial); - - struct wl_buffer *buffer = draw_frame(state); - wl_surface_attach(state->wl_surface, buffer, 0, 0); - wl_surface_commit(state->wl_surface); } static const struct xdg_surface_listener xdg_surface_listener = { @@ -219,6 +127,9 @@ wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard, xkb_state_key_get_utf8(client_state->xkb_state, keycode, buf, sizeof(buf)); fprintf(stderr, "utf8: '%s'\n", buf); + if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { + draw_frame(client_state); + } } static void @@ -313,8 +224,6 @@ wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) } /* Submit a frame for this event */ - struct wl_buffer *buffer = draw_frame(state); - wl_surface_attach(state->wl_surface, buffer, 0, 0); wl_surface_damage_buffer(state->wl_surface, 0, 0, INT32_MAX, INT32_MAX); wl_surface_commit(state->wl_surface); @@ -361,8 +270,7 @@ static const struct wl_registry_listener wl_registry_listener = { .global_remove = registry_global_remove, }; -int -main(int argc, char *argv[]) +int main(int argc, char *argv[]) { struct client_state state = { 0 }; state.width = 640; @@ -380,7 +288,7 @@ main(int argc, char *argv[]) state.xdg_toplevel = xdg_surface_get_toplevel(state.xdg_surface); xdg_toplevel_add_listener(state.xdg_toplevel, &xdg_toplevel_listener, &state); - xdg_toplevel_set_title(state.xdg_toplevel, "Example client"); + xdg_toplevel_set_title(state.xdg_toplevel, "Greetd mini wayland greeter"); wl_surface_commit(state.wl_surface); @@ -390,9 +298,13 @@ main(int argc, char *argv[]) struct wl_callback *cb = wl_surface_frame(state.wl_surface); wl_callback_add_listener(cb, &wl_surface_frame_listener, &state); + wl_display_roundtrip(state.wl_display); + draw_frame(&state); while (!state.closed) { wl_display_dispatch(state.wl_display); } + wl_display_disconnect(state.wl_display); + return 0; } |