5 #include <GL/freeglut.h>
11 #include <sys/select.h>
19 #define post_redisplay() do { glutPostRedisplay(); redisp_pending = 1; } while(0)
21 static void jobdone(unsigned int job, struct erb_rect *rect, void *cls);
22 static void display(void);
23 static void reshape(int x, int y);
24 static void keyb(unsigned char key, int x, int y);
25 static void mouse(int bn, int st, int x, int y);
26 static void motion(int x, int y);
28 static void dummy_idle(void) {}
30 static int win_width, win_height;
31 static float win_aspect;
32 static int reshape_pending, redisp_pending;
35 static struct erb_rend *erb;
37 static int mouse_x, mouse_y;
38 static int drag_x, drag_y;
41 static float disp_gamma = 2.2f;
43 static unsigned int fbtex;
44 static unsigned int sdr;
46 static const char *vs_src =
49 " gl_Position = ftransform();\n"
50 " gl_TexCoord[0] = gl_MultiTexCoord0;\n"
53 static const char *ps_src =
54 "uniform sampler2D tex;\n"
55 "uniform float inv_gamma;\n"
59 " vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n"
60 " gl_FragColor.rgb = pow(texel.xyz / texel.w, vec3(inv_gamma));\n"
61 " gl_FragColor.a = 1.0;\n"
65 int main(int argc, char **argv)
75 glutInit(&argc, argv);
76 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
77 glutInitWindowSize(1280, 800);
78 glutCreateWindow("X erebus");
80 glutDisplayFunc(display);
81 glutIdleFunc(dummy_idle); /* we want to be blocking in select, not in glutMainLoopEvent */
82 glutReshapeFunc(reshape);
83 glutKeyboardFunc(keyb);
85 glutMotionFunc(motion);
87 if(!(vs = create_vertex_shader(vs_src))) {
90 if(!(ps = create_pixel_shader(ps_src))) {
93 if(!(sdr = create_program_link(vs, ps, 0))) {
96 set_uniform_float(sdr, "inv_gamma", 1.0f / disp_gamma);
98 if(!(erb = erb_create())) {
101 erb_set_done_callback(erb, jobdone, 0);
103 reshape_pending = redisp_pending = 1;
105 glGenTextures(1, &fbtex);
106 glBindTexture(GL_TEXTURE_2D, fbtex);
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
111 dpy = glXGetCurrentDisplay();
112 xfd = ConnectionNumber(dpy);
113 maxfd = xfd > pfd[0] ? xfd : pfd[0];
116 struct timeval tv = {0, 0};
121 FD_SET(pfd[0], &rdset);
123 if(select(maxfd + 1, &rdset, 0, 0, redisp_pending ? &tv : 0) == -1) {
124 if(errno == EINTR) continue;
125 fprintf(stderr, "select failed: %s\n", strerror(errno));
129 if(FD_ISSET(pfd[0], &rdset)) {
130 struct erb_rect rect;
131 read(pfd[0], &rect, sizeof rect);
132 glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.w, rect.h,
133 GL_RGBA, GL_FLOAT, erb_getframe(erb) + (rect.y * win_width + rect.x) * 4);
137 if(FD_ISSET(xfd, &rdset) || redisp_pending) {
142 #endif /* __unix__ */
148 static void jobdone(unsigned int job, struct erb_rect *rect, void *cls)
150 write(pfd[1], rect, sizeof *rect);
153 static void display(void)
155 if(reshape_pending) {
158 erb_allocframe(erb, win_width, win_height);
161 glPixelStorei(GL_UNPACK_ROW_LENGTH, win_width);
163 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, win_width, win_height, 0,
164 GL_RGBA, GL_FLOAT, erb_getframe(erb));
167 glClear(GL_COLOR_BUFFER_BIT);
176 glVertex2f(win_width, 0);
178 glVertex2f(win_width, win_height);
180 glVertex2f(0, win_height);
186 glEnable(GL_LOGIC_OP);
189 glBegin(GL_LINE_LOOP);
191 glVertex2f(drag_x, drag_y);
192 glVertex2f(mouse_x, drag_y);
193 glVertex2f(mouse_x, mouse_y);
194 glVertex2f(drag_x, mouse_y);
197 glDisable(GL_LOGIC_OP);
203 static void reshape(int x, int y)
207 win_aspect = (float)x / (float)y;
209 glViewport(0, 0, x, y);
211 glMatrixMode(GL_PROJECTION);
213 glOrtho(0, x, y, 0, -1, 1);
219 static void keyb(unsigned char key, int x, int y)
228 static void mouse(int bn, int st, int x, int y)
236 if(st == GLUT_DOWN) {
244 rect[0] = x < drag_x ? x : drag_x;
245 rect[1] = y < drag_y ? y : drag_y;
246 rect[2] = abs(x - drag_x);
247 rect[3] = abs(y - drag_y);
249 erb_queue_block(erb, 0, rect[0], rect[1], rect[2], rect[3]);
250 printf("rect: %d,%d %dx%d\n", rect[0], rect[1], rect[2], rect[3]);
256 if(bn == 2 && st == GLUT_DOWN) {
262 static void motion(int x, int y)