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);
102 reshape_pending = redisp_pending = 1;
104 glGenTextures(1, &fbtex);
105 glBindTexture(GL_TEXTURE_2D, fbtex);
106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
110 dpy = glXGetCurrentDisplay();
111 xfd = ConnectionNumber(dpy);
112 maxfd = xfd > pfd[0] ? xfd : pfd[0];
115 struct timeval tv = {0, 0};
120 FD_SET(pfd[0], &rdset);
122 if(select(maxfd + 1, &rdset, 0, 0, redisp_pending ? &tv : 0) == -1) {
123 if(errno == EINTR) continue;
124 fprintf(stderr, "select failed: %s\n", strerror(errno));
131 if(FD_ISSET(pfd[0], &rdset)) {
132 struct erb_rect rect;
133 read(pfd[0], &rect, sizeof rect);
134 glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.w, rect.h,
135 GL_RGBA, GL_FLOAT, erb_getframe(erb) + (rect.y * win_width + rect.x) * 4);
137 printf("update (%d %d %dx%d)!\n", rect.x, rect.y, rect.w, rect.h);
140 #endif /* __unix__ */
146 static void jobdone(unsigned int job, struct erb_rect *rect, void *cls)
148 printf("jobdone!\n");
149 write(pfd[1], rect, sizeof *rect);
152 static void display(void)
154 if(reshape_pending) {
157 erb_allocframe(erb, win_width, win_height);
160 glPixelStorei(GL_UNPACK_ROW_LENGTH, win_width);
162 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, win_width, win_height, 0,
163 GL_RGBA, GL_FLOAT, erb_getframe(erb));
166 glClear(GL_COLOR_BUFFER_BIT);
175 glVertex2f(win_width, 0);
177 glVertex2f(win_width, win_height);
179 glVertex2f(0, win_height);
185 glEnable(GL_LOGIC_OP);
188 glBegin(GL_LINE_LOOP);
190 glVertex2f(drag_x, drag_y);
191 glVertex2f(mouse_x, drag_y);
192 glVertex2f(mouse_x, mouse_y);
193 glVertex2f(drag_x, mouse_y);
196 glDisable(GL_LOGIC_OP);
202 static void reshape(int x, int y)
206 win_aspect = (float)x / (float)y;
208 glViewport(0, 0, x, y);
210 glMatrixMode(GL_PROJECTION);
212 glOrtho(0, x, y, 0, -1, 1);
218 static void keyb(unsigned char key, int x, int y)
227 static void mouse(int bn, int st, int x, int y)
235 if(st == GLUT_DOWN) {
243 rect[0] = x < drag_x ? x : drag_x;
244 rect[1] = y < drag_y ? y : drag_y;
245 rect[2] = abs(x - drag_x);
246 rect[3] = abs(y - drag_y);
248 erb_queue_block(erb, 0, rect[0], rect[1], rect[2], rect[3]);
249 printf("rect: %d,%d %dx%d\n", rect[0], rect[1], rect[2], rect[3]);
255 if(bn == 2 && st == GLUT_DOWN) {
261 static void motion(int x, int y)