diff options
-rw-r--r-- | meson.build | 7 | ||||
-rw-r--r-- | src/client.h | 34 | ||||
-rw-r--r-- | src/egl.c | 122 | ||||
-rw-r--r-- | src/egl.h | 17 | ||||
-rw-r--r-- | src/log.c | 40 | ||||
-rw-r--r-- | src/log.h | 9 | ||||
-rw-r--r-- | src/main.c (renamed from src/client.c) | 74 |
7 files changed, 232 insertions, 71 deletions
diff --git a/meson.build b/meson.build index 7474a4f..cdffbdd 100644 --- a/meson.build +++ b/meson.build @@ -15,6 +15,9 @@ project( ) debug = get_option('buildtype').startswith('debug') +if debug + add_project_arguments('-DDEBUG', language : 'c') +endif data_location = join_paths( get_option('prefix'), @@ -34,7 +37,9 @@ add_project_arguments( ) sources = files( - 'src/client.c', + 'src/main.c', + 'src/log.c', + 'src/egl.c', 'src/xdg-shell-protocol.c', ) diff --git a/src/client.h b/src/client.h new file mode 100644 index 0000000..04d78ac --- /dev/null +++ b/src/client.h @@ -0,0 +1,34 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include <stdbool.h> +#include <stdint.h> +#include "egl.h" + +struct client_state { + /* Globals */ + struct wl_display *wl_display; + struct wl_registry *wl_registry; + struct wl_shm *wl_shm; + struct wl_compositor *wl_compositor; + struct wl_seat *wl_seat; + struct xdg_wm_base *xdg_wm_base; + /* Objects */ + struct wl_surface *wl_surface; + struct wl_keyboard *wl_keyboard; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + /* State */ + float offset; + uint32_t last_frame; + int width; + int height; + bool closed; + struct egl egl; + /* Keyboard state */ + struct xkb_state *xkb_state; + struct xkb_context *xkb_context; + struct xkb_keymap *xkb_keymap; +}; + +#endif /* CLIENT_H */ diff --git a/src/egl.c b/src/egl.c new file mode 100644 index 0000000..bd45413 --- /dev/null +++ b/src/egl.c @@ -0,0 +1,122 @@ +#include <assert.h> +#include <string.h> +#include <wayland-egl.h> +#include "client.h" +#include "log.h" + +static void egl_log_error(); +static const char *egl_error_string(); + +void egl_create_window(struct client_state *state) +{ + state->egl.window = wl_egl_window_create( + state->wl_surface, + state->width, + state->height); + + if (state->egl.window == EGL_NO_SURFACE) { + egl_log_error("Couldn't create EGL window"); + } +} + +void egl_create_context(struct client_state *state) +{ + struct egl *egl = &state->egl; + egl->display = eglGetDisplay(state->wl_display); + if (egl->display == EGL_NO_DISPLAY) { + egl_log_error("Couldn't get EGL display"); + return; + } + + if (!eglInitialize(egl->display, NULL, NULL)) { + egl_log_error("Couldn't initialise EGL"); + return; + } + + EGLBoolean result; + EGLConfig config; + EGLint num_configs; + static const EGLint config_attribs[] = { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_NONE + }; + + result = eglGetConfigs(egl->display, NULL, 0, &num_configs); + if ((result != EGL_TRUE) || (num_configs == 0)) { + egl_log_error("No EGL configs available"); + return; + } + + result = eglChooseConfig(egl->display, config_attribs, &config, 1, &num_configs); + if ((result != EGL_TRUE) || (num_configs != 1)) { + egl_log_error("Failed to choose EGL config"); + return; + } + + egl->surface = eglCreateWindowSurface(egl->display, config, egl->window, NULL); + if (egl->surface == EGL_NO_SURFACE) { + egl_log_error("Couldn't create EGL window surface"); + return; + } + + static const EGLint context_attribs[] = { + EGL_CONTEXT_MAJOR_VERSION, 2, + EGL_NONE + }; + + egl->context = eglCreateContext(egl->display, config, EGL_NO_CONTEXT, context_attribs); + if (egl->context == EGL_NO_CONTEXT) { + egl_log_error("Couldn't create EGL context"); + return; + } + + result = eglMakeCurrent(egl->display, egl->surface, egl->surface, egl->context); + if (!result) { + egl_log_error("Couldn't make EGL context current"); + return; + } +} + +void egl_log_error(const char *msg) { + log_error("%s: %s\n", msg, egl_error_string()); +} + +const char *egl_error_string() { + switch(eglGetError()) { + case EGL_SUCCESS: + return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT"; + case EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG"; + case EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY"; + case EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE"; + case EGL_BAD_MATCH: + return "EGL_BAD_MATCH"; + case EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER"; + case EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW"; + case EGL_CONTEXT_LOST: + return "EGL_CONTEXT_LOST"; + } + return "Unknown EGL error"; +} diff --git a/src/egl.h b/src/egl.h new file mode 100644 index 0000000..f97bd22 --- /dev/null +++ b/src/egl.h @@ -0,0 +1,17 @@ +#ifndef EGL_H +#define EGL_H + +#include <epoxy/egl.h> + +struct client_state; +struct egl { + EGLNativeWindowType window; + EGLDisplay display; + EGLContext context; + EGLSurface surface; +}; + +void egl_create_window(struct client_state *state); +void egl_create_context(struct client_state *state); + +#endif /* EGL_H */ diff --git a/src/log.c b/src/log.c new file mode 100644 index 0000000..eb4d165 --- /dev/null +++ b/src/log.c @@ -0,0 +1,40 @@ +#include <stdio.h> + +void log_error(const char *const fmt, ...) +{ + va_list args; + va_start(args, fmt); + fprintf(stderr, "[ERROR]: "); + vfprintf(stderr, fmt, args); + va_end(args); +} + +void log_warning(const char *const fmt, ...) +{ + va_list args; + va_start(args, fmt); + fprintf(stderr, "[WARNING]: "); + vfprintf(stderr, fmt, args); + va_end(args); +} + +void log_debug(const char *const fmt, ...) +{ +#ifndef DEBUG + return; +#endif + va_list args; + va_start(args, fmt); + printf("[DEBUG]: "); + vprintf(fmt, args); + va_end(args); +} + +void log_info(const char *const fmt, ...) +{ + va_list args; + va_start(args, fmt); + printf("[INFO]: "); + vprintf(fmt, args); + va_end(args); +} diff --git a/src/log.h b/src/log.h new file mode 100644 index 0000000..e030bc9 --- /dev/null +++ b/src/log.h @@ -0,0 +1,9 @@ +#ifndef LOG_H +#define LOG_H + +void log_error(const char *const fmt, ...); +void log_warning(const char *const fmt, ...); +void log_debug(const char *const fmt, ...); +void log_info(const char *const fmt, ...); + +#endif /* LOG_H */ diff --git a/src/client.c b/src/main.c index 0b2bdec..5991424 100644 --- a/src/client.c +++ b/src/main.c @@ -1,4 +1,3 @@ -#define _POSIX_C_SOURCE 200112L #include <assert.h> #include <epoxy/egl.h> #include <epoxy/gl.h> @@ -14,6 +13,8 @@ #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 */ @@ -64,30 +65,6 @@ allocate_shm_file(size_t size) } /* Wayland code */ -struct client_state { - /* Globals */ - struct wl_display *wl_display; - struct wl_registry *wl_registry; - struct wl_shm *wl_shm; - struct wl_compositor *wl_compositor; - struct wl_seat *wl_seat; - struct xdg_wm_base *xdg_wm_base; - /* Objects */ - struct wl_surface *wl_surface; - struct wl_keyboard *wl_keyboard; - struct xdg_surface *xdg_surface; - struct xdg_toplevel *xdg_toplevel; - /* State */ - float offset; - uint32_t last_frame; - int width; - int height; - bool closed; - /* Keyboard state */ - struct xkb_state *xkb_state; - struct xkb_context *xkb_context; - struct xkb_keymap *xkb_keymap; -}; static void wl_buffer_release(void *data, struct wl_buffer *wl_buffer) @@ -407,51 +384,8 @@ main(int argc, char *argv[]) wl_surface_commit(state.wl_surface); - - /* Setup EGL */ - EGLDisplay egl_dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_WAYLAND_KHR, - state.wl_display, NULL); - assert(egl_dpy != NULL); - bool res = eglInitialize(egl_dpy, NULL, NULL); - assert(res); - - const char *egl_extension_st = eglQueryString (egl_dpy, EGL_EXTENSIONS); - assert (strstr (egl_extension_st, "EGL_KHR_create_context") != NULL); - - static const EGLint config_attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, - EGL_NONE - }; - EGLConfig cfg; - EGLint count; - - res = eglChooseConfig (egl_dpy, config_attribs, &cfg, 1, &count); - assert (res); - - res = eglBindAPI (EGL_OPENGL_ES_API); - assert (res); - - static const EGLint attribs[] = { - EGL_CONTEXT_MAJOR_VERSION, 2, - EGL_NONE - }; - EGLContext core_ctx = eglCreateContext (egl_dpy, - cfg, - EGL_NO_CONTEXT, - attribs); - assert (core_ctx != EGL_NO_CONTEXT); - - struct wl_egl_window *egl_window = wl_egl_window_create(state.wl_surface, state.width, state.height); - EGLSurface surface = eglCreatePlatformWindowSurfaceEXT(egl_dpy, cfg, egl_window, NULL); - assert (surface != EGL_NO_SURFACE); - - res = eglMakeCurrent (egl_dpy, surface, surface, core_ctx); - assert (res); - - - - /* */ + egl_create_window(&state); + egl_create_context(&state); struct wl_callback *cb = wl_surface_frame(state.wl_surface); wl_callback_add_listener(cb, &wl_surface_frame_listener, &state); |