diff --git a/Makefile b/Makefile index a2aec1c..91d6e26 100644 --- a/Makefile +++ b/Makefile @@ -5,10 +5,10 @@ LDLIBS+=$(shell pkg-config --libs $(LIBS)) WAYLAND_PROTOCOLS=$(shell pkg-config --variable=pkgdatadir wayland-protocols) WAYLAND_SCANNER=$(shell pkg-config --variable=wayland_scanner wayland-scanner) -glonkers: wlr-layer-shell-unstable-v1-protocol.o xdg-shell-protocol.o renderer.o shm.o -glonkers.o: wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h renderer.h shm.h +glonkers: wlr-layer-shell-unstable-v1-protocol.o xdg-shell-protocol.o renderer.o wayland.o +glonkers.o: wlr-layer-shell-unstable-v1-protocol.h xdg-shell-protocol.h renderer.h wayland.h renderer.o: renderer.h -shm.o: +wayland.o: wayland.h xdg-shell-protocol.h: $(WAYLAND_SCANNER) client-header $(WAYLAND_PROTOCOLS)/stable/xdg-shell/xdg-shell.xml $@ diff --git a/glonkers.c b/glonkers.c index f117f6d..93ed68b 100644 --- a/glonkers.c +++ b/glonkers.c @@ -9,12 +9,12 @@ #include #include #include "renderer.h" -#include "xdg-shell-protocol.h" -#include -#include +#include "wayland.h" struct timespec program_start; +int running = 1; + void init_timer() { clock_gettime(CLOCK_MONOTONIC, &program_start); } @@ -27,177 +27,6 @@ double time_since_start() { (now.tv_nsec - program_start.tv_nsec) / 1e9; } -struct client_state { - int width, height; - /* Globals */ - struct wl_display *wl_display; - struct wl_registry *wl_registry; - struct wl_compositor *wl_compositor; - struct xdg_wm_base *xdg_wm_base; - /* Objects */ - struct wl_surface *wl_surface; - struct xdg_surface *xdg_surface; - struct xdg_toplevel *xdg_toplevel; - - struct wl_egl_window *egl_window; - - EGLDisplay egl_display; - EGLConfig egl_config; - EGLSurface egl_surface; - EGLContext egl_context; -}; - -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 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); -} - -static const struct xdg_surface_listener xdg_surface_listener = { - .configure = xdg_surface_configure, -}; - -static void -xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) -{ - xdg_wm_base_pong(xdg_wm_base, serial); -} - -static const struct xdg_wm_base_listener xdg_wm_base_listener = { - .ping = xdg_wm_base_ping, -}; - -static void -registry_handle_global(void *data, struct wl_registry *registry, - uint32_t name, const char *interface, uint32_t version) -{ - printf("interface: '%s', version: %d, name: %d\n", - interface, version, name); - - struct client_state *state = data; - - if (strcmp(interface, wl_compositor_interface.name) == 0) { - state->wl_compositor = wl_registry_bind( - registry, name, &wl_compositor_interface, 4); - } - if (strcmp(interface, xdg_wm_base_interface.name) == 0) { - state->xdg_wm_base = wl_registry_bind( - registry, name, &xdg_wm_base_interface, 1); - xdg_wm_base_add_listener(state->xdg_wm_base, - &xdg_wm_base_listener, state); - } - -} - -static void -registry_handle_global_remove(void *data, struct wl_registry *registry, - uint32_t name) -{ - // This space deliberately left blank -} - -static const struct wl_registry_listener -wl_registry_listener = { - .global = registry_handle_global, - .global_remove = registry_handle_global_remove, -}; - -static void egl_init(struct client_state *state) { - EGLint major, minor, count, n, size; - EGLConfig *configs; - int i; - EGLint config_attribs[] = { - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE - }; - - static const EGLint context_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - - state->egl_display = eglGetDisplay((EGLNativeDisplayType) state->wl_display); - if (state->egl_display == EGL_NO_DISPLAY) { - fprintf(stderr, "Can't create egl display\n"); - exit(1); - } else { - fprintf(stderr, "Created egl display\n"); - } - - if (eglInitialize(state->egl_display, &major, &minor) != EGL_TRUE) { - fprintf(stderr, "Can't initialise egl display\n"); - exit(1); - } - printf("EGL major: %d, minor %d\n", major, minor); - - eglGetConfigs(state->egl_display, NULL, 0, &count); - printf("EGL has %d configs\n", count); - - configs = calloc(count, sizeof *configs); - - eglChooseConfig(state->egl_display, config_attribs, - configs, count, &n); - - for (i = 0; i < n; i++) { - eglGetConfigAttrib(state->egl_display, - configs[i], EGL_BUFFER_SIZE, &size); - printf("Buffer size for config %d is %d\n", i, size); - eglGetConfigAttrib(state->egl_display, - configs[i], EGL_RED_SIZE, &size); - printf("Red size for config %d is %d\n", i, size); - - // just choose the first one - state->egl_config = configs[i]; - break; - } - - state->egl_context = - eglCreateContext(state->egl_display, - state->egl_config, - EGL_NO_CONTEXT, context_attribs); - - - // EGL window - state->egl_window = wl_egl_window_create(state->wl_surface, - state->width, state->height); - if (state->egl_window == EGL_NO_SURFACE) { - fprintf(stderr, "Can't create egl window\n"); - exit(1); - } else { - fprintf(stderr, "Created egl window\n"); - } - - state->egl_surface = - eglCreateWindowSurface(state->egl_display, - state->egl_config, - (unsigned long) state->egl_window, NULL); - - if (eglMakeCurrent(state->egl_display, state->egl_surface, - state->egl_surface, state->egl_context)) { - fprintf(stderr, "Made current\n"); - } else { - fprintf(stderr, "Made current failed\n"); - } -} - int main(int argc, char *argv[]) { @@ -208,29 +37,15 @@ main(int argc, char *argv[]) printf("need to supply path to shader\n"); exit(1); } - int width = 700, height = 700; - struct client_state state = { width, height, 0 }; - state.wl_display = wl_display_connect(NULL); - state.wl_registry = wl_display_get_registry(state.wl_display); - wl_registry_add_listener(state.wl_registry, &wl_registry_listener, &state); - wl_display_roundtrip(state.wl_display); - state.wl_surface = wl_compositor_create_surface(state.wl_compositor); - state.xdg_surface = xdg_wm_base_get_xdg_surface( - state.xdg_wm_base, state.wl_surface); - xdg_surface_add_listener(state.xdg_surface, &xdg_surface_listener, &state); - state.xdg_toplevel = xdg_surface_get_toplevel(state.xdg_surface); - xdg_toplevel_set_title(state.xdg_toplevel, "GLONKERS!"); - wl_surface_commit(state.wl_surface); - - egl_init(&state); + struct client_state state = wayland_init(); Renderer renderer = new_renderer(); - while (wl_display_dispatch(state.wl_display)) { + while (running) { double time = time_since_start(); render(&renderer, state.width, state.height, time, shader_path, false); - eglSwapBuffers(state.egl_display, state.egl_surface); + commit(&state); } return 0; diff --git a/wayland.c b/wayland.c new file mode 100644 index 0000000..4420897 --- /dev/null +++ b/wayland.c @@ -0,0 +1,183 @@ +#include +#include +#include +#include "wayland.h" + +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 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); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + .configure = xdg_surface_configure, +}; + +static void +xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) +{ + xdg_wm_base_pong(xdg_wm_base, serial); +} + +static const struct xdg_wm_base_listener xdg_wm_base_listener = { + .ping = xdg_wm_base_ping, +}; + +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + printf("interface: '%s', version: %d, name: %d\n", + interface, version, name); + + struct client_state *state = data; + + if (strcmp(interface, wl_compositor_interface.name) == 0) { + state->wl_compositor = wl_registry_bind( + registry, name, &wl_compositor_interface, 4); + } + if (strcmp(interface, xdg_wm_base_interface.name) == 0) { + state->xdg_wm_base = wl_registry_bind( + registry, name, &xdg_wm_base_interface, 1); + xdg_wm_base_add_listener(state->xdg_wm_base, + &xdg_wm_base_listener, state); + } + +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ + // This space deliberately left blank +} + +static const struct wl_registry_listener +wl_registry_listener = { + .global = registry_handle_global, + .global_remove = registry_handle_global_remove, +}; + +static void egl_init(struct client_state *state) { + EGLint major, minor, count, n, size; + EGLConfig *configs; + int i; + EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + + static const EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + state->egl_display = eglGetDisplay((EGLNativeDisplayType) state->wl_display); + + if (state->egl_display == EGL_NO_DISPLAY) { + fprintf(stderr, "Can't create egl display\n"); + exit(1); + } else { + fprintf(stderr, "Created egl display\n"); + } + + if (eglInitialize(state->egl_display, &major, &minor) != EGL_TRUE) { + fprintf(stderr, "Can't initialise egl display\n"); + exit(1); + } + printf("EGL major: %d, minor %d\n", major, minor); + + eglGetConfigs(state->egl_display, NULL, 0, &count); + printf("EGL has %d configs\n", count); + + configs = calloc(count, sizeof *configs); + + eglChooseConfig(state->egl_display, config_attribs, + configs, count, &n); + + for (i = 0; i < n; i++) { + eglGetConfigAttrib(state->egl_display, + configs[i], EGL_BUFFER_SIZE, &size); + printf("Buffer size for config %d is %d\n", i, size); + eglGetConfigAttrib(state->egl_display, + configs[i], EGL_RED_SIZE, &size); + printf("Red size for config %d is %d\n", i, size); + // just choose the first one + state->egl_config = configs[i]; + break; + } + + state->egl_context = + eglCreateContext(state->egl_display, + state->egl_config, + EGL_NO_CONTEXT, context_attribs); + + + // EGL window + state->egl_window = wl_egl_window_create(state->wl_surface, + state->width, state->height); + if (state->egl_window == EGL_NO_SURFACE) { + fprintf(stderr, "Can't create egl window\n"); + exit(1); + } else { + fprintf(stderr, "Created egl window\n"); + } + + state->egl_surface = + eglCreateWindowSurface(state->egl_display, + state->egl_config, + (unsigned long) state->egl_window, NULL); + + if (eglMakeCurrent(state->egl_display, state->egl_surface, + state->egl_surface, state->egl_context)) { + fprintf(stderr, "Made current\n"); + } else { + fprintf(stderr, "Made current failed\n"); + } +} + +/// Initializes wayland and creates an opengl context +struct client_state wayland_init() { + int width = 700, height = 700; + struct client_state state = { width, height, 0 }; + state.wl_display = wl_display_connect(NULL); + state.wl_registry = wl_display_get_registry(state.wl_display); + wl_registry_add_listener(state.wl_registry, &wl_registry_listener, &state); + wl_display_roundtrip(state.wl_display); + + state.wl_surface = wl_compositor_create_surface(state.wl_compositor); + state.xdg_surface = xdg_wm_base_get_xdg_surface( + state.xdg_wm_base, state.wl_surface); + xdg_surface_add_listener(state.xdg_surface, &xdg_surface_listener, &state); + state.xdg_toplevel = xdg_surface_get_toplevel(state.xdg_surface); + xdg_toplevel_set_title(state.xdg_toplevel, "GLONKERS!"); + wl_surface_commit(state.wl_surface); + + egl_init(&state); + + return state; +} + +/// Swaps front/backbuffers and dispatches pending wayland commands. +void commit(struct client_state *state) { + wl_display_dispatch(state->wl_display); + eglSwapBuffers(state->egl_display, state->egl_surface); +} + diff --git a/wayland.h b/wayland.h new file mode 100644 index 0000000..01137cb --- /dev/null +++ b/wayland.h @@ -0,0 +1,27 @@ +#include +#include +#include "xdg-shell-protocol.h" + +struct client_state { + int width, height; + /* Globals */ + struct wl_display *wl_display; + struct wl_registry *wl_registry; + struct wl_compositor *wl_compositor; + struct xdg_wm_base *xdg_wm_base; + /* Objects */ + struct wl_surface *wl_surface; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + + struct wl_egl_window *egl_window; + + EGLDisplay egl_display; + EGLConfig egl_config; + EGLSurface egl_surface; + EGLContext egl_context; +}; + +struct client_state wayland_init(); +void commit(struct client_state *state); +