project for a (works on my devices) demo
This commit is contained in:
300
sources/glut_backend.c
Normal file
300
sources/glut_backend.c
Normal file
@@ -0,0 +1,300 @@
|
||||
/* for nanosleep */
|
||||
#define _POSIX_C_SOURCE 199309L
|
||||
|
||||
#include <time.h> /*nanosleep*/
|
||||
#include <stdlib.h> /*malloc*/
|
||||
#include <stdio.h> /*fprintf*/
|
||||
#include <string.h>
|
||||
|
||||
#include <EGL/egl.h> /*graphic context*/
|
||||
|
||||
#include <wayland-egl.h>
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include "../headers/backend_resources/xdg-shell.h"
|
||||
|
||||
#include "../headers/glut_backend.h"
|
||||
|
||||
#include <my_device_handler.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user