diff --git a/api/graphics_api.C b/api/graphics_api.C index 1d717c6a65..e4cb5fd69f 100755 --- a/api/graphics_api.C +++ b/api/graphics_api.C @@ -35,6 +35,7 @@ HANDLE graphics_threadh=NULL; #ifndef _WIN32 #include #include +#include "x_opengl.h" #ifdef HAVE_PTHREAD #include @@ -48,7 +49,7 @@ HANDLE graphics_threadh=NULL; #include "filesys.h" #include "boinc_api.h" #include "graphics_api.h" -#include "filesys.h" + double boinc_max_fps = 30.; double boinc_max_gfx_cpu_frac = 0.5; @@ -141,7 +142,7 @@ int boinc_init_graphics() { pthread_attr_t graphics_thread_attr; pthread_attr_init( &graphics_thread_attr ); - retval = pthread_create( &graphics_thread, &graphics_thread_attr, p_graphics_loop, &gi ); + retval = pthread_create( &graphics_thread, &graphics_thread_attr, xwin_graphics_event_loop, &gi ); if (retval) return ERR_THREAD; pthread_attr_destroy( &graphics_thread_attr ); #endif @@ -216,4 +217,3 @@ bool throttled_app_render(int x, int y, double t) { } return false; } - diff --git a/api/reduce.C b/api/reduce.C index 35f0ed18b8..6ca54e33da 100644 --- a/api/reduce.C +++ b/api/reduce.C @@ -16,17 +16,25 @@ #ifdef _WIN32 #include "boinc_win.h" +#include #endif #ifndef _WIN32 +#include +#include +#include +#include +#include "GL/gl.h" +#define max(a,b) (a>b?a:b) +#define min(a,b) (a>b?b:a) + #include #include #include #include #ifdef __APPLE_CC__ -#define max(a,b) (a>b?a:b) -#define min(a,b) (a>b?b:a) +#include #endif #endif diff --git a/api/x_opengl.C b/api/x_opengl.C index 826f9c02de..abc4aa53e5 100644 --- a/api/x_opengl.C +++ b/api/x_opengl.C @@ -3,135 +3,253 @@ #ifdef HAVE_GL #include "boinc_gl.h" - -#include "graphics_api.h" - -void process_input(Display *dpy); -void refresh( void ); -int DrawGLScene(GLvoid); -GLvoid buildFont(GLvoid); - -extern int ok_to_draw; -int win_open; -GLuint main_font; -Display *dpy; -Window win; - -static Bool WaitForNotify(Display *d,XEvent *e,char *arg) { - return(e->type == MapNotify) && (e->xmap.window == (Window)arg); -} - -void *p_graphics_loop( void *duff ) { - XVisualInfo *vi; - Colormap cmap; - XSetWindowAttributes swa; - GLXContext cx; - XEvent event; - GRAPHICS_INFO *gfx; - int attributeList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, - GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16, None}; - - gfx = (GRAPHICS_INFO *)duff; - - /* get a connection */ - dpy = XOpenDisplay(0); - - if (dpy == NULL) { - printf("couldn't open display\n"); - return 0; - } - - /* get an appropriate visual */ - vi = glXChooseVisual(dpy,DefaultScreen(dpy),attributeList); - if (vi == NULL) { - printf("couldn't find the visual \n"); - return 0; - } - - /* create a GLX context */ - if (!(cx = glXCreateContext(dpy,vi,0,GL_FALSE))) { - fprintf(stderr, "glXGetContext failed!\n"); - return 0; - } - - /* create color map */ - if (!(cmap = XCreateColormap(dpy,RootWindow(dpy,vi->screen), - vi->visual,AllocNone))) - { - fprintf(stderr, "XCreateColormap failed!\n"); - return 0; - } - - /* create window */ - swa.colormap = cmap; - swa.border_pixel = 0; - swa.event_mask = StructureNotifyMask; - win = XCreateWindow(dpy,RootWindow(dpy,vi->screen),0,0,gfx->xsize,gfx->ysize,0,vi->depth, InputOutput,vi->visual,CWBorderPixel|CWColormap|CWEventMask, &swa); - XMapWindow(dpy,win); - XIfEvent(dpy,&event,WaitForNotify,(char*)win); - - if (!(glXMakeCurrent(dpy,win,cx))) - { - fprintf(stderr, "glXMakeCurrent failed (window)!\n"); - return 0; - } - - InitGL(); - - win_open = true; - buildFont(); - while(1) { - process_input(dpy); - } - - return NULL; -} - -// How do we prevent broken pipes and broken connection error messages? -// -void process_input(Display *dpy) { - XEvent event; - - if( XPending(dpy) ) { - do { - - XNextEvent(dpy, &event); - switch(event.type) { - case DestroyNotify: - win_open = false; - break; - default: - break; - } - } while (XPending(dpy)); - } - if (ok_to_draw && win_open) { - DrawGLScene(); - glXSwapBuffers(dpy,win); - ok_to_draw = 0; - } -} - -GLvoid buildFont(GLvoid) -{ - XFontStruct *font; - - main_font = glGenLists(256); /* storage for 256 characters */ - /* load a font with a specific name in "Host Portable Character Encoding" */ - /*font = XLoadQueryFont(dpy, - "-*-helvetica-bold-r-normal--24-*-*-*-p-*-iso8859-1");*/ - /* this really *should* be available on every X Window System...*/ - font = XLoadQueryFont(dpy, "fixed"); - if (font == NULL) - { - printf("Problems loading fonts :-(\n"); - return; // exit(1); - } - /* build 256 display lists out of our font */ - glXUseXFont(font->fid, 0, 256, main_font); - /* free our XFontStruct since we have our display lists */ - XFreeFont(dpy, font); -} - #endif +#include "boinc_api.h" +#include "graphics_api.h" +#include "app_ipc.h" +#include "util.h" +#include "glut.h" + +#define BOINC_WINDOW_CLASS_NAME "BOINC_app" + +static bool visible = true; +static int current_graphics_mode = MODE_HIDE_GRAPHICS; +int win_loop_done; +int xpos = 100, ypos = 100; // globals +int clicked_button; +int win; +extern void graphics_thread_init(); +extern GRAPHICS_INFO gi; +static void timer_handler(); +void set_mode(int mode); + +APP_INIT_DATA aid; + +void keyboardU(unsigned char key, int x, int y) { + /* This callback is invoked when a user presses a key. + */ + if (current_graphics_mode == MODE_FULLSCREEN) { + set_mode(MODE_HIDE_GRAPHICS); + // PostMessage(HWND_BROADCAST, m_uEndSSMsg, 0, 0); // WINDOWS DEPENDENT + // } else { + // boinc_app_key_release((int)wParam, (int)lParam); //CHANGE TO SPECIFICALLY RESPOND TO KEYSTROKE + } +} + +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); + // PostMessage(HWND_BROADCAST, m_uEndSSMsg, 0, 0); // WINDOWS DEPENDENT + } else { + if(state) + boinc_app_mouse_button(x, y, button, false); + else + boinc_app_mouse_button(x, y, button, true); + } +} + +void mouse_move(int x, int y){ + if(current_graphics_mode == MODE_FULLSCREEN) { + set_mode(MODE_HIDE_GRAPHICS); + // PostMessage(HWND_BROADCAST, m_uEndSSMsg, 0, 0); + } else { + boinc_app_mouse_move(x, y, false, false, false); + } +} + +void mouse_click_move(int x, int y){ + 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); + } +} + +void keyboardD(unsigned char key, int x, int y) { + /* This callback is invoked when a user presses a key. + */ + if (current_graphics_mode == MODE_FULLSCREEN) { + set_mode(MODE_HIDE_GRAPHICS); + // PostMessage(HWND_BROADCAST, m_uEndSSMsg, 0, 0); // WINDOWS DEPENDENT + } else { + // boinc_app_key_press((int)wParam, (int)lParam); //CHANGE IF WANT TO RESPOND TO KEYSTROKE + } +} + +void computeFPS(){ + static int frameCount = 0; + static int lastFrameTime = 0; + + frameCount++; + int currentTime = glutGet(GLenum(GLUT_ELAPSED_TIME)); + if (currentTime - lastFrameTime > 1000){ + char s[30]; + sprintf(s, "%s [ FPS: %4.2f ]", aid.app_name, + frameCount*1000/(currentTime - lastFrameTime)); + glutSetWindowTitle(s); + lastFrameTime = currentTime; + frameCount = 0; + } +} + + +void onIdle(){ + static double oldTime = 0; + double currentTime = dtime(); + + if(currentTime - oldTime > .001){ + timer_handler(); + oldTime = currentTime; + } + // computeFPS(); +} + +static void make_new_window(int mode){ + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); //DEPTH of how many? want 16 + if (mode == MODE_FULLSCREEN){ + glutFullScreen(); //TOPMOST AND POPUP? + } else if(mode == MODE_WINDOW){ + glutInitWindowPosition(xpos, ypos); + glutInitWindowSize(gi.xsize, gi.ysize); + boinc_get_init_data(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(timer_handler); + glutIdleFunc(onIdle); + + app_graphics_init(); + glEnable(GL_DEPTH_TEST); + } +} + +void set_mode(int mode) { + if (current_graphics_mode != mode){ + if(mode == MODE_HIDE_GRAPHICS){ + if(mode != MODE_FULLSCREEN){ + xpos = glutGet(GLUT_WINDOW_X); + ypos = glutGet(GLUT_WINDOW_Y); + + gi.xsize = glutGet(GLUT_WINDOW_WIDTH); + gi.ysize = glutGet(GLUT_WINDOW_HEIGHT); + } + glutDestroyWindow(win); + } + make_new_window(mode); + current_graphics_mode = mode; + } + + // tell the core client that we're entering new mode + // + if (app_client_shm) { + printf("in0\n"); + app_client_shm->shm->graphics_reply.send_msg( + xml_graphics_modes[current_graphics_mode] + ); + } +} + +void* xwin_graphics_event_loop(void*){ + + if (boinc_is_standalone()) { + set_mode(MODE_WINDOW); + } else { + set_mode(MODE_HIDE_GRAPHICS); + } + /* + glutReshapeFunc(app_graphics_resize); + glutKeyboardFunc(keyboardD); + glutKeyboardUpFunc(keyboardU); + glutMouseFunc(mouse_click); + glutMotionFunc(mouse_click_move); + glutDisplayFunc(timer_handler); + glutIdleFunc(onIdle); + + app_graphics_init(); + glEnable(GL_DEPTH_TEST);*/ + glutMainLoop(); +} + +static void timer_handler() { + // printf("in timer_handler\n"); + char buf[MSG_CHANNEL_SIZE]; + + int width, height, new_mode, msg; + if (app_client_shm) { + fprintf(stderr, "In first if\n"); fflush(stderr); + if(app_client_shm->shm->graphics_request.get_msg(buf)){ + new_mode = app_client_shm->decode_graphics_msg(buf); + switch(new_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(new_mode); + break; + } + } + } + if (!visible) return; + if (current_graphics_mode == MODE_HIDE_GRAPHICS) return; + + // TODO: remove width, height from API + // + width = glutGet(GLUT_WINDOW_WIDTH); + height = glutGet(GLUT_WINDOW_HEIGHT); + + if (throttled_app_render(width, height, dtime())) { + // printf("swapping buffers\n"); + glutSwapBuffers(); + } +} + + +/* + +BOOL VerifyPassword(HWND hwnd) +{ // Under NT, we return TRUE immediately. This lets the saver quit, +// and the system manages passwords. Under '95, we call VerifyScreenSavePwd. +// This checks the appropriate registry key and, if necessary, +// pops up a verify dialog +/*OSVERSIONINFO osv; osv.dwOSVersionInfoSize=sizeof(osv); GetVersionEx(&osv); +if (osv.dwPlatformId==VER_PLATFORM_WIN32_NT) return TRUE; +HINSTANCE hpwdcpl=::LoadLibrary("PASSWORD.CPL"); +if (hpwdcpl==NULL) {return TRUE;} +typedef BOOL (WINAPI *VERIFYSCREENSAVEPWD)(HWND hwnd); +VERIFYSCREENSAVEPWD VerifyScreenSavePwd; +VerifyScreenSavePwd= +(VERIFYSCREENSAVEPWD)GetProcAddress(hpwdcpl,"VerifyScreenSavePwd"); +if (VerifyScreenSavePwd==NULL) +{ + FreeLibrary(hpwdcpl);return TRUE; +} + BOOL bres=VerifyScreenSavePwd(hwnd); FreeLibrary(hpwdcpl); + return bres; +} +*/ + +#if 0 +float txt_widths[256]; + +#endif diff --git a/api/x_opengl.h b/api/x_opengl.h index 3a3cbc7bcf..35871c36c5 100644 --- a/api/x_opengl.h +++ b/api/x_opengl.h @@ -1 +1 @@ -extern void *p_graphics_loop( void * ); +extern void *xwin_graphics_event_loop( void * );