#include "X11OpenGLWindow.h" #include "OpenGLInclude.h" #include #include #ifdef GLEW_STATIC #include "CustomGL/glew.h" #else #include #endif//GLEW_STATIC #ifdef GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS #include "CustomGL/glxew.h" #else #include #endif // GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS #include //#define DYNAMIC_LOAD_X11_FUNCTIONS #ifdef DYNAMIC_LOAD_X11_FUNCTIONS #include #endif //DYNAMIC_LOAD_X11_FUNCTIONS //#include //#include //#include //defined in GL/glxew.h //#include #include #include #include #include #include GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_STENCIL_SIZE , 8, GLX_DOUBLEBUFFER, None }; /* static int att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DEPTH_SIZE , 24, GLX_STENCIL_SIZE , 8, GLX_DOUBLEBUFFER , True, None }; */ static bool forceOpenGL3 = true; #ifdef DYNAMIC_LOAD_X11_FUNCTIONS ///our X11 function typedefs typedef int (*PFNXFREE)(void*); typedef XErrorHandler (* PFNXSETERRORHANDLER) (XErrorHandler); typedef int (* PFNXSYNC) (Display* a,Bool b); typedef Display* (* PFNXOPENDISPLAY) (_Xconst char* a); typedef Colormap (*PFNXCREATECOLORMAP) (Display* a,Window b,Visual* c,int d); typedef Window (*PFNXCREATEWINDOW) (Display* a,Window b,int c,int d,unsigned int e,unsigned int f,unsigned int g,int h,unsigned int i,Visual* j,unsigned long k,XSetWindowAttributes* l); typedef int (*PFNXMAPWINDOW) (Display*, Window); typedef int (*PFNXSTORENAME) (Display* a,Window b,_Xconst char* c); typedef int (*PFNXCLOSEDISPLAY) (Display* a); typedef int (*PFNXDESTROYWINDOW) (Display* a,Window b); typedef int (*PFNXRAISEWINDOW) (Display* a, Window b); #if NeedWidePrototypes typedef KeySym* (*PFNXGETKEYBOARDMAPPING) (Display*,unsigned int,int,int*); typedef KeySym (*PFNXKEYCODETOKEYSYM) (Display* a,unsigned int b,int c); #else typedef KeySym* (*PFNXGETKEYBOARDMAPPING) (Display*,KeyCode,int,int*); typedef KeySym (*PFNXKEYCODETOKEYSYM) (Display* a,KeyCode b,int c); #endif typedef void (*PFNXCONVERTCASE) (KeySym /* sym */,KeySym * /* lower */,KeySym * /* upper */); typedef int (*PFNXPENDING) (Display* a); typedef int (*PFNXNEXTEVENT) (Display* a,XEvent* b); typedef int (*PFNXEVENTSQUEUED) (Display* a,int b); typedef int (*PFNXPEEKEVENT) (Display* a,XEvent* b); typedef KeySym (*PFNXLOOKUPKEYSYM) (XKeyEvent* a,int b); typedef Status (*PFNXGETWINDOWATTRIBUTES) (Display* a,Window b,XWindowAttributes* c); #define X11_LIBRARY "libX11.so.6" #define MyXSync m_data->m_x11_XSync #define MyXGetKeyboardMapping m_data->m_x11_XGetKeyboardMapping #define MyXSetErrorHandler m_data->m_x11_XSetErrorHandler #define MyXOpenDisplay m_data->m_x11_XOpenDisplay #define MyXCreateColormap m_data->m_x11_XCreateColormap #define MyXCreateWindow m_data->m_x11_XCreateWindow #define MyXMapWindow m_data->m_x11_XMapWindow #define MyXStoreName m_data->m_x11_XStoreName #define MyXDestroyWindow m_data->m_x11_XDestroyWindow #define MyXRaiseWindow m_data->m_x11_XRaiseWindow #define MyXCloseDisplay m_data->m_x11_XCloseDisplay #define MyXKeycodeToKeysym m_data->m_x11_XKeycodeToKeysym #define MyXConvertCase m_data->m_x11_XConvertCase #define MyXPending m_data->m_x11_XPending #define MyXNextEvent m_data->m_x11_XNextEvent #define MyXEventsQueued m_data->m_x11_XEventsQueued #define MyXPeekEvent m_data->m_x11_XPeekEvent #define MyXNextEvent m_data->m_x11_XNextEvent #define MyXGetWindowAttributes m_data->m_x11_XGetWindowAttributes #define MyXStoreName m_data->m_x11_XStoreName #define MyXFree m_data->m_x11_XFree #define MyXMapWindow m_data->m_x11_XMapWindow #define MyXStoreName m_data->m_x11_XStoreName #define MyXLookupKeysym m_data->m_x11_XLookupKeysym #else #define MyXSync XSync #define MyXGetKeyboardMapping XGetKeyboardMapping #define MyXSetErrorHandler XSetErrorHandler #define MyXOpenDisplay XOpenDisplay #define MyXCreateColormap XCreateColormap #define MyXCreateWindow XCreateWindow #define MyXMapWindow XMapWindow #define MyXStoreName XStoreName #define MyXDestroyWindow XDestroyWindow #define MyXRaiseWindow XRaiseWindow #define MyXCloseDisplay XCloseDisplay #define MyXKeycodeToKeysym XKeycodeToKeysym #define MyXConvertCase XConvertCase #define MyXPending XPending #define MyXNextEvent XNextEvent #define MyXEventsQueued XEventsQueued #define MyXPeekEvent XPeekEvent #define MyXNextEvent XNextEvent #define MyXGetWindowAttributes XGetWindowAttributes #define MyXStoreName XStoreName #define MyXFree XFree #define MyXMapWindow XMapWindow #define MyXStoreName XStoreName #define MyXLookupKeysym XLookupKeysym #endif//DYNAMIC_LOAD_X11_FUNCTIONS enum { MY_X11_ALT_KEY = 1, MY_X11_SHIFT_KEY = 2, MY_X11_CONTROL_KEY = 4 }; struct InternalData2 { Display* m_dpy; Window m_root; XVisualInfo* m_vi; Colormap m_cmap; XSetWindowAttributes m_swa; Window m_win; GLXContext m_glc; XWindowAttributes m_gwa; XEvent m_xev; GLXFBConfig m_bestFbc; int m_modifierFlags; int m_glWidth; int m_glHeight; #ifdef DYNAMIC_LOAD_X11_FUNCTIONS //dynamically load stuff void* m_x11_library; PFNXFREE m_x11_XFree; PFNXSETERRORHANDLER m_x11_XSetErrorHandler; PFNXSYNC m_x11_XSync; PFNXOPENDISPLAY m_x11_XOpenDisplay; PFNXCREATECOLORMAP m_x11_XCreateColormap; PFNXCREATEWINDOW m_x11_XCreateWindow; PFNXMAPWINDOW m_x11_XMapWindow; PFNXSTORENAME m_x11_XStoreName; PFNXCLOSEDISPLAY m_x11_XCloseDisplay; PFNXDESTROYWINDOW m_x11_XDestroyWindow; PFNXRAISEWINDOW m_x11_XRaiseWindow; PFNXKEYCODETOKEYSYM m_x11_XKeycodeToKeysym; PFNXGETKEYBOARDMAPPING m_x11_XGetKeyboardMapping; PFNXCONVERTCASE m_x11_XConvertCase; PFNXPENDING m_x11_XPending; PFNXNEXTEVENT m_x11_XNextEvent; PFNXEVENTSQUEUED m_x11_XEventsQueued; PFNXPEEKEVENT m_x11_XPeekEvent; PFNXLOOKUPKEYSYM m_x11_XLookupKeysym; PFNXGETWINDOWATTRIBUTES m_x11_XGetWindowAttributes; #endif //DYNAMIC_LOAD_X11_FUNCTIONS b3WheelCallback m_wheelCallback; b3MouseMoveCallback m_mouseMoveCallback; b3MouseButtonCallback m_mouseButtonCallback; b3ResizeCallback m_resizeCallback; b3KeyboardCallback m_keyboardCallback; InternalData2() :m_dpy(0), m_vi(0), m_modifierFlags(0), m_glWidth(-1), m_glHeight(-1), m_wheelCallback(0), m_mouseMoveCallback(0), m_mouseButtonCallback(0), m_resizeCallback(0), m_keyboardCallback(0) { #ifdef DYNAMIC_LOAD_X11_FUNCTIONS m_x11_library = dlopen(X11_LIBRARY, RTLD_LOCAL | RTLD_NOW); if (!m_x11_library) { printf("Error opening X11 library %s\n", X11_LIBRARY); exit(0); } bool missingFunc = false; missingFunc = ((m_x11_XFree = (PFNXFREE) dlsym(m_x11_library, "XFree"))==NULL) | missingFunc; assert(!missingFunc); if (missingFunc) { printf("Error: missing func XFree in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XSetErrorHandler = (PFNXSETERRORHANDLER) dlsym(m_x11_library,"XSetErrorHandler"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XSetErrorHandler in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XSetErrorHandler = (PFNXSETERRORHANDLER) dlsym(m_x11_library,"XSetErrorHandler"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XSetErrorHandler in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XSync = (PFNXSYNC) dlsym(m_x11_library,"XSync"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XSync in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XOpenDisplay = (PFNXOPENDISPLAY) dlsym(m_x11_library,"XOpenDisplay"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XOpenDisplay in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XCreateColormap = (PFNXCREATECOLORMAP) dlsym(m_x11_library,"XCreateColormap"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XCreateColormap in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XCreateWindow = (PFNXCREATEWINDOW) dlsym(m_x11_library,"XCreateWindow"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XCreateWindow in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XMapWindow = (PFNXMAPWINDOW) dlsym(m_x11_library,"XMapWindow"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XMapWindow in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XStoreName = (PFNXSTORENAME) dlsym(m_x11_library,"XStoreName"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XStoreName in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XCloseDisplay = (PFNXCLOSEDISPLAY) dlsym(m_x11_library,"XCloseDisplay"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XCloseDisplay in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XDestroyWindow = (PFNXDESTROYWINDOW) dlsym(m_x11_library,"XDestroyWindow"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XDestroyWindow in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XRaiseWindow = (PFNXRAISEWINDOW) dlsym(m_x11_library,"XRaiseWindow"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XRaiseWindow in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XGetKeyboardMapping = (PFNXGETKEYBOARDMAPPING) dlsym(m_x11_library,"XGetKeyboardMapping"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XGetKeyboardMapping in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XKeycodeToKeysym = (PFNXKEYCODETOKEYSYM) dlsym(m_x11_library,"XKeycodeToKeysym"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XKeycodeToKeysym in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XConvertCase = (PFNXCONVERTCASE) dlsym(m_x11_library,"XConvertCase"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XConvertCase in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XPending = (PFNXPENDING) dlsym(m_x11_library,"XPending"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XPending in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XNextEvent = (PFNXNEXTEVENT) dlsym(m_x11_library,"XNextEvent"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XNextEvent in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XEventsQueued = (PFNXEVENTSQUEUED) dlsym(m_x11_library,"XEventsQueued"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XEventsQueued in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XPeekEvent = (PFNXPEEKEVENT) dlsym(m_x11_library,"XPeekEvent"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XPeekEvent in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XLookupKeysym = (PFNXLOOKUPKEYSYM) dlsym(m_x11_library,"XLookupKeysym"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XLookupKeysym in %s, exiting!\n", X11_LIBRARY); exit(0);} missingFunc = ((m_x11_XGetWindowAttributes = (PFNXGETWINDOWATTRIBUTES) dlsym(m_x11_library,"XGetWindowAttributes"))==NULL) | missingFunc; if (missingFunc) { printf("Error: missing func XGetWindowAttributes in %s, exiting!\n", X11_LIBRARY); exit(0);} if (missingFunc) { printf("Error: a missing func in %s, exiting!\n", X11_LIBRARY); exit(0); } else { printf("X11 functions dynamically loaded using dlopen/dlsym OK!\n"); } #endif //DYNAMIC_LOAD_X11_FUNCTIONS } }; #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092 typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); // Helper to check for extension string presence. Adapted from: // http://www.opengl.org/resources/features/OGLextensions/ static bool isExtensionSupported(const char *extList, const char *extension) { const char *start; const char *where, *terminator; /* Extension names should not have spaces. */ where = strchr(extension, ' '); if (where || *extension == '\0') return false; /* It takes a bit of care to be fool-proof about parsing the OpenGL extensions string. Don't be fooled by sub-strings, etc. */ for (start=extList;;) { where = strstr(start, extension); if (!where) break; terminator = where + strlen(extension); if ( where == start || *(where - 1) == ' ' ) if ( *terminator == ' ' || *terminator == '\0' ) return true; start = terminator; } return false; } static bool ctxErrorOccurred = false; static int ctxErrorHandler( Display *dpy, XErrorEvent *ev ) { ctxErrorOccurred = true; return 0; } X11OpenGLWindow::X11OpenGLWindow() :m_OpenGLInitialized(false), m_requestedExit(false) { m_data = new InternalData2; } X11OpenGLWindow::~X11OpenGLWindow() { if (m_OpenGLInitialized) { disableOpenGL(); } delete m_data; } void X11OpenGLWindow::enableOpenGL() { if (forceOpenGL3) { // Get the default screen's GLX extension list const char *glxExts = glXQueryExtensionsString( m_data->m_dpy, DefaultScreen( m_data->m_dpy ) ); // NOTE: It is not necessary to create or make current to a context before // calling glXGetProcAddressARB, unless we dynamically load OpenGL/GLX/X11 glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" ); GLXContext ctx = 0; // Install an X error handler so the application won't exit if GL 3.0 // context allocation fails. // // Note this error handler is global. All display connections in all threads // of a process use the same error handler, so be sure to guard against other // threads issuing X commands while this code is running. ctxErrorOccurred = false; int (*oldHandler)(Display*, XErrorEvent*) = MyXSetErrorHandler(&ctxErrorHandler); // Check for the GLX_ARB_create_context extension string and the function. // If either is not present, use GLX 1.3 context creation method. if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) || !glXCreateContextAttribsARB ) { printf( "glXCreateContextAttribsARB() not found" " ... using old-style GLX context\n" ); ctx = glXCreateNewContext( m_data->m_dpy, m_data->m_bestFbc, GLX_RGBA_TYPE, 0, True ); } // If it does, try to get a GL 3.0 context! else { int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB ,3, GLX_CONTEXT_MINOR_VERSION_ARB, 2, GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,None }; /* int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 2, //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None }; */ printf( "Creating context\n" ); ctx = glXCreateContextAttribsARB( m_data->m_dpy, m_data->m_bestFbc, 0, True, context_attribs ); // Sync to ensure any errors generated are processed. MyXSync( m_data->m_dpy, False ); if ( !ctxErrorOccurred && ctx ) printf( "Created GL 3.0 context\n" ); else { // Couldn't create GL 3.0 context. Fall back to old-style 2.x context. // When a context version below 3.0 is requested, implementations will // return the newest context version compatible with OpenGL versions less // than version 3.0. // GLX_CONTEXT_MAJOR_VERSION_ARB = 1 context_attribs[1] = 1; // GLX_CONTEXT_MINOR_VERSION_ARB = 0 context_attribs[3] = 0; ctxErrorOccurred = false; printf( "Failed to create GL 3.0 context" " ... using old-style GLX context\n" ); ctx = glXCreateContextAttribsARB( m_data->m_dpy, m_data->m_bestFbc, 0, True, context_attribs ); } } // Sync to ensure any errors generated are processed. MyXSync( m_data->m_dpy, False ); // Restore the original error handler MyXSetErrorHandler( oldHandler ); if ( ctxErrorOccurred || !ctx ) { printf( "Failed to create an OpenGL context\n" ); exit(1); } // Verifying that context is a direct context if ( ! glXIsDirect ( m_data->m_dpy, ctx ) ) { printf( "Indirect GLX rendering context obtained\n" ); } else { printf( "Direct GLX rendering context obtained\n" ); } printf( "Making context current\n" ); glXMakeCurrent( m_data->m_dpy, m_data->m_win, ctx ); m_data->m_glc = ctx; } else { m_data->m_glc = glXCreateContext(m_data->m_dpy, m_data->m_vi, NULL, GL_TRUE); glXMakeCurrent(m_data->m_dpy, m_data->m_win, m_data->m_glc); } #ifdef GLEW_INIT_OPENGL11_FUNCTIONS { GLboolean res = glewOpenGL11Init(); if (res==0) { printf("glewOpenGL11Init OK!\n"); } else { printf("ERROR: glewOpenGL11Init failed, exiting!\n"); exit(0); } } #endif //GLEW_INIT_OPENGL11_FUNCTIONS const GLubyte* ven = glGetString(GL_VENDOR); printf("GL_VENDOR=%s\n", ven); const GLubyte* ren = glGetString(GL_RENDERER); printf("GL_RENDERER=%s\n",ren); const GLubyte* ver = glGetString(GL_VERSION); printf("GL_VERSION=%s\n", ver); const GLubyte* sl = glGetString(GL_SHADING_LANGUAGE_VERSION); printf("GL_SHADING_LANGUAGE_VERSION=%s\n", sl); //Access pthreads as a workaround for a bug in Linux/Ubuntu //See https://bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers-319/+bug/1248642 int i=pthread_getconcurrency(); printf("pthread_getconcurrency()=%d\n",i); // const GLubyte* ext = glGetString(GL_EXTENSIONS); // printf("GL_EXTENSIONS=%s\n", ext); } void X11OpenGLWindow::disableOpenGL() { glXMakeCurrent(m_data->m_dpy, None, NULL); glXDestroyContext(m_data->m_dpy, m_data->m_glc); } void X11OpenGLWindow::createWindow(const b3gWindowConstructionInfo& ci) { m_data->m_dpy = MyXOpenDisplay(NULL); if(m_data->m_dpy == NULL) { printf("\n\tcannot connect to X server\n\n"); exit(0); } m_data->m_root = DefaultRootWindow(m_data->m_dpy); #ifdef GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS GLboolean res = glewXInit(); if (res==0) { printf("glewXInit OK\n"); } else { printf("glewXInit failed, exit\n"); exit(0); } #endif //GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS if (ci.m_openglVersion < 3) { forceOpenGL3 = false; } if (forceOpenGL3) { int glxMinor, glxMajor; if (!glXQueryVersion(m_data->m_dpy,&glxMajor,&glxMinor) || (((glxMajor==1)&&(glxMinor<3)) || (glxMajor<1))) { printf("Invalid GLX version: major %d, minor %d\n",glxMajor,glxMinor); exit(0); } static int visual_attribs[] = { GLX_X_RENDERABLE , True, GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT, GLX_RENDER_TYPE , GLX_RGBA_BIT, GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR, GLX_RED_SIZE , 8, GLX_GREEN_SIZE , 8, GLX_BLUE_SIZE , 8, GLX_ALPHA_SIZE , 8, GLX_DEPTH_SIZE , 24, GLX_STENCIL_SIZE , 8, GLX_DOUBLEBUFFER , True, None }; int fbcount; GLXFBConfig* fbc = glXChooseFBConfig(m_data->m_dpy, DefaultScreen(m_data->m_dpy), visual_attribs, &fbcount); if (!fbc) { printf( "Failed to retrieve a framebuffer config\n" ); exit(1); } ///don't use highest samples, it is really slow on some NVIDIA Quadro cards #ifdef USE_HIGHEST_SAMPLES int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999; int i; for (i=0; im_dpy, fbc[i] ); if ( vi ) { int samp_buf, samples; glXGetFBConfigAttrib( m_data->m_dpy, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf ); glXGetFBConfigAttrib( m_data->m_dpy, fbc[i], GLX_SAMPLES , &samples ); //printf( " Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d," // " SAMPLES = %d\n", // i, vi -> visualid, samp_buf, samples ); if ( best_fbc < 0 || (samp_buf && (samples > best_num_samp)) ) best_fbc = i, best_num_samp = samples; if ( worst_fbc < 0 || (!samp_buf || (samples < worst_num_samp)) ) worst_fbc = i, worst_num_samp = samples; } MyXFree( vi ); } m_data->m_bestFbc = fbc[ best_fbc ]; #else m_data->m_bestFbc = *fbc; #endif // Be sure to free the FBConfig list allocated by glXChooseFBConfig() MyXFree( fbc ); m_data->m_vi = glXGetVisualFromFBConfig( m_data->m_dpy, m_data->m_bestFbc ); m_data->m_swa.colormap = m_data->m_cmap = MyXCreateColormap( m_data->m_dpy, RootWindow( m_data->m_dpy, m_data->m_vi->screen ), m_data->m_vi->visual, AllocNone ); m_data->m_swa.background_pixmap = None ; m_data->m_swa.border_pixel = 0; m_data->m_swa.event_mask = ExposureMask | KeyReleaseMask | KeyPressMask |ButtonPressMask | ButtonReleaseMask |PointerMotionMask|StructureNotifyMask; ; m_data->m_root = RootWindow( m_data->m_dpy, m_data->m_vi->screen ); m_data->m_win = MyXCreateWindow( m_data->m_dpy, m_data->m_root, 0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput, m_data->m_vi->visual, CWBorderPixel|CWColormap|CWEventMask, &m_data->m_swa ); //m_data->m_win = m_data->m_x11_XCreateWindow(m_data->m_dpy, m_data->m_root, 0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput, m_data->m_vi->visual, CWColormap | CWEventMask, &m_data->m_swa); if (!m_data->m_win) { printf("Cannot create window\n"); exit(0); } MyXMapWindow(m_data->m_dpy, m_data->m_win); MyXStoreName(m_data->m_dpy, m_data->m_win, "OpenGL3 Window"); } else { m_data->m_vi = glXChooseVisual(m_data->m_dpy, 0, att); printf("4\n"); if(m_data->m_vi == NULL) { printf("\n\tno appropriate visual found\n\n"); exit(0); } else { printf("\n\tvisual %p selected\n", (void *)m_data->m_vi->visualid); /* %p creates hexadecimal output like in glxinfo */ } m_data->m_cmap = MyXCreateColormap(m_data->m_dpy, m_data->m_root, m_data->m_vi->visual, AllocNone); m_data->m_swa.colormap = m_data->m_cmap; m_data->m_swa.event_mask = ExposureMask | KeyReleaseMask | KeyPressMask |ButtonPressMask | ButtonReleaseMask |PointerMotionMask|StructureNotifyMask; m_data->m_win = MyXCreateWindow(m_data->m_dpy, m_data->m_root, 0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput, m_data->m_vi->visual, CWColormap | CWEventMask, &m_data->m_swa); MyXMapWindow(m_data->m_dpy, m_data->m_win); MyXStoreName(m_data->m_dpy, m_data->m_win, "OpenGL2 Window"); } enableOpenGL(); } void X11OpenGLWindow::closeWindow() { disableOpenGL(); MyXDestroyWindow(m_data->m_dpy, m_data->m_win); MyXCloseDisplay(m_data->m_dpy); } int X11OpenGLWindow::getAsciiCodeFromVirtualKeycode(int keycode) { int result = 0; KeySym key, key_lc, key_uc; int keysyms_per_keycode_return; KeySym *keysym = MyXGetKeyboardMapping(m_data->m_dpy, keycode, 1, &keysyms_per_keycode_return); key = keysym[0]; //key = MyXKeycodeToKeysym( m_data->m_dpy, keycode, 0 ); switch( key ) { case XK_Escape: return B3G_ESCAPE; case XK_Return: return B3G_RETURN; case XK_Control_L: case XK_Control_R: { return B3G_CONTROL; } case XK_Left: return B3G_LEFT_ARROW; case XK_Right: return B3G_RIGHT_ARROW; case XK_Up: return B3G_UP_ARROW; case XK_Down: return B3G_DOWN_ARROW; case XK_Alt_L: case XK_Alt_R: { return B3G_ALT; } case XK_Shift_L: case XK_Shift_R: return B3G_SHIFT; case XK_F1: return B3G_F1; case XK_F2: return B3G_F2; case XK_F3: return B3G_F3; case XK_F4: return B3G_F4; case XK_F5: return B3G_F5; case XK_F6: return B3G_F6; case XK_F7: return B3G_F7; case XK_F8: return B3G_F8; case XK_F9: return B3G_F9; case XK_F10: return B3G_F10; case XK_F11: return B3G_F11; case XK_F12: return B3G_F12; case XK_F13: return B3G_F13; case XK_F14: return B3G_F14; case XK_F15: return B3G_F15; default: // Make lowercase MyXConvertCase( key, &key_lc, &key_uc ); key = key_lc; // Valid ISO 8859-1 character? if( (key >= 32 && key <= 126) ||(key >= 160 && key <= 255) ) { return (int) key; } result = -1; } MyXFree(keysym); return result; } bool X11OpenGLWindow::isModifierKeyPressed(int key) { bool isPressed = false; switch (key) { case B3G_ALT: { isPressed = ((m_data->m_modifierFlags & MY_X11_ALT_KEY)!=0); break; }; case B3G_SHIFT: { isPressed = ((m_data->m_modifierFlags & MY_X11_SHIFT_KEY)!=0); break; }; case B3G_CONTROL: { isPressed = ((m_data->m_modifierFlags & MY_X11_CONTROL_KEY )!=0); break; }; default: { } }; return isPressed; } void X11OpenGLWindow::pumpMessage() { int buttonState = 1; // Process all pending events while( MyXPending( m_data->m_dpy ) ) { MyXNextEvent(m_data->m_dpy, &m_data->m_xev); // printf("#"); // fflush(stdout); switch( m_data->m_xev.type ) { case KeyPress: { int keycode = getAsciiCodeFromVirtualKeycode(m_data->m_xev.xkey.keycode); switch (keycode) { case B3G_ALT: m_data->m_modifierFlags |= MY_X11_ALT_KEY; break; case B3G_SHIFT: m_data->m_modifierFlags |= MY_X11_SHIFT_KEY; break; case B3G_CONTROL: m_data->m_modifierFlags |= MY_X11_CONTROL_KEY; break; default: {} }; if (m_data->m_keyboardCallback) { int state = 1; (*m_data->m_keyboardCallback)(keycode,state); // printf("keycode %d",keycode); // fflush(stdout); } break; } case KeyRelease: { // fflush(stdout); int keycode = getAsciiCodeFromVirtualKeycode( m_data->m_xev.xkey.keycode); switch (keycode) { case B3G_ALT: m_data->m_modifierFlags &= ~MY_X11_ALT_KEY; break; case B3G_SHIFT: m_data->m_modifierFlags &= ~MY_X11_SHIFT_KEY; break; case B3G_CONTROL: m_data->m_modifierFlags &= ~MY_X11_CONTROL_KEY; break; default: {} }; if (m_data->m_keyboardCallback) { #if 0 unsigned short is_retriggered = 0; ///filter out keyboard repeat //see http://stackoverflow.com/questions/2100654/ignore-auto-repeat-in-x11-applications if (MyXEventsQueued(m_data->m_dpy, QueuedAfterReading)) { XEvent nev; MyXPeekEvent(m_data->m_dpy, &nev); if (nev.type == KeyPress && nev.xkey.time == m_data->m_xev.xkey.time && nev.xkey.keycode == m_data->m_xev.xkey.keycode) { fprintf (stdout, "key #%ld was retriggered.\n", (long) MyXLookupKeysym(&nev.xkey, 0)); // delete retriggered KeyPress event MyXNextEvent(m_data->m_dpy, & m_data->m_xev); is_retriggered = 1; } } #endif int state = 0; (*m_data->m_keyboardCallback)(keycode,state); } break; } case ButtonRelease: buttonState = 0; //continue with ButtonPress code case ButtonPress: { // printf("!"); // fflush(stdout); int button=-1; switch (m_data->m_xev.xbutton.button) { case Button1: { button=0; break; } case Button2: { button=1; break; } case Button3: { button=2; break; } case Button4: { if (m_data->m_wheelCallback) { (*m_data->m_wheelCallback)(0,10); } break; } case Button5: { if (m_data->m_wheelCallback) { (*m_data->m_wheelCallback)(0,-10); } break; } } int xpos = m_data->m_xev.xmotion.x; int ypos = m_data->m_xev.xmotion.y; if (button>=0 && m_data->m_mouseButtonCallback) { // printf("xpos = %d, ypos = %d\n",xpos,ypos); (*m_data->m_mouseButtonCallback)(button,buttonState,xpos,ypos); } break; } case MotionNotify: { // printf("!"); // fflush(0); if (m_data->m_mouseMoveCallback) { int xpos = m_data->m_xev.xmotion.x; int ypos = m_data->m_xev.xmotion.y; (*m_data->m_mouseMoveCallback)(xpos,ypos); } break; } case ConfigureNotify: { // printf("@"); // fflush(0); m_data->m_glWidth = m_data->m_xev.xconfigure.width; m_data->m_glHeight = m_data->m_xev.xconfigure.height; if (m_data->m_resizeCallback) { (*m_data->m_resizeCallback)(m_data->m_xev.xconfigure.width,m_data->m_xev.xconfigure.height); } break; } case ClientMessage: { // printf("?"); // fflush(stdout); break; } case Expose: { break; } case DestroyNotify: { break; } default: { //XRRUpdateConfiguration( &event ); } }; } } void X11OpenGLWindow::startRendering() { pumpMessage(); MyXGetWindowAttributes(m_data->m_dpy, m_data->m_win, &m_data->m_gwa); glViewport(0, 0, m_data->m_gwa.width, m_data->m_gwa.height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); //clear buffers //glCullFace(GL_BACK); //glFrontFace(GL_CCW); glEnable(GL_DEPTH_TEST); } void X11OpenGLWindow::renderAllObjects() { } void X11OpenGLWindow::endRendering() { glXSwapBuffers(m_data->m_dpy, m_data->m_win); } void X11OpenGLWindow::runMainLoop() { } float X11OpenGLWindow::getTimeInSeconds() { return 0.f; } bool X11OpenGLWindow::requestedExit() const { return m_requestedExit; } void X11OpenGLWindow::setRequestExit() { m_requestedExit=true; } void X11OpenGLWindow::setRenderCallback( b3RenderCallback renderCallback) { } void X11OpenGLWindow::setWindowTitle(const char* title) { MyXStoreName(m_data->m_dpy, m_data->m_win, title); } void X11OpenGLWindow::setWheelCallback(b3WheelCallback wheelCallback) { m_data->m_wheelCallback = wheelCallback; } void X11OpenGLWindow::setMouseMoveCallback(b3MouseMoveCallback mouseCallback) { m_data->m_mouseMoveCallback = mouseCallback; } void X11OpenGLWindow::setMouseButtonCallback(b3MouseButtonCallback mouseCallback) { m_data->m_mouseButtonCallback = mouseCallback; } void X11OpenGLWindow::setResizeCallback(b3ResizeCallback resizeCallback) { if (resizeCallback && m_data->m_glWidth>0 && m_data->m_glHeight > 0) { resizeCallback(m_data->m_glWidth, m_data->m_glHeight); } m_data->m_resizeCallback = resizeCallback; } void X11OpenGLWindow::setKeyboardCallback( b3KeyboardCallback keyboardCallback) { m_data->m_keyboardCallback = keyboardCallback; } b3MouseMoveCallback X11OpenGLWindow::getMouseMoveCallback() { return m_data->m_mouseMoveCallback; } b3MouseButtonCallback X11OpenGLWindow::getMouseButtonCallback() { return m_data->m_mouseButtonCallback; } b3ResizeCallback X11OpenGLWindow::getResizeCallback() { return m_data->m_resizeCallback; } b3WheelCallback X11OpenGLWindow::getWheelCallback() { return m_data->m_wheelCallback; } b3KeyboardCallback X11OpenGLWindow::getKeyboardCallback() { return m_data->m_keyboardCallback; } int X11OpenGLWindow::getWidth() const { if (m_data) return m_data->m_glWidth; return 0; } int X11OpenGLWindow::getHeight() const { if (m_data) return m_data->m_glHeight; return 0; } #include int X11OpenGLWindow::fileOpenDialog(char* filename, int maxNameLength) { int len = 0; FILE * output = popen("zenity --file-selection --file-filter=\"*.urdf\" --file-filter=\"*.sdf\" --file-filter=\"*.obj\" --file-filter=\"*.*\"","r"); if (output) { while( fgets(filename, maxNameLength-1, output) != NULL ) { len=strlen(filename); if (len>0) { filename[len-1]=0; printf("file open (length=%d) = %s\n", len,filename); } } pclose(output); } else { printf("Error: fileOpenDialog no popen output, perhaps install zenity?\n"); } MyXRaiseWindow(m_data->m_dpy, m_data->m_win); return len; }