#include #include #include #include #include #include "x_opengl.h" #include "app_ipc.h" #include "util.h" #include "boinc_gl.h" #include "graphics_api.h" #include "graphics_impl.h" #define BOINC_WINDOW_CLASS_NAME "BOINC_app" #define TIMER_INTERVAL_MSEC 30 static bool visible = true; static int current_graphics_mode = MODE_HIDE_GRAPHICS; static int acked_graphics_mode; static int xpos = 100, ypos = 100; static int clicked_button; static int win=0; static void set_mode(int mode); static APP_INIT_DATA aid; // This callback is invoked when a user presses a key. // void keyboardD(unsigned char key, int x, int y) { if (current_graphics_mode == MODE_FULLSCREEN) { set_mode(MODE_HIDE_GRAPHICS); } } void keyboardU(unsigned char key, int x, int y) { if (current_graphics_mode == MODE_FULLSCREEN) { set_mode(MODE_HIDE_GRAPHICS); } } void mouse_click(int button, int state, int x, int y){ clicked_button = button; if (current_graphics_mode == MODE_FULLSCREEN) { set_mode(MODE_HIDE_GRAPHICS); } else { if (state) { boinc_app_mouse_button(x, y, button, false); } else { boinc_app_mouse_button(x, y, button, true); } } } void mouse_click_move(int x, int y){ if (current_graphics_mode == MODE_FULLSCREEN){ set_mode(MODE_HIDE_GRAPHICS); } else if (clicked_button == 2){ boinc_app_mouse_move(x, y, false, false, true); } else if (clicked_button == 1){ boinc_app_mouse_move(x, y, false, true, false); } else if (clicked_button == 0){ boinc_app_mouse_move(x, y, true, false, false); } else{ boinc_app_mouse_move(x, y, false, false, false); } } static void maybe_render() { int width, height; if (visible && (current_graphics_mode != MODE_HIDE_GRAPHICS)) { width = glutGet(GLUT_WINDOW_WIDTH); height = glutGet(GLUT_WINDOW_HEIGHT); if (throttled_app_render(width, height, dtime())) { glutSwapBuffers(); } } } static void close_func() { if (bmsp->boinc_is_standalone_hook()) { exit(0); } else { set_mode(MODE_HIDE_GRAPHICS); } } static void make_new_window(int mode){ char* args[] = {"foobar", 0}; int one=1; static bool first=true; if (mode == MODE_WINDOW || mode == MODE_FULLSCREEN){ if (first) { glutInit(&one, args); first = false; } glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowPosition(xpos, ypos); glutInitWindowSize(600, 400); bmsp->boinc_get_init_data_hook(aid); if (!strlen(aid.app_name)) { strcpy(aid.app_name, "BOINC Application"); } win = glutCreateWindow(aid.app_name); glutReshapeFunc(app_graphics_resize); glutKeyboardFunc(keyboardD); glutKeyboardUpFunc(keyboardU); glutMouseFunc(mouse_click); glutMotionFunc(mouse_click_move); glutDisplayFunc(maybe_render); app_graphics_init(); glEnable(GL_DEPTH_TEST); if (mode == MODE_FULLSCREEN) { glutFullScreen(); } } } void KillWindow() { if (win) { glutDestroyWindow(win); win = 0; } } void set_mode(int mode) { if (mode == current_graphics_mode) return; KillWindow(); current_graphics_mode = mode; if (mode != MODE_HIDE_GRAPHICS) { make_new_window(mode); } } static void wait_for_initial_message() { bmsp->app_client_shm->shm->graphics_reply.send_msg( xml_graphics_modes[MODE_HIDE_GRAPHICS] ); acked_graphics_mode = MODE_HIDE_GRAPHICS; while (1) { if (bmsp->app_client_shm->shm->graphics_request.has_msg()) { break; } sleep(1); } } static void timer_handler(int) { char buf[MSG_CHANNEL_SIZE]; GRAPHICS_MSG m; int new_mode; if (bmsp->app_client_shm) { if (bmsp->app_client_shm->shm->graphics_request.get_msg(buf)) { bmsp->app_client_shm->decode_graphics_msg(buf, m); switch (m.mode) { case MODE_REREAD_PREFS: //only reread graphics prefs if we have a window open // switch (current_graphics_mode){ case MODE_WINDOW: case MODE_FULLSCREEN: app_graphics_reread_prefs(); break; } break; case MODE_HIDE_GRAPHICS: case MODE_WINDOW: case MODE_FULLSCREEN: case MODE_BLANKSCREEN: set_mode(m.mode); break; } } if (acked_graphics_mode != current_graphics_mode) { bool sent = bmsp->app_client_shm->shm->graphics_reply.send_msg( xml_graphics_modes[current_graphics_mode] ); if (sent) acked_graphics_mode = current_graphics_mode; } } maybe_render(); glutTimerFunc(TIMER_INTERVAL_MSEC, timer_handler, 0); } static jmp_buf jbuf; static pthread_t graphics_thread; void restart() { if (pthread_equal(pthread_self(), graphics_thread)) { atexit(restart); longjmp(jbuf, 1); } } void xwin_graphics_event_loop() { graphics_thread = pthread_self(); if (bmsp->boinc_is_standalone_hook()) { set_mode(MODE_WINDOW); } else { wait_for_initial_message(); timer_handler(0); atexit(restart); } int retval = setjmp(jbuf); if (retval) { //fprintf(stderr, "graphics thread restarted\n"); fflush(stderr); set_mode(MODE_HIDE_GRAPHICS); } glutTimerFunc(TIMER_INTERVAL_MSEC, timer_handler, 0); glutMainLoop(); } #ifdef __GNUC__ static volatile const char __attribute__((unused)) *BOINCrcsid="$Id$"; #else static volatile const char *BOINCrcsid="$Id$"; #endif