doorbell

diff spycam/src/main.cc @ 0:a5755687dd75

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 08 Mar 2016 03:26:01 +0200
parents
children daade2a35e69
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/spycam/src/main.cc	Tue Mar 08 03:26:01 2016 +0200
     1.3 @@ -0,0 +1,236 @@
     1.4 +#include <stdio.h>
     1.5 +#include <stdlib.h>
     1.6 +#include <unistd.h>
     1.7 +#include <sys/select.h>
     1.8 +#include <X11/Xlib.h>
     1.9 +#include <X11/Xatom.h>
    1.10 +#include <GLES2/gl2.h>
    1.11 +#include <EGL/egl.h>
    1.12 +#include "spycam.h"
    1.13 +
    1.14 +static void cleanup();
    1.15 +static bool create_glwin(int xsz, int ysz);
    1.16 +static bool handle_event(XEvent *ev);
    1.17 +static void set_window_title(const char *title);
    1.18 +
    1.19 +static int win_width, win_height;
    1.20 +static bool quit, redraw_pending;
    1.21 +static Display *dpy;
    1.22 +static Window win;
    1.23 +static EGLDisplay egl_dpy;
    1.24 +static EGLContext egl_ctx;
    1.25 +static EGLSurface egl_win;
    1.26 +static Atom xa_wm_proto, xa_del_window;
    1.27 +
    1.28 +int main(int argc, char **argv)
    1.29 +{
    1.30 +	if(!(dpy = XOpenDisplay(0))) {
    1.31 +		fprintf(stderr, "failed to connect to the X server.\n");
    1.32 +		return 1;
    1.33 +	}
    1.34 +	xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", False);
    1.35 +	xa_del_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
    1.36 +
    1.37 +	egl_dpy = eglGetDisplay(dpy);
    1.38 +	int egl_ver_major, egl_ver_minor;
    1.39 +	if(!eglInitialize(egl_dpy, &egl_ver_major, &egl_ver_minor)) {
    1.40 +		fprintf(stderr, "failed to initialize EGL\n");
    1.41 +		return 1;
    1.42 +	}
    1.43 +	printf("initialized EGL %d.%d\n", egl_ver_major, egl_ver_minor);
    1.44 +
    1.45 +	if(!create_glwin(800, 600)) {
    1.46 +		cleanup();
    1.47 +		return 1;
    1.48 +	}
    1.49 +
    1.50 +	if(!app_init()) {
    1.51 +		cleanup();
    1.52 +		return 1;
    1.53 +	}
    1.54 +
    1.55 +	for(;;) {
    1.56 +		while(XPending(dpy) || !redraw_pending) {
    1.57 +			XEvent ev;
    1.58 +			XNextEvent(dpy, &ev);
    1.59 +			if(!handle_event(&ev) || quit) {
    1.60 +				goto break_main_loop;
    1.61 +			}
    1.62 +		}
    1.63 +
    1.64 +		if(redraw_pending) {
    1.65 +			app_draw();
    1.66 +			eglSwapBuffers(egl_dpy, egl_win);
    1.67 +		}
    1.68 +	}
    1.69 +break_main_loop:
    1.70 +
    1.71 +	cleanup();
    1.72 +	return 0;
    1.73 +}
    1.74 +
    1.75 +void app_quit()
    1.76 +{
    1.77 +	quit = true;
    1.78 +}
    1.79 +
    1.80 +void app_redisplay()
    1.81 +{
    1.82 +	redraw_pending = true;
    1.83 +}
    1.84 +
    1.85 +static void cleanup()
    1.86 +{
    1.87 +	if(egl_dpy) {
    1.88 +		eglMakeCurrent(egl_dpy, 0, 0, 0);
    1.89 +		if(egl_win)
    1.90 +			eglDestroySurface(egl_dpy, egl_win);
    1.91 +		if(egl_ctx)
    1.92 +			eglDestroyContext(egl_dpy, egl_ctx);
    1.93 +		eglTerminate(egl_dpy);
    1.94 +	}
    1.95 +	if(dpy) {
    1.96 +		if(win)
    1.97 +			XDestroyWindow(dpy, win);
    1.98 +		XCloseDisplay(dpy);
    1.99 +	}
   1.100 +}
   1.101 +
   1.102 +static bool create_glwin(int xsz, int ysz)
   1.103 +{
   1.104 +	static const int egl_attr[] = {
   1.105 +		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
   1.106 +		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
   1.107 +		EGL_RED_SIZE, 5,
   1.108 +		EGL_GREEN_SIZE, 5,
   1.109 +		EGL_BLUE_SIZE, 5,
   1.110 +		EGL_DEPTH_SIZE, 16,
   1.111 +		EGL_NONE
   1.112 +	};
   1.113 +
   1.114 +	int scr = DefaultScreen(dpy);
   1.115 +	Window root_win = RootWindow(dpy, scr);
   1.116 +
   1.117 +	EGLConfig cfg;
   1.118 +	int num_cfg;
   1.119 +	if(!eglChooseConfig(egl_dpy, egl_attr, &cfg, 1, &num_cfg)) {
   1.120 +		fprintf(stderr, "failed to find matching EGL visual\n");
   1.121 +		return false;
   1.122 +	}
   1.123 +	int rsize, gsize, bsize, zsize, ssize, vis_id;
   1.124 +	eglGetConfigAttrib(egl_dpy, cfg, EGL_RED_SIZE, &rsize);
   1.125 +	eglGetConfigAttrib(egl_dpy, cfg, EGL_GREEN_SIZE, &gsize);
   1.126 +	eglGetConfigAttrib(egl_dpy, cfg, EGL_BLUE_SIZE, &bsize);
   1.127 +	eglGetConfigAttrib(egl_dpy, cfg, EGL_DEPTH_SIZE, &zsize);
   1.128 +	eglGetConfigAttrib(egl_dpy, cfg, EGL_STENCIL_SIZE, &ssize);
   1.129 +	eglGetConfigAttrib(egl_dpy, cfg, EGL_NATIVE_VISUAL_ID, &vis_id);
   1.130 +	printf("got visual %d: %d bpp (%d%d%d), %d zbuffer, %d stencil\n", vis_id, rsize + gsize + bsize,
   1.131 +			rsize, gsize, bsize, zsize, ssize);
   1.132 +
   1.133 +	int num_vis;
   1.134 +	XVisualInfo *vis_info, vis_template;
   1.135 +	vis_template.visualid = vis_id;
   1.136 +	if(!(vis_info = XGetVisualInfo(dpy, VisualIDMask, &vis_template, &num_vis))) {
   1.137 +		fprintf(stderr, "visual id %d is invalid (?!)\n", vis_id);
   1.138 +		return false;
   1.139 +	}
   1.140 +
   1.141 +	XSetWindowAttributes xattr;
   1.142 +	xattr.border_pixel = xattr.backing_pixel = BlackPixel(dpy, scr);
   1.143 +	xattr.colormap = XCreateColormap(dpy, root_win, vis_info->visual, AllocNone);
   1.144 +	unsigned int xattr_mask = CWColormap | CWBorderPixel | CWBackPixel;
   1.145 +
   1.146 +	win = XCreateWindow(dpy, root_win, 0, 0, xsz, ysz, 0, vis_info->depth, InputOutput,
   1.147 +			vis_info->visual, xattr_mask, &xattr);
   1.148 +	if(!win) {
   1.149 +		fprintf(stderr, "failed to create window\n");
   1.150 +		XFree(vis_info);
   1.151 +		return false;
   1.152 +	}
   1.153 +	XFree(vis_info);
   1.154 +	XSelectInput(dpy, win, ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask);
   1.155 +
   1.156 +	XSetWMProtocols(dpy, win, &xa_del_window, 1);
   1.157 +	set_window_title("spycam");
   1.158 +
   1.159 +	eglBindAPI(EGL_OPENGL_ES_API);
   1.160 +
   1.161 +	if(!(egl_win = eglCreateWindowSurface(egl_dpy, cfg, win, 0))) {
   1.162 +		fprintf(stderr, "failed to create EGL window\n");
   1.163 +		XDestroyWindow(dpy, win);
   1.164 +		return false;
   1.165 +	}
   1.166 +
   1.167 +	static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
   1.168 +	if(!(egl_ctx = eglCreateContext(egl_dpy, cfg, EGL_NO_CONTEXT, ctxattr))) {
   1.169 +		fprintf(stderr, "failed to create EGL context\n");
   1.170 +		eglDestroySurface(egl_dpy, egl_win);
   1.171 +		XDestroyWindow(dpy, win);
   1.172 +		return false;
   1.173 +	}
   1.174 +	eglMakeCurrent(egl_dpy, egl_win, egl_win, egl_ctx);
   1.175 +
   1.176 +	XMapWindow(dpy, win);
   1.177 +
   1.178 +	eglQuerySurface(dpy, egl_win, EGL_WIDTH, &win_width);
   1.179 +	eglQuerySurface(dpy, egl_win, EGL_HEIGHT, &win_height);
   1.180 +	app_reshape(win_width, win_height);
   1.181 +
   1.182 +	return true;
   1.183 +}
   1.184 +
   1.185 +static bool handle_event(XEvent *ev)
   1.186 +{
   1.187 +	static bool mapped;
   1.188 +
   1.189 +	switch(ev->type) {
   1.190 +	case Expose:
   1.191 +		if(mapped) {
   1.192 +			redraw_pending = true;
   1.193 +		}
   1.194 +		break;
   1.195 +
   1.196 +	case MapNotify:
   1.197 +		mapped = true;
   1.198 +		redraw_pending = true;
   1.199 +		break;
   1.200 +
   1.201 +	case UnmapNotify:
   1.202 +		mapped = false;
   1.203 +		redraw_pending = false;
   1.204 +		break;
   1.205 +
   1.206 +	case ConfigureNotify:
   1.207 +		if(win_width != (int)ev->xconfigure.width || win_height != (int)ev->xconfigure.height) {
   1.208 +			win_width = ev->xconfigure.width;
   1.209 +			win_height = ev->xconfigure.height;
   1.210 +			app_reshape(win_width, win_height);
   1.211 +		}
   1.212 +		break;
   1.213 +
   1.214 +	case KeyPress:
   1.215 +	case KeyRelease:
   1.216 +		app_keyboard(XLookupKeysym(&ev->xkey, 0) & 0xff, ev->type == KeyPress);
   1.217 +		break;
   1.218 +
   1.219 +	case ClientMessage:
   1.220 +		if(ev->xclient.message_type == xa_wm_proto &&
   1.221 +				(Atom)ev->xclient.data.l[0] == xa_del_window) {
   1.222 +			return false;
   1.223 +		}
   1.224 +		break;
   1.225 +
   1.226 +	default:
   1.227 +		break;
   1.228 +	}
   1.229 +	return true;
   1.230 +}
   1.231 +
   1.232 +static void set_window_title(const char *title)
   1.233 +{
   1.234 +	XTextProperty text_prop;
   1.235 +	XStringListToTextProperty((char**)&title, 1, &text_prop);
   1.236 +	XSetWMName(dpy, win, &text_prop);
   1.237 +	XSetWMIconName(dpy, win, &text_prop);
   1.238 +	XFree(text_prop.value);
   1.239 +}