diff --git a/glonkers.c b/glonkers.c index 2acd567..867cd87 100644 --- a/glonkers.c +++ b/glonkers.c @@ -22,6 +22,9 @@ int main(int argc, char *argv[]) { else if (strcmp("--layer", argv[i]) == 0) { output_type = OUTPUT_LAYER; } + else if (strcmp("--output", argv[i]) == 0) { + // output name + } else { // path to fragment shader if (shader_path != NULL) { @@ -38,7 +41,8 @@ int main(int argc, char *argv[]) { struct client_state *state = wayland_init(output_type); - Renderer renderer = new_renderer(); + bool renderer_initialized = false; + Renderer renderer; bool running = true; while (running) { @@ -47,6 +51,10 @@ int main(int argc, char *argv[]) { int width = event.data.draw.width; int height = event.data.draw.height; double time = event.data.draw.time / 1000.0; + if (!renderer_initialized) { + renderer_initialized = true; + renderer = new_renderer(); + } render(&renderer, width, height, time, shader_path, 0); swap_buffers(state, event.data.draw.surface); } diff --git a/wayland.c b/wayland.c index cf40a7c..fe92a77 100644 --- a/wayland.c +++ b/wayland.c @@ -63,11 +63,117 @@ struct client_state { /// Starting values. int width = 700, height = 700; +void egl_init_surface(struct client_state *state, struct surface *surface) { + printf("Creating egl window of size: %dx%d\n", surface->width, surface->height); + surface->egl_window = wl_egl_window_create(surface->wl_surface, + surface->width, surface->height); + if (surface->egl_window == EGL_NO_SURFACE) { + fprintf(stderr, "Can't create egl window\n"); + exit(1); + } else { + fprintf(stderr, "Created egl window\n"); + } + + surface->egl_surface = + eglCreateWindowSurface(state->egl_display, + state->egl_config, + (unsigned long) surface->egl_window, NULL); + + if (eglMakeCurrent(state->egl_display, surface->egl_surface, + surface->egl_surface, state->egl_context)) { + fprintf(stderr, "Made current\n"); + } else { + fprintf(stderr, "Made current failed\n"); + } +} + + 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 void egl_init(struct client_state *state) { + 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_OPENGL_ES3_BIT | EGL_OPENGL_BIT, + EGL_MIN_SWAP_INTERVAL, 0, // make sure that swapping buffers don't block the thread + EGL_NONE + }; + + static const EGLint context_attribs[] = { + //EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_CONTEXT_MAJOR_VERSION, 4, + EGL_CONTEXT_MINOR_VERSION, 6, + EGL_CONTEXT_OPENGL_PROFILE_MASK, + EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, + 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"); + } + + EGLint major, minor; + 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); + + // Desktop GL? + if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) { + printf("eglBindAPI failed\n"); + exit(1); + } + + EGLint count; + eglGetConfigs(state->egl_display, NULL, 0, &count); + printf("EGL has %d configs\n", count); + + EGLConfig *configs = calloc(count, sizeof *configs); + + EGLint n; + eglChooseConfig(state->egl_display, config_attribs, + configs, count, &n); + + for (int i = 0; i < n; i++) { + EGLint size; + 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); + if (state->egl_context == EGL_NO_CONTEXT) { + printf("Failed to create EGL context\n"); + exit(1); + } + + struct surface_list *next = state->surface_list; + while (next != NULL) { + egl_init_surface(state, &next->data); + next = next->next; + } +} + static const struct wl_buffer_listener wl_buffer_listener = { .release = wl_buffer_release, }; @@ -96,12 +202,12 @@ static void xdg_toplevel_configure ( int32_t height, struct wl_array *states ) { - struct client_state *state = data; // resize egl window struct surface_list *next = state->surface_list; while (next->data.xdg_toplevel != xdg_toplevel) { next = next->next; } + printf("configuring window %p\n", &next->data); next->data.width = width; next->data.height = height; wl_egl_window_resize(next->data.egl_window, width, height, 0, 0); @@ -131,6 +237,7 @@ static void zwlr_layer_surface_v1_configure(void *data, struct zwlr_layer_surfac struct client_state *state = data; struct surface_list *next = state->surface_list; while (next->data.zwlr_layer_surface_v1 != zwlr_layer_surface_v1) { next = next->next; } + printf("configuring layer %p\n", &next->data); next->data.width = width; next->data.height = height; wl_egl_window_resize(next->data.egl_window, width, height, 0, 0); @@ -166,6 +273,99 @@ static const struct wl_callback_listener wl_surface_frame_listener = { .done = wl_surface_frame_done, }; +bool really_dirty_hack = false; + +/// Function called when an output (display) has been assigned a name. +static void wl_output_name(void *data, struct wl_output *wl_output, const char *name) { + if (!really_dirty_hack) { + really_dirty_hack = true; + printf("hi!!!!\n"); + struct client_state *state = data; + + struct wl_surface *wl_surface = wl_compositor_create_surface(state->wl_compositor); + + // wlr_layer_shell + int layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; + struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1 = + zwlr_layer_shell_v1_get_layer_surface( + state->zwlr_layer_shell_v1, + wl_surface, + wl_output, + layer, + "wallpaper" + ); + zwlr_layer_surface_v1_set_anchor(zwlr_layer_surface_v1, + ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP + | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); + zwlr_layer_surface_v1_set_size(zwlr_layer_surface_v1, 0, 0); + zwlr_layer_surface_v1_add_listener(zwlr_layer_surface_v1, &zwlr_layer_surface_v1_listener, state); + + struct surface surface = { + .wl_surface = wl_surface, + .zwlr_layer_surface_v1 = zwlr_layer_surface_v1, + .dirty = false, + .width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + }; + // persistent pointer for the callback + struct surface *surface_location; + if (state->surface_list == NULL) { + printf("borg??????\n"); + state->surface_list = malloc(sizeof(struct surface_list)); + printf("SURFACE LIST RIGHT????? %p\n", state->surface_list); + state->surface_list->data = surface; + state->surface_list->next = NULL; + surface_location = &state->surface_list->data; + } else { + printf("MOOOORB??????\n"); + struct surface_list *next = state->surface_list; + while (next->next != NULL) { next = next->next; } + next->next = malloc(sizeof(struct surface_list)); + next->next->data = surface; + next->next->next = NULL; + surface_location = &next->next->data; + } + + // frame callback + struct wl_callback *cb = wl_surface_frame(wl_surface); + wl_callback_add_listener(cb, &wl_surface_frame_listener, surface_location); + + wl_surface_commit(wl_surface); + + egl_init(state); + } +} + +static void wl_output_description(void *data, struct wl_output *wl_output, const char *description) { +} +static void wl_output_done(void *data, struct wl_output *wl_output) { +} +static void wl_output_geometry( + void *data, struct wl_output *wl_output, + int x, + int y, + int physical_width, + int physical_height, + int subpixel, + const char *make, + const char *model, + int transform + ) { +} +static void wl_output_mode(void *data, struct wl_output *wl_output, unsigned int mode, int width, int height, int refresh) { +} +static void wl_output_scale(void *data, struct wl_output *wl_output, int factor) { +} + +static const struct wl_output_listener wl_output_listener = { + .description = wl_output_description, + .done = wl_output_done, + .geometry = wl_output_geometry, + .mode = wl_output_mode, + .name = wl_output_name, + .scale = wl_output_scale, +}; + void pointer_enter_handler ( void *data, struct wl_pointer *pointer, @@ -258,7 +458,7 @@ static void registry_handle_global( state->cursor_surface = wl_compositor_create_surface(state->wl_compositor); wl_surface_attach(state->cursor_surface, cursor_buffer, 0, 0); - wl_surface_commit(state->cursor_surface); + //wl_surface_commit(state->cursor_surface); } if ((strcmp(interface, xdg_wm_base_interface.name) == 0) && (state->output_type == OUTPUT_WINDOW)) { state->xdg_wm_base = wl_registry_bind( @@ -291,6 +491,10 @@ static void registry_handle_global( // frame callback struct wl_callback *cb = wl_surface_frame(wl_surface); wl_callback_add_listener(cb, &wl_surface_frame_listener, &state->surface_list->data); + + wl_surface_commit(wl_surface); + + egl_init(state); } if ((strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) && (state->output_type == OUTPUT_LAYER)) { state->zwlr_layer_shell_v1 = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 4); @@ -298,51 +502,7 @@ static void registry_handle_global( if (strcmp(interface, wl_output_interface.name) == 0 && state->output_type == OUTPUT_LAYER) { struct wl_output *wl_output = wl_registry_bind( registry, name, &wl_output_interface, 4); - - struct wl_surface *wl_surface = wl_compositor_create_surface(state->wl_compositor); - - // wlr_layer_shell - int layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; - struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1 = - zwlr_layer_shell_v1_get_layer_surface( - state->zwlr_layer_shell_v1, - wl_surface, - wl_output, - layer, - "wallpaper" - ); - zwlr_layer_surface_v1_set_anchor(zwlr_layer_surface_v1, - ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP - | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); - zwlr_layer_surface_v1_set_size(zwlr_layer_surface_v1, 0, 0); - zwlr_layer_surface_v1_add_listener(zwlr_layer_surface_v1, &zwlr_layer_surface_v1_listener, state); - - struct surface surface = { - .wl_surface = wl_surface, - .zwlr_layer_surface_v1 = zwlr_layer_surface_v1, - .dirty = false, - .width = DEFAULT_WIDTH, - .height = DEFAULT_HEIGHT, - }; - // persistent pointer for the callback - struct surface *surface_location; - if (state->surface_list == NULL) { - state->surface_list = malloc(sizeof(struct surface_list)); - state->surface_list->data = surface; - state->surface_list->next = NULL; - surface_location = &state->surface_list->data; - } else { - struct surface_list *next = state->surface_list; - while (next->next != NULL) { next = next->next; } - next->next = malloc(sizeof(struct surface_list)); - next->next->data = surface; - next->next->next = NULL; - surface_location = &next->next->data; - } - - // frame callback - struct wl_callback *cb = wl_surface_frame(wl_surface); - wl_callback_add_listener(cb, &wl_surface_frame_listener, surface_location); + wl_output_add_listener(wl_output, &wl_output_listener, state); } } @@ -359,130 +519,29 @@ static const struct wl_registry_listener wl_registry_listener = { .global_remove = registry_handle_global_remove, }; -static void egl_init(struct client_state *state) { - 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_OPENGL_ES3_BIT | EGL_OPENGL_BIT, - EGL_MIN_SWAP_INTERVAL, 0, // make sure that swapping buffers don't block the thread - EGL_NONE - }; - - static const EGLint context_attribs[] = { - //EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_CONTEXT_MAJOR_VERSION, 4, - EGL_CONTEXT_MINOR_VERSION, 6, - EGL_CONTEXT_OPENGL_PROFILE_MASK, - EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, - 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"); - } - - EGLint major, minor; - 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); - - // Desktop GL? - if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) { - printf("eglBindAPI failed\n"); - exit(1); - } - - EGLint count; - eglGetConfigs(state->egl_display, NULL, 0, &count); - printf("EGL has %d configs\n", count); - - EGLConfig *configs = calloc(count, sizeof *configs); - - EGLint n; - eglChooseConfig(state->egl_display, config_attribs, - configs, count, &n); - - for (int i = 0; i < n; i++) { - EGLint size; - 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); - if (state->egl_context == EGL_NO_CONTEXT) { - printf("Failed to create EGL context\n"); - exit(1); - } - - // EGL window - struct surface_list *next = state->surface_list; - while (next != NULL) { - printf("Creating egl window of size: %dx%d\n", next->data.width, next->data.height); - next->data.egl_window = wl_egl_window_create(next->data.wl_surface, - next->data.width, next->data.height); - if (next->data.egl_window == EGL_NO_SURFACE) { - fprintf(stderr, "Can't create egl window\n"); - exit(1); - } else { - fprintf(stderr, "Created egl window\n"); - } - - next->data.egl_surface = - eglCreateWindowSurface(state->egl_display, - state->egl_config, - (unsigned long) next->data.egl_window, NULL); - - if (eglMakeCurrent(state->egl_display, next->data.egl_surface, - next->data.egl_surface, state->egl_context)) { - fprintf(stderr, "Made current\n"); - } else { - fprintf(stderr, "Made current failed\n"); - } - - next = next->next; - } -} - /// Initializes wayland and creates an opengl context struct client_state* wayland_init(int output_type) { struct client_state *state = malloc(sizeof(struct client_state)); + state->surface_list = NULL; + state->surface_list_next = NULL; state->running = 1; state->output_type = output_type; state->wl_display = wl_display_connect(NULL); state->wl_registry = wl_display_get_registry(state->wl_display); - state->surface_list = NULL; - state->surface_list_next = NULL; wl_registry_add_listener(state->wl_registry, &wl_registry_listener, state); wl_display_roundtrip(state->wl_display); wl_seat_get_pointer(state->wl_seat); struct surface_list *next = state->surface_list; + + printf("ughhhhh:??? %p\n", next); while (next != NULL) { + printf("committing surface after initialization 🐯\n"); wl_surface_commit(next->data.wl_surface); next = next->next; } - - egl_init(state); + return state; } @@ -496,7 +555,8 @@ struct event wait_for_event(struct client_state *state) { struct event event = { .type = EVENT_EXIT }; return event; } - while (true) { + // don't bother with loop if no surfaces to render + while (state->surface_list != NULL) { if (next == NULL) { next = state->surface_list; } @@ -531,6 +591,7 @@ struct event wait_for_event(struct client_state *state) { break; } } + printf("dispatching\n"); wl_display_dispatch(state->wl_display); struct event event = { .type = EVENT_NONE,