/* for nanosleep */ #define _POSIX_C_SOURCE 199309L #include /*nanosleep*/ #include /*malloc*/ #include /*fprintf*/ #include #include /*graphic context*/ #include #include #include "../headers/backend_resources/xdg-shell.h" #include "../headers/glut_backend.h" #include struct client_state { struct wl_display *display; struct wl_registry *registry; struct wl_compositor *compositor; struct xdg_wm_base *xdg_wm_base; struct wl_surface *surface; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; /**/ struct wl_egl_window *egl_window; EGLDisplay egl_display; EGLConfig egl_config; EGLContext egl_context; EGLSurface egl_surface; int32_t width; int32_t height; uint8_t running; }; static struct client_state state; static void global_registry(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version) { struct client_state *state = data; if(!strcmp(interface, wl_compositor_interface.name)) { state->compositor = wl_registry_bind(wl_registry, name, &wl_compositor_interface, version); } else if(!strcmp(interface, xdg_wm_base_interface.name)) { state->xdg_wm_base = wl_registry_bind(wl_registry, name, &xdg_wm_base_interface, version); } } static void global_remove(void *data, struct wl_registry *wl_registry, uint32_t name) { (void) data; (void) wl_registry; (void) name; } static const struct wl_registry_listener registry_listener = { global_registry, global_remove }; static void wm_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) { (void) data; xdg_wm_base_pong(xdg_wm_base, serial); } static const struct xdg_wm_base_listener wm_base_listener = { wm_ping }; static void surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { (void) data; xdg_surface_ack_configure(xdg_surface, serial); } static const struct xdg_surface_listener surface_listener = { surface_configure }; /******************************/ /********XDG Toplevel**********/ /******************************/ static void toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) { struct client_state *state = data; (void) xdg_toplevel; (void) states; if(!width && !height) return; if(state->width != width || state->height != height) { state->width = width; state->height = height; wl_egl_window_resize(state->egl_window, width, height, 0, 0); wl_surface_commit(state->surface); } } static void toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) { (void) xdg_toplevel; struct client_state *state = data; state->running = 0; } static const struct xdg_toplevel_listener toplevel_listener = { toplevel_configure, toplevel_close }; static void wayland_connect(struct client_state *state) { state->display = wl_display_connect(NULL); if(!state->display) { fprintf(stderr, "Couldn't connect to wayland display\n"); exit(EXIT_FAILURE); } state->registry = wl_display_get_registry(state->display); wl_registry_add_listener(state->registry, ®istry_listener, state); wl_display_roundtrip(state->display); if(!state->compositor || !state->xdg_wm_base) { fprintf(stderr, "Couldn't find compositor or xdg shell\n"); exit(EXIT_FAILURE); } xdg_wm_base_add_listener(state->xdg_wm_base, &wm_base_listener, NULL); state->surface = wl_compositor_create_surface(state->compositor); state->xdg_surface = xdg_wm_base_get_xdg_surface(state->xdg_wm_base, state->surface); xdg_surface_add_listener(state->xdg_surface, &surface_listener, NULL); state->xdg_toplevel = xdg_surface_get_toplevel(state->xdg_surface); xdg_toplevel_set_title(state->xdg_toplevel, "Hello World"); xdg_toplevel_add_listener(state->xdg_toplevel, &toplevel_listener, state); wl_surface_commit(state->surface); } /**/ static void egl_init(struct client_state *state) { EGLint major; EGLint minor; EGLint num_configs; /* replaced EGL_OPENGL_BIT with EGL_OPENGL_ES2_BIT */ EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; state->egl_window = wl_egl_window_create(state->surface, state->width, state->height); state->egl_display = eglGetDisplay((EGLNativeDisplayType) state->display); if(state->display == EGL_NO_DISPLAY) { fprintf(stderr, "Couldn't get EGL display\n"); exit(EXIT_FAILURE); } if(eglInitialize(state->egl_display, &major, &minor) != EGL_TRUE) { fprintf(stderr, "Couldnt initialize EGL\n"); exit(EXIT_FAILURE); } if(eglChooseConfig(state->egl_display, attribs, &state->egl_config, 1, &num_configs) != EGL_TRUE) { fprintf(stderr, "CouldnÄt find matching EGL config\n"); exit(EXIT_FAILURE); } state->egl_surface = eglCreateWindowSurface(state->egl_display, state->egl_config, (EGLNativeWindowType) state->egl_window, NULL); if(state->egl_surface == EGL_NO_SURFACE) { fprintf(stderr, "Couldn't create EGL surface\n"); exit(EXIT_FAILURE); } /* added from https://stackoverflow.com/questions/25843368/glgetstringgl-version-returns-opengl-es-cm-1-1-but-my-phone-supports-opengl */ const EGLint context_attrib_list[] = { // request a context using Open GL ES 2.0 EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; /*thanks to the dudes of stackoverflow for explaining how the attrib_list works*/ state->egl_context = eglCreateContext(state->egl_display, state->egl_config, EGL_NO_CONTEXT, context_attrib_list); if(state->egl_context == EGL_NO_CONTEXT) { fprintf(stderr, "Couldn't create EGL context\n"); exit(EXIT_FAILURE); } if(!eglMakeCurrent(state->egl_display, state->egl_surface, state->egl_surface, state->egl_context)) { fprintf(stderr, "Couldn't make EGL context current\n"); exit(EXIT_FAILURE); } } /* refer to demo_2_egl */ void init_implementation( char **paths, int count){ device_handler_init(); for( int i = 0; i < count; i++){ device_handler_add(paths[i]); } } int create_window_implementation( const char *title){ state.running = 1; wayland_connect(&state); /* */ egl_init(&state); } void init_window_size_implementation( int width, int height){ state.width = width; state.height = height; } /* BAD implementation : perpetual malloc and free */ void sleep_implementation(){ /* the second field should be the remainder, in case of premature ending */ struct timespec *millisecond = malloc( sizeof( struct timespec)); millisecond->tv_sec=0; millisecond->tv_nsec=1e6; nanosleep( millisecond, NULL); /*won't compensate any delay due to the loop body*/ free(millisecond); } void swap_buffers_implementation(){ /* should not be here (glued) */ wl_display_dispatch_pending(state.display); eglSwapBuffers( state.egl_display, state.egl_surface); }