doorbell

view spycam/src/main.cc @ 1:daade2a35e69

holy fuck the rpi sucks balls
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 08 Mar 2016 02:28:08 +0000
parents a5755687dd75
children
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/select.h>
5 #include <X11/Xlib.h>
6 #include <X11/Xutil.h>
7 #include <X11/Xatom.h>
8 #include <GLES2/gl2.h>
9 #include <EGL/egl.h>
10 #include "spycam.h"
12 static void cleanup();
13 static bool create_glwin(int xsz, int ysz);
14 static bool handle_event(XEvent *ev);
15 static void set_window_title(const char *title);
17 static int win_width, win_height;
18 static bool quit, redraw_pending;
19 static Display *dpy;
20 static Window win;
21 static EGLDisplay egl_dpy;
22 static EGLContext egl_ctx;
23 static EGLSurface egl_win;
24 static Atom xa_wm_proto, xa_del_window;
26 int main(int argc, char **argv)
27 {
28 if(!(dpy = XOpenDisplay(0))) {
29 fprintf(stderr, "failed to connect to the X server.\n");
30 return 1;
31 }
32 xa_wm_proto = XInternAtom(dpy, "WM_PROTOCOLS", False);
33 xa_del_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
35 egl_dpy = eglGetDisplay(dpy);
36 int egl_ver_major, egl_ver_minor;
37 if(!eglInitialize(egl_dpy, &egl_ver_major, &egl_ver_minor)) {
38 fprintf(stderr, "failed to initialize EGL\n");
39 return 1;
40 }
41 printf("initialized EGL %d.%d\n", egl_ver_major, egl_ver_minor);
43 if(!create_glwin(800, 600)) {
44 cleanup();
45 return 1;
46 }
48 if(!app_init()) {
49 cleanup();
50 return 1;
51 }
53 for(;;) {
54 while(XPending(dpy) || !redraw_pending) {
55 XEvent ev;
56 XNextEvent(dpy, &ev);
57 if(!handle_event(&ev) || quit) {
58 goto break_main_loop;
59 }
60 }
62 if(redraw_pending) {
63 app_draw();
64 eglSwapBuffers(egl_dpy, egl_win);
65 }
66 }
67 break_main_loop:
69 cleanup();
70 return 0;
71 }
73 void app_quit()
74 {
75 quit = true;
76 }
78 void app_redisplay()
79 {
80 redraw_pending = true;
81 }
83 static void cleanup()
84 {
85 if(egl_dpy) {
86 eglMakeCurrent(egl_dpy, 0, 0, 0);
87 if(egl_win)
88 eglDestroySurface(egl_dpy, egl_win);
89 if(egl_ctx)
90 eglDestroyContext(egl_dpy, egl_ctx);
91 eglTerminate(egl_dpy);
92 }
93 if(dpy) {
94 if(win)
95 XDestroyWindow(dpy, win);
96 XCloseDisplay(dpy);
97 }
98 }
100 static bool create_glwin(int xsz, int ysz)
101 {
102 static const int egl_attr[] = {
103 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
104 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
105 EGL_RED_SIZE, 5,
106 EGL_GREEN_SIZE, 5,
107 EGL_BLUE_SIZE, 5,
108 EGL_DEPTH_SIZE, 16,
109 EGL_NONE
110 };
112 int scr = DefaultScreen(dpy);
113 Window root_win = RootWindow(dpy, scr);
115 EGLConfig cfg;
116 int num_cfg;
117 if(!eglChooseConfig(egl_dpy, egl_attr, &cfg, 1, &num_cfg)) {
118 fprintf(stderr, "failed to find matching EGL visual\n");
119 return false;
120 }
121 int rsize, gsize, bsize, zsize, ssize, vis_id;
122 eglGetConfigAttrib(egl_dpy, cfg, EGL_RED_SIZE, &rsize);
123 eglGetConfigAttrib(egl_dpy, cfg, EGL_GREEN_SIZE, &gsize);
124 eglGetConfigAttrib(egl_dpy, cfg, EGL_BLUE_SIZE, &bsize);
125 eglGetConfigAttrib(egl_dpy, cfg, EGL_DEPTH_SIZE, &zsize);
126 eglGetConfigAttrib(egl_dpy, cfg, EGL_STENCIL_SIZE, &ssize);
127 eglGetConfigAttrib(egl_dpy, cfg, EGL_NATIVE_VISUAL_ID, &vis_id);
128 printf("got visual %d: %d bpp (%d%d%d), %d zbuffer, %d stencil\n", vis_id, rsize + gsize + bsize,
129 rsize, gsize, bsize, zsize, ssize);
131 int num_vis;
132 XVisualInfo *vis_info, vis_template;
133 vis_template.visualid = vis_id;
134 if(!(vis_info = XGetVisualInfo(dpy, VisualIDMask, &vis_template, &num_vis))) {
135 fprintf(stderr, "visual id %d is invalid (?!)\n", vis_id);
136 return false;
137 }
139 XSetWindowAttributes xattr;
140 xattr.border_pixel = xattr.backing_pixel = BlackPixel(dpy, scr);
141 xattr.colormap = XCreateColormap(dpy, root_win, vis_info->visual, AllocNone);
142 unsigned int xattr_mask = CWColormap | CWBorderPixel | CWBackPixel;
144 win = XCreateWindow(dpy, root_win, 0, 0, xsz, ysz, 0, vis_info->depth, InputOutput,
145 vis_info->visual, xattr_mask, &xattr);
146 if(!win) {
147 fprintf(stderr, "failed to create window\n");
148 XFree(vis_info);
149 return false;
150 }
151 XFree(vis_info);
152 XSelectInput(dpy, win, ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask);
154 XSetWMProtocols(dpy, win, &xa_del_window, 1);
155 set_window_title("spycam");
157 eglBindAPI(EGL_OPENGL_ES_API);
159 if(!(egl_win = eglCreateWindowSurface(egl_dpy, cfg, win, 0))) {
160 fprintf(stderr, "failed to create EGL window\n");
161 XDestroyWindow(dpy, win);
162 return false;
163 }
165 static const int ctxattr[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
166 if(!(egl_ctx = eglCreateContext(egl_dpy, cfg, EGL_NO_CONTEXT, ctxattr))) {
167 fprintf(stderr, "failed to create EGL context\n");
168 eglDestroySurface(egl_dpy, egl_win);
169 XDestroyWindow(dpy, win);
170 return false;
171 }
172 eglMakeCurrent(egl_dpy, egl_win, egl_win, egl_ctx);
174 XMapWindow(dpy, win);
176 eglQuerySurface(dpy, egl_win, EGL_WIDTH, &win_width);
177 eglQuerySurface(dpy, egl_win, EGL_HEIGHT, &win_height);
178 app_reshape(win_width, win_height);
180 return true;
181 }
183 static bool handle_event(XEvent *ev)
184 {
185 static bool mapped;
187 switch(ev->type) {
188 case Expose:
189 if(mapped) {
190 redraw_pending = true;
191 }
192 break;
194 case MapNotify:
195 mapped = true;
196 redraw_pending = true;
197 break;
199 case UnmapNotify:
200 mapped = false;
201 redraw_pending = false;
202 break;
204 case ConfigureNotify:
205 if(win_width != (int)ev->xconfigure.width || win_height != (int)ev->xconfigure.height) {
206 win_width = ev->xconfigure.width;
207 win_height = ev->xconfigure.height;
208 app_reshape(win_width, win_height);
209 }
210 break;
212 case KeyPress:
213 case KeyRelease:
214 app_keyboard(XLookupKeysym(&ev->xkey, 0) & 0xff, ev->type == KeyPress);
215 break;
217 case ClientMessage:
218 if(ev->xclient.message_type == xa_wm_proto &&
219 (Atom)ev->xclient.data.l[0] == xa_del_window) {
220 return false;
221 }
222 break;
224 default:
225 break;
226 }
227 return true;
228 }
230 static void set_window_title(const char *title)
231 {
232 XTextProperty text_prop;
233 XStringListToTextProperty((char**)&title, 1, &text_prop);
234 XSetWMName(dpy, win, &text_prop);
235 XSetWMIconName(dpy, win, &text_prop);
236 XFree(text_prop.value);
237 }