1 #include "X11OpenGLWindow.h"
2 #include "OpenGLInclude.h"
3
4 #include<stdio.h>
5 #include<stdlib.h>
6 #ifdef GLEW_STATIC
7 #include "CustomGL/glew.h"
8 #else
9 #include <GL/glew.h>
10 #endif//GLEW_STATIC
11
12 #ifdef GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS
13 #include "CustomGL/glxew.h"
14 #else
15 #include<GL/glx.h>
16 #endif // GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS
17 #include <assert.h>
18
19 //#define DYNAMIC_LOAD_X11_FUNCTIONS
20 #ifdef DYNAMIC_LOAD_X11_FUNCTIONS
21 #include <dlfcn.h>
22 #endif //DYNAMIC_LOAD_X11_FUNCTIONS
23
24 //#include<X11/X.h>
25 //#include<X11/Xlib.h>
26 //#include<GL/gl.h>
27
28 //defined in GL/glxew.h
29 //#include<GL/glu.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34
35 #include <pthread.h>
36
37 GLint att[] = { GLX_RGBA,
38 GLX_DEPTH_SIZE, 24,
39 GLX_RED_SIZE , 8,
40 GLX_GREEN_SIZE , 8,
41 GLX_BLUE_SIZE , 8,
42 GLX_ALPHA_SIZE , 8,
43 GLX_STENCIL_SIZE , 8,
44 GLX_DOUBLEBUFFER,
45 None };
46 /*
47 static int att[] =
48 {
49 GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None
50
51 GLX_X_RENDERABLE , True,
52 GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
53 GLX_RENDER_TYPE , GLX_RGBA_BIT,
54 GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
55 GLX_RED_SIZE , 8,
56 GLX_GREEN_SIZE , 8,
57 GLX_BLUE_SIZE , 8,
58 GLX_ALPHA_SIZE , 8,
59 GLX_DEPTH_SIZE , 24,
60 GLX_STENCIL_SIZE , 8,
61 GLX_DOUBLEBUFFER , True,
62 None
63 };
64 */
65 static bool forceOpenGL3 = true;
66
67
68
69 #ifdef DYNAMIC_LOAD_X11_FUNCTIONS
70
71 ///our X11 function typedefs
72
73 typedef int (*PFNXFREE)(void*);
74 typedef XErrorHandler (* PFNXSETERRORHANDLER) (XErrorHandler);
75 typedef int (* PFNXSYNC) (Display* a,Bool b);
76 typedef Display* (* PFNXOPENDISPLAY) (_Xconst char* a);
77 typedef Colormap (*PFNXCREATECOLORMAP) (Display* a,Window b,Visual* c,int d);
78 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);
79 typedef int (*PFNXMAPWINDOW) (Display*, Window);
80 typedef int (*PFNXSTORENAME) (Display* a,Window b,_Xconst char* c);
81 typedef int (*PFNXCLOSEDISPLAY) (Display* a);
82 typedef int (*PFNXDESTROYWINDOW) (Display* a,Window b);
83 typedef int (*PFNXRAISEWINDOW) (Display* a, Window b);
84
85 #if NeedWidePrototypes
86 typedef KeySym* (*PFNXGETKEYBOARDMAPPING) (Display*,unsigned int,int,int*);
87 typedef KeySym (*PFNXKEYCODETOKEYSYM) (Display* a,unsigned int b,int c);
88 #else
89 typedef KeySym* (*PFNXGETKEYBOARDMAPPING) (Display*,KeyCode,int,int*);
90 typedef KeySym (*PFNXKEYCODETOKEYSYM) (Display* a,KeyCode b,int c);
91 #endif
92 typedef void (*PFNXCONVERTCASE) (KeySym /* sym */,KeySym * /* lower */,KeySym * /* upper */);
93 typedef int (*PFNXPENDING) (Display* a);
94 typedef int (*PFNXNEXTEVENT) (Display* a,XEvent* b);
95 typedef int (*PFNXEVENTSQUEUED) (Display* a,int b);
96 typedef int (*PFNXPEEKEVENT) (Display* a,XEvent* b);
97 typedef KeySym (*PFNXLOOKUPKEYSYM) (XKeyEvent* a,int b);
98 typedef Status (*PFNXGETWINDOWATTRIBUTES) (Display* a,Window b,XWindowAttributes* c);
99
100 #define X11_LIBRARY "libX11.so.6"
101
102 #define MyXSync m_data->m_x11_XSync
103 #define MyXGetKeyboardMapping m_data->m_x11_XGetKeyboardMapping
104 #define MyXSetErrorHandler m_data->m_x11_XSetErrorHandler
105 #define MyXOpenDisplay m_data->m_x11_XOpenDisplay
106 #define MyXCreateColormap m_data->m_x11_XCreateColormap
107 #define MyXCreateWindow m_data->m_x11_XCreateWindow
108 #define MyXMapWindow m_data->m_x11_XMapWindow
109 #define MyXStoreName m_data->m_x11_XStoreName
110 #define MyXDestroyWindow m_data->m_x11_XDestroyWindow
111 #define MyXRaiseWindow m_data->m_x11_XRaiseWindow
112 #define MyXCloseDisplay m_data->m_x11_XCloseDisplay
113 #define MyXKeycodeToKeysym m_data->m_x11_XKeycodeToKeysym
114 #define MyXConvertCase m_data->m_x11_XConvertCase
115 #define MyXPending m_data->m_x11_XPending
116 #define MyXNextEvent m_data->m_x11_XNextEvent
117 #define MyXEventsQueued m_data->m_x11_XEventsQueued
118 #define MyXPeekEvent m_data->m_x11_XPeekEvent
119 #define MyXNextEvent m_data->m_x11_XNextEvent
120 #define MyXGetWindowAttributes m_data->m_x11_XGetWindowAttributes
121 #define MyXStoreName m_data->m_x11_XStoreName
122 #define MyXFree m_data->m_x11_XFree
123 #define MyXMapWindow m_data->m_x11_XMapWindow
124 #define MyXStoreName m_data->m_x11_XStoreName
125 #define MyXLookupKeysym m_data->m_x11_XLookupKeysym
126
127 #else
128 #define MyXSync XSync
129 #define MyXGetKeyboardMapping XGetKeyboardMapping
130 #define MyXSetErrorHandler XSetErrorHandler
131 #define MyXOpenDisplay XOpenDisplay
132 #define MyXCreateColormap XCreateColormap
133 #define MyXCreateWindow XCreateWindow
134 #define MyXMapWindow XMapWindow
135 #define MyXStoreName XStoreName
136 #define MyXDestroyWindow XDestroyWindow
137 #define MyXRaiseWindow XRaiseWindow
138 #define MyXCloseDisplay XCloseDisplay
139 #define MyXKeycodeToKeysym XKeycodeToKeysym
140 #define MyXConvertCase XConvertCase
141 #define MyXPending XPending
142 #define MyXNextEvent XNextEvent
143 #define MyXEventsQueued XEventsQueued
144 #define MyXPeekEvent XPeekEvent
145 #define MyXNextEvent XNextEvent
146 #define MyXGetWindowAttributes XGetWindowAttributes
147 #define MyXStoreName XStoreName
148 #define MyXFree XFree
149 #define MyXMapWindow XMapWindow
150 #define MyXStoreName XStoreName
151 #define MyXLookupKeysym XLookupKeysym
152
153 #endif//DYNAMIC_LOAD_X11_FUNCTIONS
154
155 enum
156 {
157 MY_X11_ALT_KEY = 1,
158 MY_X11_SHIFT_KEY = 2,
159 MY_X11_CONTROL_KEY = 4
160 };
161
162 struct InternalData2
163 {
164 Display* m_dpy;
165 Window m_root;
166 XVisualInfo* m_vi;
167 Colormap m_cmap;
168 XSetWindowAttributes m_swa;
169 Window m_win;
170 GLXContext m_glc;
171 XWindowAttributes m_gwa;
172 XEvent m_xev;
173 GLXFBConfig m_bestFbc;
174 int m_modifierFlags;
175 int m_glWidth;
176 int m_glHeight;
177
178 #ifdef DYNAMIC_LOAD_X11_FUNCTIONS
179 //dynamically load stuff
180 void* m_x11_library;
181 PFNXFREE m_x11_XFree;
182 PFNXSETERRORHANDLER m_x11_XSetErrorHandler;
183 PFNXSYNC m_x11_XSync;
184 PFNXOPENDISPLAY m_x11_XOpenDisplay;
185 PFNXCREATECOLORMAP m_x11_XCreateColormap;
186 PFNXCREATEWINDOW m_x11_XCreateWindow;
187 PFNXMAPWINDOW m_x11_XMapWindow;
188 PFNXSTORENAME m_x11_XStoreName;
189 PFNXCLOSEDISPLAY m_x11_XCloseDisplay;
190 PFNXDESTROYWINDOW m_x11_XDestroyWindow;
191 PFNXRAISEWINDOW m_x11_XRaiseWindow;
192 PFNXKEYCODETOKEYSYM m_x11_XKeycodeToKeysym;
193 PFNXGETKEYBOARDMAPPING m_x11_XGetKeyboardMapping;
194 PFNXCONVERTCASE m_x11_XConvertCase;
195 PFNXPENDING m_x11_XPending;
196 PFNXNEXTEVENT m_x11_XNextEvent;
197 PFNXEVENTSQUEUED m_x11_XEventsQueued;
198 PFNXPEEKEVENT m_x11_XPeekEvent;
199 PFNXLOOKUPKEYSYM m_x11_XLookupKeysym;
200 PFNXGETWINDOWATTRIBUTES m_x11_XGetWindowAttributes;
201 #endif //DYNAMIC_LOAD_X11_FUNCTIONS
202
203 b3WheelCallback m_wheelCallback;
204 b3MouseMoveCallback m_mouseMoveCallback;
205 b3MouseButtonCallback m_mouseButtonCallback;
206 b3ResizeCallback m_resizeCallback;
207 b3KeyboardCallback m_keyboardCallback;
208
InternalData2InternalData2209 InternalData2()
210 :m_dpy(0),
211 m_vi(0),
212 m_modifierFlags(0),
213 m_glWidth(-1),
214 m_glHeight(-1),
215 m_wheelCallback(0),
216 m_mouseMoveCallback(0),
217 m_mouseButtonCallback(0),
218 m_resizeCallback(0),
219 m_keyboardCallback(0)
220 {
221 #ifdef DYNAMIC_LOAD_X11_FUNCTIONS
222 m_x11_library = dlopen(X11_LIBRARY, RTLD_LOCAL | RTLD_NOW);
223 if (!m_x11_library)
224 {
225 printf("Error opening X11 library %s\n", X11_LIBRARY);
226 exit(0);
227 }
228
229 bool missingFunc = false;
230
231 missingFunc = ((m_x11_XFree = (PFNXFREE) dlsym(m_x11_library, "XFree"))==NULL) | missingFunc;
232 assert(!missingFunc);
233 if (missingFunc) { printf("Error: missing func XFree in %s, exiting!\n", X11_LIBRARY); exit(0);}
234 missingFunc = ((m_x11_XSetErrorHandler = (PFNXSETERRORHANDLER) dlsym(m_x11_library,"XSetErrorHandler"))==NULL) | missingFunc;
235 if (missingFunc) { printf("Error: missing func XSetErrorHandler in %s, exiting!\n", X11_LIBRARY); exit(0);}
236 missingFunc = ((m_x11_XSetErrorHandler = (PFNXSETERRORHANDLER) dlsym(m_x11_library,"XSetErrorHandler"))==NULL) | missingFunc;
237 if (missingFunc) { printf("Error: missing func XSetErrorHandler in %s, exiting!\n", X11_LIBRARY); exit(0);}
238 missingFunc = ((m_x11_XSync = (PFNXSYNC) dlsym(m_x11_library,"XSync"))==NULL) | missingFunc;
239 if (missingFunc) { printf("Error: missing func XSync in %s, exiting!\n", X11_LIBRARY); exit(0);}
240 missingFunc = ((m_x11_XOpenDisplay = (PFNXOPENDISPLAY) dlsym(m_x11_library,"XOpenDisplay"))==NULL) | missingFunc;
241 if (missingFunc) { printf("Error: missing func XOpenDisplay in %s, exiting!\n", X11_LIBRARY); exit(0);}
242 missingFunc = ((m_x11_XCreateColormap = (PFNXCREATECOLORMAP) dlsym(m_x11_library,"XCreateColormap"))==NULL) | missingFunc;
243 if (missingFunc) { printf("Error: missing func XCreateColormap in %s, exiting!\n", X11_LIBRARY); exit(0);}
244 missingFunc = ((m_x11_XCreateWindow = (PFNXCREATEWINDOW) dlsym(m_x11_library,"XCreateWindow"))==NULL) | missingFunc;
245 if (missingFunc) { printf("Error: missing func XCreateWindow in %s, exiting!\n", X11_LIBRARY); exit(0);}
246 missingFunc = ((m_x11_XMapWindow = (PFNXMAPWINDOW) dlsym(m_x11_library,"XMapWindow"))==NULL) | missingFunc;
247 if (missingFunc) { printf("Error: missing func XMapWindow in %s, exiting!\n", X11_LIBRARY); exit(0);}
248 missingFunc = ((m_x11_XStoreName = (PFNXSTORENAME) dlsym(m_x11_library,"XStoreName"))==NULL) | missingFunc;
249 if (missingFunc) { printf("Error: missing func XStoreName in %s, exiting!\n", X11_LIBRARY); exit(0);}
250 missingFunc = ((m_x11_XCloseDisplay = (PFNXCLOSEDISPLAY) dlsym(m_x11_library,"XCloseDisplay"))==NULL) | missingFunc;
251 if (missingFunc) { printf("Error: missing func XCloseDisplay in %s, exiting!\n", X11_LIBRARY); exit(0);}
252 missingFunc = ((m_x11_XDestroyWindow = (PFNXDESTROYWINDOW) dlsym(m_x11_library,"XDestroyWindow"))==NULL) | missingFunc;
253 if (missingFunc) { printf("Error: missing func XDestroyWindow in %s, exiting!\n", X11_LIBRARY); exit(0);}
254 missingFunc = ((m_x11_XRaiseWindow = (PFNXRAISEWINDOW) dlsym(m_x11_library,"XRaiseWindow"))==NULL) | missingFunc;
255 if (missingFunc) { printf("Error: missing func XRaiseWindow in %s, exiting!\n", X11_LIBRARY); exit(0);}
256
257 missingFunc = ((m_x11_XGetKeyboardMapping = (PFNXGETKEYBOARDMAPPING) dlsym(m_x11_library,"XGetKeyboardMapping"))==NULL) | missingFunc;
258 if (missingFunc) { printf("Error: missing func XGetKeyboardMapping in %s, exiting!\n", X11_LIBRARY); exit(0);}
259 missingFunc = ((m_x11_XKeycodeToKeysym = (PFNXKEYCODETOKEYSYM) dlsym(m_x11_library,"XKeycodeToKeysym"))==NULL) | missingFunc;
260 if (missingFunc) { printf("Error: missing func XKeycodeToKeysym in %s, exiting!\n", X11_LIBRARY); exit(0);}
261 missingFunc = ((m_x11_XConvertCase = (PFNXCONVERTCASE) dlsym(m_x11_library,"XConvertCase"))==NULL) | missingFunc;
262 if (missingFunc) { printf("Error: missing func XConvertCase in %s, exiting!\n", X11_LIBRARY); exit(0);}
263 missingFunc = ((m_x11_XPending = (PFNXPENDING) dlsym(m_x11_library,"XPending"))==NULL) | missingFunc;
264 if (missingFunc) { printf("Error: missing func XPending in %s, exiting!\n", X11_LIBRARY); exit(0);}
265 missingFunc = ((m_x11_XNextEvent = (PFNXNEXTEVENT) dlsym(m_x11_library,"XNextEvent"))==NULL) | missingFunc;
266 if (missingFunc) { printf("Error: missing func XNextEvent in %s, exiting!\n", X11_LIBRARY); exit(0);}
267 missingFunc = ((m_x11_XEventsQueued = (PFNXEVENTSQUEUED) dlsym(m_x11_library,"XEventsQueued"))==NULL) | missingFunc;
268 if (missingFunc) { printf("Error: missing func XEventsQueued in %s, exiting!\n", X11_LIBRARY); exit(0);}
269 missingFunc = ((m_x11_XPeekEvent = (PFNXPEEKEVENT) dlsym(m_x11_library,"XPeekEvent"))==NULL) | missingFunc;
270 if (missingFunc) { printf("Error: missing func XPeekEvent in %s, exiting!\n", X11_LIBRARY); exit(0);}
271 missingFunc = ((m_x11_XLookupKeysym = (PFNXLOOKUPKEYSYM) dlsym(m_x11_library,"XLookupKeysym"))==NULL) | missingFunc;
272 if (missingFunc) { printf("Error: missing func XLookupKeysym in %s, exiting!\n", X11_LIBRARY); exit(0);}
273 missingFunc = ((m_x11_XGetWindowAttributes = (PFNXGETWINDOWATTRIBUTES) dlsym(m_x11_library,"XGetWindowAttributes"))==NULL) | missingFunc;
274 if (missingFunc) { printf("Error: missing func XGetWindowAttributes in %s, exiting!\n", X11_LIBRARY); exit(0);}
275
276 if (missingFunc)
277 {
278 printf("Error: a missing func in %s, exiting!\n", X11_LIBRARY);
279 exit(0);
280 } else
281 {
282 printf("X11 functions dynamically loaded using dlopen/dlsym OK!\n");
283 }
284 #endif //DYNAMIC_LOAD_X11_FUNCTIONS
285 }
286 };
287
288 #define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
289 #define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
290 typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
291
292 // Helper to check for extension string presence. Adapted from:
293 // http://www.opengl.org/resources/features/OGLextensions/
isExtensionSupported(const char * extList,const char * extension)294 static bool isExtensionSupported(const char *extList, const char *extension)
295 {
296 const char *start;
297 const char *where, *terminator;
298
299 /* Extension names should not have spaces. */
300 where = strchr(extension, ' ');
301 if (where || *extension == '\0')
302 return false;
303
304 /* It takes a bit of care to be fool-proof about parsing the
305 OpenGL extensions string. Don't be fooled by sub-strings,
306 etc. */
307 for (start=extList;;) {
308 where = strstr(start, extension);
309
310 if (!where)
311 break;
312
313 terminator = where + strlen(extension);
314
315 if ( where == start || *(where - 1) == ' ' )
316 if ( *terminator == ' ' || *terminator == '\0' )
317 return true;
318
319 start = terminator;
320 }
321
322 return false;
323 }
324
325 static bool ctxErrorOccurred = false;
ctxErrorHandler(Display * dpy,XErrorEvent * ev)326 static int ctxErrorHandler( Display *dpy, XErrorEvent *ev )
327 {
328 ctxErrorOccurred = true;
329 return 0;
330 }
331
332
333
334
X11OpenGLWindow()335 X11OpenGLWindow::X11OpenGLWindow()
336 :m_OpenGLInitialized(false),
337 m_requestedExit(false)
338 {
339 m_data = new InternalData2;
340 }
341
~X11OpenGLWindow()342 X11OpenGLWindow::~X11OpenGLWindow()
343 {
344 if (m_OpenGLInitialized)
345 {
346 disableOpenGL();
347 }
348
349 delete m_data;
350 }
351
352
353
enableOpenGL()354 void X11OpenGLWindow::enableOpenGL()
355 {
356
357
358 if (forceOpenGL3)
359 {
360 // Get the default screen's GLX extension list
361 const char *glxExts = glXQueryExtensionsString( m_data->m_dpy,
362 DefaultScreen( m_data->m_dpy ) );
363
364 // NOTE: It is not necessary to create or make current to a context before
365 // calling glXGetProcAddressARB, unless we dynamically load OpenGL/GLX/X11
366
367 glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
368 glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
369 glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
370
371 GLXContext ctx = 0;
372
373 // Install an X error handler so the application won't exit if GL 3.0
374 // context allocation fails.
375 //
376 // Note this error handler is global. All display connections in all threads
377 // of a process use the same error handler, so be sure to guard against other
378 // threads issuing X commands while this code is running.
379 ctxErrorOccurred = false;
380 int (*oldHandler)(Display*, XErrorEvent*) =
381 MyXSetErrorHandler(&ctxErrorHandler);
382
383 // Check for the GLX_ARB_create_context extension string and the function.
384 // If either is not present, use GLX 1.3 context creation method.
385 if ( !isExtensionSupported( glxExts, "GLX_ARB_create_context" ) ||
386 !glXCreateContextAttribsARB )
387 {
388 printf( "glXCreateContextAttribsARB() not found"
389 " ... using old-style GLX context\n" );
390 ctx = glXCreateNewContext( m_data->m_dpy, m_data->m_bestFbc, GLX_RGBA_TYPE, 0, True );
391 }
392
393 // If it does, try to get a GL 3.0 context!
394 else
395 {
396 int context_attribs[] = {
397 GLX_CONTEXT_MAJOR_VERSION_ARB ,3,
398 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
399 GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
400 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,None
401 };
402 /*
403 int context_attribs[] =
404 {
405 GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
406 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
407
408 //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
409 None
410 };
411 */
412 printf( "Creating context\n" );
413 ctx = glXCreateContextAttribsARB( m_data->m_dpy, m_data->m_bestFbc, 0,
414 True, context_attribs );
415
416 // Sync to ensure any errors generated are processed.
417 MyXSync( m_data->m_dpy, False );
418 if ( !ctxErrorOccurred && ctx )
419 printf( "Created GL 3.0 context\n" );
420 else
421 {
422 // Couldn't create GL 3.0 context. Fall back to old-style 2.x context.
423 // When a context version below 3.0 is requested, implementations will
424 // return the newest context version compatible with OpenGL versions less
425 // than version 3.0.
426 // GLX_CONTEXT_MAJOR_VERSION_ARB = 1
427 context_attribs[1] = 1;
428 // GLX_CONTEXT_MINOR_VERSION_ARB = 0
429 context_attribs[3] = 0;
430
431 ctxErrorOccurred = false;
432
433 printf( "Failed to create GL 3.0 context"
434 " ... using old-style GLX context\n" );
435 ctx = glXCreateContextAttribsARB( m_data->m_dpy, m_data->m_bestFbc, 0,
436 True, context_attribs );
437 }
438 }
439
440 // Sync to ensure any errors generated are processed.
441 MyXSync( m_data->m_dpy, False );
442
443 // Restore the original error handler
444 MyXSetErrorHandler( oldHandler );
445
446 if ( ctxErrorOccurred || !ctx )
447 {
448 printf( "Failed to create an OpenGL context\n" );
449 exit(1);
450 }
451
452 // Verifying that context is a direct context
453 if ( ! glXIsDirect ( m_data->m_dpy, ctx ) )
454 {
455 printf( "Indirect GLX rendering context obtained\n" );
456 }
457 else
458 {
459 printf( "Direct GLX rendering context obtained\n" );
460 }
461
462 printf( "Making context current\n" );
463 glXMakeCurrent( m_data->m_dpy, m_data->m_win, ctx );
464 m_data->m_glc = ctx;
465
466 } else
467 {
468 m_data->m_glc = glXCreateContext(m_data->m_dpy, m_data->m_vi, NULL, GL_TRUE);
469 glXMakeCurrent(m_data->m_dpy, m_data->m_win, m_data->m_glc);
470 }
471
472 #ifdef GLEW_INIT_OPENGL11_FUNCTIONS
473 {
474 GLboolean res = glewOpenGL11Init();
475 if (res==0)
476 {
477 printf("glewOpenGL11Init OK!\n");
478 } else
479 {
480 printf("ERROR: glewOpenGL11Init failed, exiting!\n");
481 exit(0);
482 }
483 }
484
485 #endif //GLEW_INIT_OPENGL11_FUNCTIONS
486
487 const GLubyte* ven = glGetString(GL_VENDOR);
488 printf("GL_VENDOR=%s\n", ven);
489
490 const GLubyte* ren = glGetString(GL_RENDERER);
491 printf("GL_RENDERER=%s\n",ren);
492 const GLubyte* ver = glGetString(GL_VERSION);
493 printf("GL_VERSION=%s\n", ver);
494 const GLubyte* sl = glGetString(GL_SHADING_LANGUAGE_VERSION);
495 printf("GL_SHADING_LANGUAGE_VERSION=%s\n", sl);
496
497 //Access pthreads as a workaround for a bug in Linux/Ubuntu
498 //See https://bugs.launchpad.net/ubuntu/+source/nvidia-graphics-drivers-319/+bug/1248642
499
500 int i=pthread_getconcurrency();
501 printf("pthread_getconcurrency()=%d\n",i);
502
503 // const GLubyte* ext = glGetString(GL_EXTENSIONS);
504 // printf("GL_EXTENSIONS=%s\n", ext);
505 }
506
disableOpenGL()507 void X11OpenGLWindow::disableOpenGL()
508 {
509 glXMakeCurrent(m_data->m_dpy, None, NULL);
510 glXDestroyContext(m_data->m_dpy, m_data->m_glc);
511 }
512
513
createWindow(const b3gWindowConstructionInfo & ci)514 void X11OpenGLWindow::createWindow(const b3gWindowConstructionInfo& ci)
515 {
516
517 m_data->m_dpy = MyXOpenDisplay(NULL);
518
519 if(m_data->m_dpy == NULL) {
520 printf("\n\tcannot connect to X server\n\n");
521 exit(0);
522 }
523
524 m_data->m_root = DefaultRootWindow(m_data->m_dpy);
525
526
527 #ifdef GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS
528 GLboolean res = glewXInit();
529 if (res==0)
530 {
531 printf("glewXInit OK\n");
532 } else
533 {
534 printf("glewXInit failed, exit\n");
535 exit(0);
536 }
537 #endif //GLEW_DYNAMIC_LOAD_ALL_GLX_FUNCTIONS
538
539
540 if (ci.m_openglVersion < 3)
541 {
542 forceOpenGL3 = false;
543 }
544
545 if (forceOpenGL3)
546 {
547 int glxMinor, glxMajor;
548 if (!glXQueryVersion(m_data->m_dpy,&glxMajor,&glxMinor) || (((glxMajor==1)&&(glxMinor<3)) || (glxMajor<1)))
549 {
550 printf("Invalid GLX version: major %d, minor %d\n",glxMajor,glxMinor);
551 exit(0);
552 }
553
554 static int visual_attribs[] =
555 {
556 GLX_X_RENDERABLE , True,
557 GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
558 GLX_RENDER_TYPE , GLX_RGBA_BIT,
559 GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
560 GLX_RED_SIZE , 8,
561 GLX_GREEN_SIZE , 8,
562 GLX_BLUE_SIZE , 8,
563 GLX_ALPHA_SIZE , 8,
564 GLX_DEPTH_SIZE , 24,
565 GLX_STENCIL_SIZE , 8,
566 GLX_DOUBLEBUFFER , True,
567 None
568 };
569 int fbcount;
570 GLXFBConfig* fbc = glXChooseFBConfig(m_data->m_dpy, DefaultScreen(m_data->m_dpy), visual_attribs, &fbcount);
571 if (!fbc)
572 {
573 printf( "Failed to retrieve a framebuffer config\n" );
574 exit(1);
575 }
576 ///don't use highest samples, it is really slow on some NVIDIA Quadro cards
577 #ifdef USE_HIGHEST_SAMPLES
578 int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
579
580 int i;
581 for (i=0; i<fbcount; ++i)
582 {
583 XVisualInfo *vi = glXGetVisualFromFBConfig( m_data->m_dpy, fbc[i] );
584 if ( vi )
585 {
586 int samp_buf, samples;
587 glXGetFBConfigAttrib( m_data->m_dpy, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
588 glXGetFBConfigAttrib( m_data->m_dpy, fbc[i], GLX_SAMPLES , &samples );
589
590 //printf( " Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
591 // " SAMPLES = %d\n",
592 // i, vi -> visualid, samp_buf, samples );
593
594 if ( best_fbc < 0 || (samp_buf && (samples > best_num_samp)) )
595 best_fbc = i, best_num_samp = samples;
596 if ( worst_fbc < 0 || (!samp_buf || (samples < worst_num_samp)) )
597 worst_fbc = i, worst_num_samp = samples;
598 }
599 MyXFree( vi );
600 }
601
602 m_data->m_bestFbc = fbc[ best_fbc ];
603 #else
604 m_data->m_bestFbc = *fbc;
605 #endif
606 // Be sure to free the FBConfig list allocated by glXChooseFBConfig()
607 MyXFree( fbc );
608
609 m_data->m_vi = glXGetVisualFromFBConfig( m_data->m_dpy, m_data->m_bestFbc );
610
611
612 m_data->m_swa.colormap = m_data->m_cmap = MyXCreateColormap( m_data->m_dpy,
613 RootWindow( m_data->m_dpy, m_data->m_vi->screen ),
614 m_data->m_vi->visual, AllocNone );
615 m_data->m_swa.background_pixmap = None ;
616 m_data->m_swa.border_pixel = 0;
617 m_data->m_swa.event_mask = ExposureMask | KeyReleaseMask | KeyPressMask |ButtonPressMask | ButtonReleaseMask |PointerMotionMask|StructureNotifyMask;
618 ;
619 m_data->m_root = RootWindow( m_data->m_dpy, m_data->m_vi->screen );
620
621 m_data->m_win = MyXCreateWindow( m_data->m_dpy, m_data->m_root,
622 0, 0, ci.m_width, ci.m_height, 0, m_data->m_vi->depth, InputOutput,
623 m_data->m_vi->visual,
624 CWBorderPixel|CWColormap|CWEventMask, &m_data->m_swa );
625
626 //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);
627
628
629 if (!m_data->m_win)
630 {
631 printf("Cannot create window\n");
632 exit(0);
633 }
634
635 MyXMapWindow(m_data->m_dpy, m_data->m_win);
636 MyXStoreName(m_data->m_dpy, m_data->m_win, "OpenGL3 Window");
637
638
639 } else
640 {
641 m_data->m_vi = glXChooseVisual(m_data->m_dpy, 0, att);
642
643 printf("4\n");
644
645 if(m_data->m_vi == NULL) {
646 printf("\n\tno appropriate visual found\n\n");
647 exit(0);
648 }
649 else {
650 printf("\n\tvisual %p selected\n", (void *)m_data->m_vi->visualid); /* %p creates hexadecimal output like in glxinfo */
651 }
652
653
654 m_data->m_cmap = MyXCreateColormap(m_data->m_dpy, m_data->m_root, m_data->m_vi->visual, AllocNone);
655 m_data->m_swa.colormap = m_data->m_cmap;
656 m_data->m_swa.event_mask = ExposureMask | KeyReleaseMask | KeyPressMask |ButtonPressMask | ButtonReleaseMask |PointerMotionMask|StructureNotifyMask;
657 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);
658
659 MyXMapWindow(m_data->m_dpy, m_data->m_win);
660
661 MyXStoreName(m_data->m_dpy, m_data->m_win, "OpenGL2 Window");
662
663
664 }
665
666 enableOpenGL();
667 }
668
closeWindow()669 void X11OpenGLWindow::closeWindow()
670 {
671 disableOpenGL();
672
673 MyXDestroyWindow(m_data->m_dpy, m_data->m_win);
674 MyXCloseDisplay(m_data->m_dpy);
675 }
676
getAsciiCodeFromVirtualKeycode(int keycode)677 int X11OpenGLWindow::getAsciiCodeFromVirtualKeycode(int keycode)
678 {
679 int result = 0;
680
681 KeySym key, key_lc, key_uc;
682
683 int keysyms_per_keycode_return;
684 KeySym *keysym = MyXGetKeyboardMapping(m_data->m_dpy,
685 keycode,
686 1,
687 &keysyms_per_keycode_return);
688
689 key = keysym[0];
690
691
692 //key = MyXKeycodeToKeysym( m_data->m_dpy, keycode, 0 );
693
694 switch( key )
695 {
696 case XK_Escape: return B3G_ESCAPE;
697 case XK_Return: return B3G_RETURN;
698 case XK_BackSpace: return B3G_BACKSPACE;
699 case XK_Delete: return B3G_DELETE;
700 case XK_Tab: return 9;
701
702 case XK_Control_L:
703 case XK_Control_R: {
704 return B3G_CONTROL;
705 }
706 case XK_Left: return B3G_LEFT_ARROW;
707 case XK_Right: return B3G_RIGHT_ARROW;
708 case XK_Up: return B3G_UP_ARROW;
709 case XK_Down: return B3G_DOWN_ARROW;
710
711 case XK_Alt_L:
712 case XK_Alt_R:
713 {
714 return B3G_ALT;
715 }
716 case XK_Shift_L:
717 case XK_Shift_R: return B3G_SHIFT;
718 case XK_F1: return B3G_F1;
719 case XK_F2: return B3G_F2;
720 case XK_F3: return B3G_F3;
721 case XK_F4: return B3G_F4;
722 case XK_F5: return B3G_F5;
723 case XK_F6: return B3G_F6;
724 case XK_F7: return B3G_F7;
725 case XK_F8: return B3G_F8;
726 case XK_F9: return B3G_F9;
727 case XK_F10: return B3G_F10;
728 case XK_F11: return B3G_F11;
729 case XK_F12: return B3G_F12;
730 case XK_F13: return B3G_F13;
731 case XK_F14: return B3G_F14;
732 case XK_F15: return B3G_F15;
733 default:
734 // Make lowercase
735 MyXConvertCase( key, &key_lc, &key_uc );
736 key = key_lc;
737 // Valid ISO 8859-1 character?
738 if( (key >= 32 && key <= 126) ||(key >= 160 && key <= 255) )
739 {
740 return (int) key;
741 }
742 result = -1;
743 }
744
745 MyXFree(keysym);
746
747 return result;
748 }
749
isModifierKeyPressed(int key)750 bool X11OpenGLWindow::isModifierKeyPressed(int key)
751 {
752 bool isPressed = false;
753
754 switch (key)
755 {
756 case B3G_ALT:
757 {
758 isPressed = ((m_data->m_modifierFlags & MY_X11_ALT_KEY)!=0);
759 break;
760 };
761 case B3G_SHIFT:
762 {
763 isPressed = ((m_data->m_modifierFlags & MY_X11_SHIFT_KEY)!=0);
764 break;
765 };
766 case B3G_CONTROL:
767 {
768 isPressed = ((m_data->m_modifierFlags & MY_X11_CONTROL_KEY )!=0);
769 break;
770 };
771
772 default:
773 {
774 }
775 };
776 return isPressed;
777 }
778
pumpMessage()779 void X11OpenGLWindow::pumpMessage()
780 {
781
782 int buttonState = 1;
783
784 // Process all pending events
785 while( MyXPending( m_data->m_dpy ) )
786 {
787 MyXNextEvent(m_data->m_dpy, &m_data->m_xev);
788 // printf("#");
789 // fflush(stdout);
790 switch( m_data->m_xev.type )
791 {
792 case KeyPress:
793 {
794 int keycode = getAsciiCodeFromVirtualKeycode(m_data->m_xev.xkey.keycode);
795 switch (keycode)
796 {
797 case B3G_ALT:
798 m_data->m_modifierFlags |= MY_X11_ALT_KEY;
799 break;
800 case B3G_SHIFT:
801 m_data->m_modifierFlags |= MY_X11_SHIFT_KEY;
802 break;
803 case B3G_CONTROL:
804 m_data->m_modifierFlags |= MY_X11_CONTROL_KEY;
805 break;
806 default:
807 {}
808 };
809 if (m_data->m_keyboardCallback)
810 {
811
812 int state = 1;
813 (*m_data->m_keyboardCallback)(keycode,state);
814 // printf("keycode %d",keycode);
815 // fflush(stdout);
816
817 }
818 break;
819 }
820
821 case KeyRelease:
822 {
823 // fflush(stdout);
824 int keycode = getAsciiCodeFromVirtualKeycode( m_data->m_xev.xkey.keycode);
825 switch (keycode)
826 {
827 case B3G_ALT:
828 m_data->m_modifierFlags &= ~MY_X11_ALT_KEY;
829 break;
830 case B3G_SHIFT:
831 m_data->m_modifierFlags &= ~MY_X11_SHIFT_KEY;
832 break;
833 case B3G_CONTROL:
834 m_data->m_modifierFlags &= ~MY_X11_CONTROL_KEY;
835 break;
836 default:
837 {}
838 };
839
840 if (m_data->m_keyboardCallback)
841 {
842 #if 0
843 unsigned short is_retriggered = 0;
844 ///filter out keyboard repeat
845 //see http://stackoverflow.com/questions/2100654/ignore-auto-repeat-in-x11-applications
846 if (MyXEventsQueued(m_data->m_dpy, QueuedAfterReading))
847 {
848 XEvent nev;
849 MyXPeekEvent(m_data->m_dpy, &nev);
850
851 if (nev.type == KeyPress && nev.xkey.time == m_data->m_xev.xkey.time &&
852 nev.xkey.keycode == m_data->m_xev.xkey.keycode)
853 {
854 fprintf (stdout, "key #%ld was retriggered.\n",
855 (long) MyXLookupKeysym(&nev.xkey, 0));
856
857 // delete retriggered KeyPress event
858 MyXNextEvent(m_data->m_dpy, & m_data->m_xev);
859 is_retriggered = 1;
860 }
861 }
862 #endif
863 int state = 0;
864 (*m_data->m_keyboardCallback)(keycode,state);
865 }
866
867 break;
868 }
869
870 case ButtonRelease:
871 buttonState = 0;
872 //continue with ButtonPress code
873 case ButtonPress:
874 {
875 // printf("!");
876 // fflush(stdout);
877
878 int button=-1;
879
880 switch (m_data->m_xev.xbutton.button)
881 {
882 case Button1:
883 {
884 button=0;
885 break;
886 }
887 case Button2:
888 {
889 button=1;
890 break;
891 }
892 case Button3:
893 {
894 button=2;
895 break;
896 }
897 case Button4:
898 {
899 if (m_data->m_wheelCallback)
900 {
901 (*m_data->m_wheelCallback)(0,10);
902 }
903 break;
904 }
905 case Button5:
906 {
907 if (m_data->m_wheelCallback)
908 {
909 (*m_data->m_wheelCallback)(0,-10);
910 }
911 break;
912 }
913 }
914 int xpos = m_data->m_xev.xmotion.x;
915 int ypos = m_data->m_xev.xmotion.y;
916
917 if (button>=0 && m_data->m_mouseButtonCallback)
918 {
919 // printf("xpos = %d, ypos = %d\n",xpos,ypos);
920
921 (*m_data->m_mouseButtonCallback)(button,buttonState,xpos,ypos);
922 }
923 break;
924 }
925 case MotionNotify:
926 {
927 // printf("!");
928 // fflush(0);
929 if (m_data->m_mouseMoveCallback)
930 {
931 int xpos = m_data->m_xev.xmotion.x;
932 int ypos = m_data->m_xev.xmotion.y;
933 (*m_data->m_mouseMoveCallback)(xpos,ypos);
934 }
935 break;
936 }
937 case ConfigureNotify:
938 {
939 // printf("@");
940 // fflush(0);
941 m_data->m_glWidth = m_data->m_xev.xconfigure.width;
942 m_data->m_glHeight = m_data->m_xev.xconfigure.height;
943
944 if (m_data->m_resizeCallback)
945 {
946 (*m_data->m_resizeCallback)(m_data->m_xev.xconfigure.width,m_data->m_xev.xconfigure.height);
947 }
948 break;
949 }
950 case ClientMessage:
951 {
952 // printf("?");
953 // fflush(stdout);
954 break;
955 }
956 case Expose:
957 {
958 break;
959 }
960 case DestroyNotify:
961 {
962 break;
963 }
964 default:
965 {
966 //XRRUpdateConfiguration( &event );
967 }
968 };
969 }
970 }
971
972
973
startRendering()974 void X11OpenGLWindow::startRendering()
975 {
976 pumpMessage();
977
978 MyXGetWindowAttributes(m_data->m_dpy, m_data->m_win, &m_data->m_gwa);
979 glViewport(0, 0, m_data->m_gwa.width, m_data->m_gwa.height);
980
981 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); //clear buffers
982
983 //glCullFace(GL_BACK);
984 //glFrontFace(GL_CCW);
985 glEnable(GL_DEPTH_TEST);
986 }
987
renderAllObjects()988 void X11OpenGLWindow::renderAllObjects()
989 {
990
991 }
992
endRendering()993 void X11OpenGLWindow::endRendering()
994 {
995 glXSwapBuffers(m_data->m_dpy, m_data->m_win);
996 }
997
runMainLoop()998 void X11OpenGLWindow::runMainLoop()
999 {
1000
1001 }
1002
getTimeInSeconds()1003 float X11OpenGLWindow::getTimeInSeconds()
1004 {
1005 return 0.f;
1006 }
1007
requestedExit() const1008 bool X11OpenGLWindow::requestedExit() const
1009 {
1010 return m_requestedExit;
1011 }
1012
setRequestExit()1013 void X11OpenGLWindow::setRequestExit()
1014 {
1015 m_requestedExit=true;
1016 }
1017
setRenderCallback(b3RenderCallback renderCallback)1018 void X11OpenGLWindow::setRenderCallback( b3RenderCallback renderCallback)
1019 {
1020
1021 }
1022
setWindowTitle(const char * title)1023 void X11OpenGLWindow::setWindowTitle(const char* title)
1024 {
1025 MyXStoreName(m_data->m_dpy, m_data->m_win, title);
1026 }
1027
1028
setWheelCallback(b3WheelCallback wheelCallback)1029 void X11OpenGLWindow::setWheelCallback(b3WheelCallback wheelCallback)
1030 {
1031 m_data->m_wheelCallback = wheelCallback;
1032 }
1033
setMouseMoveCallback(b3MouseMoveCallback mouseCallback)1034 void X11OpenGLWindow::setMouseMoveCallback(b3MouseMoveCallback mouseCallback)
1035 {
1036 m_data->m_mouseMoveCallback = mouseCallback;
1037 }
1038
setMouseButtonCallback(b3MouseButtonCallback mouseCallback)1039 void X11OpenGLWindow::setMouseButtonCallback(b3MouseButtonCallback mouseCallback)
1040 {
1041 m_data->m_mouseButtonCallback = mouseCallback;
1042 }
1043
setResizeCallback(b3ResizeCallback resizeCallback)1044 void X11OpenGLWindow::setResizeCallback(b3ResizeCallback resizeCallback)
1045 {
1046 if (resizeCallback && m_data->m_glWidth>0 && m_data->m_glHeight > 0)
1047 {
1048 resizeCallback(m_data->m_glWidth, m_data->m_glHeight);
1049 }
1050 m_data->m_resizeCallback = resizeCallback;
1051 }
1052
setKeyboardCallback(b3KeyboardCallback keyboardCallback)1053 void X11OpenGLWindow::setKeyboardCallback( b3KeyboardCallback keyboardCallback)
1054 {
1055 m_data->m_keyboardCallback = keyboardCallback;
1056
1057 }
1058
getMouseMoveCallback()1059 b3MouseMoveCallback X11OpenGLWindow::getMouseMoveCallback()
1060 {
1061 return m_data->m_mouseMoveCallback;
1062 }
getMouseButtonCallback()1063 b3MouseButtonCallback X11OpenGLWindow::getMouseButtonCallback()
1064 {
1065 return m_data->m_mouseButtonCallback;
1066 }
getResizeCallback()1067 b3ResizeCallback X11OpenGLWindow::getResizeCallback()
1068 {
1069 return m_data->m_resizeCallback;
1070 }
getWheelCallback()1071 b3WheelCallback X11OpenGLWindow::getWheelCallback()
1072 {
1073 return m_data->m_wheelCallback;
1074 }
1075
1076
getKeyboardCallback()1077 b3KeyboardCallback X11OpenGLWindow::getKeyboardCallback()
1078 {
1079 return m_data->m_keyboardCallback;
1080 }
1081
getWidth() const1082 int X11OpenGLWindow::getWidth() const
1083 {
1084 if (m_data)
1085 return m_data->m_glWidth;
1086 return 0;
1087 }
getHeight() const1088 int X11OpenGLWindow::getHeight() const
1089 {
1090 if (m_data)
1091 return m_data->m_glHeight;
1092 return 0;
1093 }
1094
1095
1096 #include <stdio.h>
1097
fileOpenDialog(char * filename,int maxNameLength)1098 int X11OpenGLWindow::fileOpenDialog(char* filename, int maxNameLength)
1099 {
1100 int len = 0;
1101 FILE * output = popen("zenity --file-selection --file-filter=\"*.urdf\" --file-filter=\"*.sdf\" --file-filter=\"*.obj\" --file-filter=\"*.*\"","r");
1102 if (output)
1103 {
1104 while( fgets(filename, maxNameLength-1, output) != NULL )
1105 {
1106 len=strlen(filename);
1107 if (len>0)
1108 {
1109 filename[len-1]=0;
1110 printf("file open (length=%d) = %s\n", len,filename);
1111 }
1112 }
1113 pclose(output);
1114 } else
1115 {
1116 printf("Error: fileOpenDialog no popen output, perhaps install zenity?\n");
1117 }
1118 MyXRaiseWindow(m_data->m_dpy, m_data->m_win);
1119 return len;
1120
1121 }
1122