X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=xerebus%2Fsrc%2Fmain.c;h=0eda94d4569bf92c0e3ea6ff0bf1a80f45f78c06;hb=7572b3ea92bec83c2a256eb1d6c1b0b77233c6b9;hp=3fed7e60ca234b92048f733711dcc95f33b4f413;hpb=c8b13dff969d8104c178d9362aa21cefb9d61fe8;p=erebus2020 diff --git a/xerebus/src/main.c b/xerebus/src/main.c index 3fed7e6..0eda94d 100644 --- a/xerebus/src/main.c +++ b/xerebus/src/main.c @@ -1,6 +1,268 @@ #include +#include +#include +#include "opengl.h" +#include +#include "erebus.h" +#include "sdr.h" + +#ifdef __unix__ +#include +#include +#include +#include + +static Display *dpy; +static int pfd[2]; +#endif + +#define post_redisplay() do { glutPostRedisplay(); redisp_pending = 1; } while(0) + +static void jobdone(unsigned int job, struct erb_rect *rect, void *cls); +static void display(void); +static void reshape(int x, int y); +static void keyb(unsigned char key, int x, int y); +static void mouse(int bn, int st, int x, int y); +static void motion(int x, int y); + +static void dummy_idle(void) {} + +static int win_width, win_height; +static float win_aspect; +static int reshape_pending, redisp_pending; +static int quit; + +static struct erb_rend *erb; + +static int mouse_x, mouse_y; +static int drag_x, drag_y; +static int drag; + +static float disp_gamma = 2.2f; + +static unsigned int fbtex; +static unsigned int sdr; + +static const char *vs_src = + "void main()\n" + "{\n" + " gl_Position = ftransform();\n" + " gl_TexCoord[0] = gl_MultiTexCoord0;\n" + "}\n"; + +static const char *ps_src = + "uniform sampler2D tex;\n" + "uniform float inv_gamma;\n" + "\n" + "void main()\n" + "{\n" + " vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" + " gl_FragColor.rgb = pow(texel.xyz / texel.w, vec3(inv_gamma));\n" + " gl_FragColor.a = 1.0;\n" + "}\n"; + int main(int argc, char **argv) { + unsigned int vs, ps; + +#ifdef __unix__ + int xfd, maxfd; + + pipe(pfd); +#endif + + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + glutInitWindowSize(1280, 800); + glutCreateWindow("X erebus"); + + glutDisplayFunc(display); + glutIdleFunc(dummy_idle); /* we want to be blocking in select, not in glutMainLoopEvent */ + glutReshapeFunc(reshape); + glutKeyboardFunc(keyb); + glutMouseFunc(mouse); + glutMotionFunc(motion); + + if(!(vs = create_vertex_shader(vs_src))) { + return 1; + } + if(!(ps = create_pixel_shader(ps_src))) { + return 1; + } + if(!(sdr = create_program_link(vs, ps, 0))) { + return 1; + } + set_uniform_float(sdr, "inv_gamma", 1.0f / disp_gamma); + + if(!(erb = erb_create())) { + return 1; + } + erb_set_done_callback(erb, jobdone, 0); + + reshape_pending = redisp_pending = 1; + + glGenTextures(1, &fbtex); + glBindTexture(GL_TEXTURE_2D, fbtex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + +#ifdef __unix__ + dpy = glXGetCurrentDisplay(); + xfd = ConnectionNumber(dpy); + maxfd = xfd > pfd[0] ? xfd : pfd[0]; + + while(!quit) { + struct timeval tv = {0, 0}; + fd_set rdset; + + FD_ZERO(&rdset); + FD_SET(xfd, &rdset); + FD_SET(pfd[0], &rdset); + + if(select(maxfd + 1, &rdset, 0, 0, redisp_pending ? &tv : 0) == -1) { + if(errno == EINTR) continue; + fprintf(stderr, "select failed: %s\n", strerror(errno)); + break; + } + + if(FD_ISSET(pfd[0], &rdset)) { + struct erb_rect rect; + read(pfd[0], &rect, sizeof rect); + glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.w, rect.h, + GL_RGBA, GL_FLOAT, erb_getframe(erb) + (rect.y * win_width + rect.x) * 4); + post_redisplay(); + } + + if(FD_ISSET(xfd, &rdset) || redisp_pending) { + redisp_pending = 0; + glutMainLoopEvent(); + } + } +#endif /* __unix__ */ + + erb_destroy(erb); return 0; } + +static void jobdone(unsigned int job, struct erb_rect *rect, void *cls) +{ + write(pfd[1], rect, sizeof *rect); +} + +static void display(void) +{ + if(reshape_pending) { + reshape_pending = 0; + + erb_allocframe(erb, win_width, win_height); + erb_begin(erb); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, win_width); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, win_width, win_height, 0, + GL_RGBA, GL_FLOAT, erb_getframe(erb)); + } + + glClear(GL_COLOR_BUFFER_BIT); + + glUseProgram(sdr); + + glBegin(GL_QUADS); + glColor3f(1, 1, 1); + glTexCoord2f(0, 0); + glVertex2f(0, 0); + glTexCoord2f(1, 0); + glVertex2f(win_width, 0); + glTexCoord2f(1, 1); + glVertex2f(win_width, win_height); + glTexCoord2f(0, 1); + glVertex2f(0, win_height); + glEnd(); + + if(drag) { + glUseProgram(0); + + glEnable(GL_LOGIC_OP); + glLogicOp(GL_XOR); + + glBegin(GL_LINE_LOOP); + glColor3f(1, 1, 1); + glVertex2f(drag_x, drag_y); + glVertex2f(mouse_x, drag_y); + glVertex2f(mouse_x, mouse_y); + glVertex2f(drag_x, mouse_y); + glEnd(); + + glDisable(GL_LOGIC_OP); + } + + glutSwapBuffers(); +} + +static void reshape(int x, int y) +{ + win_width = x; + win_height = y; + win_aspect = (float)x / (float)y; + + glViewport(0, 0, x, y); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, x, y, 0, -1, 1); + + reshape_pending = 1; + post_redisplay(); +} + +static void keyb(unsigned char key, int x, int y) +{ + if(key == 27) { + glutExit(); + quit = 1; + } + post_redisplay(); +} + +static void mouse(int bn, int st, int x, int y) +{ + int rect[4]; + + mouse_x = x; + mouse_y = y; + + if(bn == 0) { + if(st == GLUT_DOWN) { + drag = 1; + drag_x = x; + drag_y = y; + } else { + if(drag) { + drag = 0; + + rect[0] = x < drag_x ? x : drag_x; + rect[1] = y < drag_y ? y : drag_y; + rect[2] = abs(x - drag_x); + rect[3] = abs(y - drag_y); + + erb_queue_block(erb, 0, rect[0], rect[1], rect[2], rect[3]); + printf("rect: %d,%d %dx%d\n", rect[0], rect[1], rect[2], rect[3]); + } + } + + post_redisplay(); + } + if(bn == 2 && st == GLUT_DOWN) { + drag = 0; + post_redisplay(); + } +} + +static void motion(int x, int y) +{ + mouse_x = x; + mouse_y = y; + + post_redisplay(); +}