diff --git a/justfile b/justfile index 19c5e49..face83e 100644 --- a/justfile +++ b/justfile @@ -4,7 +4,7 @@ alias r := run c_flags := if os() == "macos" { "$(curl-config --libs) -framework Cocoa -framework QuartzCore -framework CoreImage -framework Metal -framework MetalKit -ObjC" } else if os_family() == "unix" { - "$(curl-config --libs) -lEGL -lGLESv2 -lGL -lm -lwayland-client -lX11 -lXi -lXcursor" + "$(curl-config --libs) -lEGL -lGLESv2 -lGL -lm -lwayland-client -lwayland-egl -lX11 -lXi -lXcursor" } else { "" } [macos] @@ -18,8 +18,8 @@ build: generate_wayland_protocols cc -Ivendor/ -O0 -g -Wall -Wextra {{ c_flags }} src/*.c src/wayland-crap/*.c -o bin/chat_client run: build - # nixGLIntel ./bin/chat_client - ./bin/chat_client + nixGLIntel ./bin/chat_client + # ./bin/chat_client [linux] generate_wayland_protocols: diff --git a/src/gfx.h b/src/gfx.h index 4ca8189..2922345 100644 --- a/src/gfx.h +++ b/src/gfx.h @@ -77,11 +77,13 @@ typedef struct { #elif __linux__ #include "wayland-crap/xdg-shell.h" #include +#include #include #include #include #include #include +#include // And I thought MacOS needed a lot of state to create a window typedef struct { @@ -98,6 +100,12 @@ typedef struct { struct wl_seat *seat; struct wl_pointer *pointer; + EGLDisplay egl_display; + EGLConfig egl_config; + EGLSurface egl_surface; + EGLContext egl_context; + struct wl_egl_window *egl_window; + int mouse_x, mouse_y; int mouse_left_down, mouse_right_down; } _opengl_gfx_context_wayland; @@ -740,33 +748,39 @@ _opengl_gfx_init_context_wayland(uint32_t width, uint32_t height) { // wait for all the globals to be registered wl_display_roundtrip(cx.display); - xdg_wm_base_add_listener(cx.wm_base, &xdg_wm_base_listener, &cx); + xdg_wm_base_add_listener(cx.wm_base, &xdg_wm_base_listener, + &_gfx_context.backend); cx.pointer = wl_seat_get_pointer(cx.seat); - wl_pointer_add_listener(cx.pointer, &pointer_listener, &cx); + wl_pointer_add_listener(cx.pointer, &pointer_listener, + &_gfx_context.backend); cx.surface = wl_compositor_create_surface(cx.compositor); cx.xdg_surface = xdg_wm_base_get_xdg_surface(cx.wm_base, cx.surface); - xdg_surface_add_listener(cx.xdg_surface, &xdg_surface_listener, &cx); + xdg_surface_add_listener(cx.xdg_surface, &xdg_surface_listener, + &_gfx_context.backend); cx.xdg_toplevel = xdg_surface_get_toplevel(cx.xdg_surface); - xdg_toplevel_add_listener(cx.xdg_toplevel, &xdg_toplevel_listener, &cx); + xdg_toplevel_add_listener(cx.xdg_toplevel, &xdg_toplevel_listener, + &_gfx_context.backend); xdg_toplevel_set_title(cx.xdg_toplevel, "chat - [Slack sux]"); xdg_toplevel_set_app_id(cx.xdg_toplevel, "nl.spacegirl.a_chat_client"); wl_surface_commit(cx.surface); wl_display_roundtrip(cx.display); - int size = width * height * 4; + int buffer_size = width * height * 4; int fd = syscall(SYS_memfd_create, "buffer", 0); - ftruncate(fd, size); + ftruncate(fd, buffer_size); - uint8_t *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - for (int i = 0; i < size; ++i) { + uint8_t *data = + mmap(NULL, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + for (int i = 0; i < buffer_size; ++i) { data[i] = 255; } - cx.shared_memory_pool = wl_shm_create_pool(cx.shared_memory, fd, size); + cx.shared_memory_pool = + wl_shm_create_pool(cx.shared_memory, fd, buffer_size); cx.buffer = wl_shm_pool_create_buffer(cx.shared_memory_pool, 0, width, height, width * 4, WL_SHM_FORMAT_ARGB8888); @@ -774,6 +788,86 @@ _opengl_gfx_init_context_wayland(uint32_t width, uint32_t height) { wl_surface_attach(cx.surface, cx.buffer, 0, 0); wl_surface_commit(cx.surface); + /* Init EGL */ + EGLint major, minor, count, n, size; + EGLConfig *configs; + EGLint config_attribs[] = { + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT, + // + EGL_RED_SIZE, + 8, + // + EGL_BLUE_SIZE, + 8, + // + EGL_GREEN_SIZE, + 8, + // + EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + // + EGL_NONE, + }; + + static const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE}; + + cx.egl_display = eglGetDisplay((EGLNativeDisplayType)cx.display); + if (cx.egl_display == EGL_NO_DISPLAY) { + fprintf(stderr, "Failed to create EGL display\n"); + exit(1); + } + fprintf(stderr, "Created EGL display\n"); + + if (eglInitialize(cx.egl_display, &major, &minor) != EGL_TRUE) { + fprintf(stderr, "Failed to initialize EGL display\n"); + exit(1); + } + fprintf(stderr, "EGL major: %d, minor: %d\n", major, minor); + + eglGetConfigs(cx.egl_display, NULL, 0, &count); + configs = calloc(count, sizeof(EGLConfig)); + + eglChooseConfig(cx.egl_display, config_attribs, configs, count, &n); + + for (int i = 0; i < n; ++i) { + eglGetConfigAttrib(cx.egl_display, configs[i], EGL_BUFFER_SIZE, &size); + fprintf(stderr, "EGL Buffer size: %d\n", size); + + eglGetConfigAttrib(cx.egl_display, configs[i], EGL_RED_SIZE, &size); + fprintf(stderr, "EGL Red size: %d\n", size); + + cx.egl_config = configs[i]; + break; + } + + cx.egl_context = eglCreateContext(cx.egl_display, cx.egl_config, + EGL_NO_CONTEXT, context_attribs); + + cx.egl_window = wl_egl_window_create(cx.surface, width, height); + if (cx.egl_window == EGL_NO_SURFACE) { + fprintf(stderr, "Failed to create EGL window\n"); + exit(1); + } + fprintf(stderr, "Created EGL window\n"); + + cx.egl_surface = eglCreateWindowSurface(cx.egl_display, cx.egl_config, + cx.egl_window, NULL); + if (eglMakeCurrent(cx.egl_display, cx.egl_surface, cx.egl_surface, + cx.egl_context) != EGL_TRUE) { + fprintf(stderr, "eglMakeCurrent() failed\n"); + } + + glClearColor(1.0f, 0.0f, 1.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + glFlush(); + + if (eglSwapBuffers(cx.egl_display, cx.egl_surface) != EGL_TRUE) { + fprintf(stderr, "eglSwapBuffers() failed\n"); + } + /* ******** */ + return cx; } @@ -803,6 +897,12 @@ static _opengl_gfx_context_x11 _opengl_gfx_init_context_11(uint32_t width, static void _opengl_gfx_send_events_wayland(_opengl_gfx_context_wayland *cx) { wl_display_dispatch(cx->display); + + // TODO: move this to present() + _gfx_context.gpu_glyphs.size = 0; + _gfx_context.gpu_ui_rects.size = 0; + _gfx_context.frame_func(cx->mouse_x, cx->mouse_y, cx->mouse_left_down, + cx->mouse_right_down); } static void _opengl_gfx_send_events_x11(_opengl_gfx_context_x11 *cx) { diff --git a/src/main.c b/src/main.c index d4a7a03..4fad040 100644 --- a/src/main.c +++ b/src/main.c @@ -203,8 +203,9 @@ void ed_frame(int mouse_x, int mouse_y, bool mouse_left_down, int main(int argc, char *argv[]) { /* curl_global_init(CURL_GLOBAL_ALL); - slack_client client = slack_init_client(_String("test token"), _String("Cookie: test_cookie=hello")); - _slack_debug_print_auth_test(&client, _String("test token"), _String("Cookie: test_cookie=hello")); + slack_client client = slack_init_client(_String("test token"), + _String("Cookie: test_cookie=hello")); _slack_debug_print_auth_test(&client, + _String("test token"), _String("Cookie: test_cookie=hello")); curl_global_cleanup(); return 0;