🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1118 lines
36 KiB

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