glgraphics.linux.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. #include <stdio.h>
  2. #include <GL/gl.h>
  3. #include <GL/glx.h>
  4. #include <X11/extensions/xf86vmode.h>
  5. #include <assert.h>
  6. /* Added by BaH */
  7. #include <brl.mod/blitz.mod/blitz.h>
  8. #include <X11/Xutil.h>
  9. extern void bbSystemPoll();
  10. extern Display *bbSystemDisplay();
  11. extern void bbSetSystemWindow(int window);
  12. static XF86VidModeModeInfo **modes,*mode;
  13. static Display *xdisplay;
  14. static int xscreen,xwindow,xfullscreen;
  15. typedef int (* GLXSWAPINTERVALEXT) (int);
  16. GLXSWAPINTERVALEXT glXSwapIntervalEXT;
  17. void *glXExtension(Display *dpy,int screen,const char *catagory,const char *name){
  18. const char *extensions;
  19. extensions=glXQueryExtensionsString(dpy,screen);
  20. if (strstr(extensions,catagory)) {
  21. return (void*)glXGetProcAddressARB(name);
  22. }
  23. return (void*)0;
  24. }
  25. enum{
  26. MODE_SHARED=0,
  27. MODE_WIDGET=1,
  28. MODE_WINDOW=2,
  29. MODE_DISPLAY=3
  30. };
  31. enum{
  32. FLAGS_BACKBUFFER= 0x2,
  33. FLAGS_ALPHABUFFER= 0x4,
  34. FLAGS_DEPTHBUFFER= 0x8,
  35. FLAGS_STENCILBUFFER=0x10,
  36. FLAGS_ACCUMBUFFER= 0x20,
  37. FLAGS_FULLSCREEN=0x80000000
  38. };
  39. typedef struct BBGLContext BBGLContext;
  40. struct BBGLContext{
  41. int mode,width,height,depth,hertz,flags,sync;
  42. int window;
  43. GLXContext glContext;
  44. };
  45. // glgraphics.bmx interface
  46. int bbGLGraphicsGraphicsModes( int *imodes,int maxcount );
  47. BBGLContext *bbGLGraphicsAttachGraphics( int window,int flags );
  48. BBGLContext *bbGLGraphicsCreateGraphics( int width,int height,int depth,int hz,int flags );
  49. void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hz,int *flags );
  50. void bbGLGraphicsClose( BBGLContext *context );
  51. void bbGLGraphicsSetGraphics( BBGLContext *context );
  52. void bbGLGraphicsFlip( int sync );
  53. void bbGLExit();
  54. static BBGLContext *_currentContext;
  55. static BBGLContext *_activeContext;
  56. static BBGLContext *_sharedContext;
  57. #define INTERLACE 0x010
  58. #define DBLSCAN 0x020
  59. static XF86VidModeModeInfo _oldMode;
  60. int _calchertz(XF86VidModeModeInfo *m){
  61. int freq;
  62. freq=(m->dotclock*1000.0)/(m->htotal*m->vtotal)+.5;
  63. if (m->flags&INTERLACE) freq<<=1;
  64. if (m->flags&DBLSCAN) freq>>=1;
  65. return freq;
  66. }
  67. int _initDisplay(){
  68. int major,minor;
  69. if (xdisplay) return 0;
  70. xdisplay=bbSystemDisplay();
  71. if (!xdisplay) return -1;
  72. if (glXQueryVersion(xdisplay,&major,&minor)==0) return -1;
  73. // printf("glXVersion=%d.%d\n",major,minor);fflush(stdout);
  74. XF86VidModeQueryVersion(xdisplay,&major,&minor);
  75. // printf("XF86VidModeExtension-Version %d.%d\n", major,minor);
  76. xscreen=DefaultScreen(xdisplay);
  77. // glXSwapIntervalEXT=(GLXSWAPINTERVALEXT)glXGetProcAddressARB("glXSwapIntervalSGI");
  78. glXSwapIntervalEXT=(GLXSWAPINTERVALEXT)glXExtension(xdisplay,xscreen,"GLX_SGI_swap_control","glXSwapIntervalSGI");
  79. atexit( bbGLExit );
  80. return 0;
  81. }
  82. int bbGLGraphicsGraphicsModes( int *imodes,int maxcount ){
  83. XF86VidModeModeInfo **xmodes,*m;
  84. int count,i;
  85. if (_initDisplay()) return 0;
  86. XF86VidModeGetAllModeLines(xdisplay,xscreen,&count,&xmodes);
  87. if (count>maxcount) count=maxcount;
  88. for (i=0;i<count;i++)
  89. {
  90. m=xmodes[i];
  91. *imodes++=m->hdisplay; //width
  92. *imodes++=m->vdisplay; //height;
  93. *imodes++=24;
  94. *imodes++=_calchertz(m);
  95. }
  96. XFree(xmodes);
  97. return count;
  98. }
  99. static void _swapBuffers( BBGLContext *context ){
  100. if( !context ) return;
  101. glXSwapBuffers(xdisplay,context->window);
  102. bbSystemPoll();
  103. }
  104. BBGLContext *bbGLGraphicsAttachGraphics( int window,int flags ){
  105. BBGLContext *context=(BBGLContext*)malloc( sizeof(BBGLContext) );
  106. memset( context,0,sizeof(BBGLContext) );
  107. context->mode=MODE_WIDGET;
  108. context->flags=flags;
  109. context->sync=-1;
  110. context->window=window;
  111. return context;
  112. }
  113. XVisualInfo *_chooseVisual(flags){
  114. int glspec[32],*s;
  115. s=glspec;
  116. *s++=GLX_RGBA;
  117. if (flags&FLAGS_BACKBUFFER) *s++=GLX_DOUBLEBUFFER;
  118. if (flags&FLAGS_ALPHABUFFER) {*s++=GLX_ALPHA_SIZE;*s++=1;}
  119. if (flags&FLAGS_DEPTHBUFFER) {*s++=GLX_DEPTH_SIZE;*s++=1;}
  120. if (flags&FLAGS_STENCILBUFFER) {*s++=GLX_STENCIL_SIZE;*s++=1;}
  121. if (flags&FLAGS_ACCUMBUFFER)
  122. {
  123. *s++=GLX_ACCUM_RED_SIZE;*s++=1;
  124. *s++=GLX_ACCUM_GREEN_SIZE;*s++=1;
  125. *s++=GLX_ACCUM_BLUE_SIZE;*s++=1;
  126. *s++=GLX_ACCUM_ALPHA_SIZE;*s++=1;
  127. }
  128. *s++=None;
  129. return glXChooseVisual(xdisplay,xscreen,glspec);
  130. }
  131. void _makeCurrent( BBGLContext *context ){
  132. glXMakeCurrent(xdisplay,context->window,context->glContext);
  133. _currentContext=context;
  134. }
  135. static void _validateSize( BBGLContext *context ){
  136. Window root_return;
  137. int x,y;
  138. unsigned int w,h,border,d;
  139. if( !context || context->mode!=MODE_WIDGET ) return;
  140. if (_initDisplay()) return;
  141. XGetGeometry(xdisplay,context->window,&root_return,&x,&y,&w,&h,&border,&d);
  142. context->width=w;
  143. context->height=h;
  144. }
  145. static void _validateContext( BBGLContext *context ){
  146. GLXContext sharedcontext=0;
  147. XVisualInfo *vizinfo;
  148. if( !context || context->glContext ) return;
  149. if (_initDisplay()) return;
  150. //_initSharedContext();
  151. if( _sharedContext ) sharedcontext=_sharedContext->glContext;
  152. vizinfo=_chooseVisual(context->flags);
  153. context->glContext=glXCreateContext(xdisplay,vizinfo,sharedcontext,True);
  154. glXMakeCurrent(xdisplay,context->window,context->glContext);
  155. bbSetSystemWindow(context->window);
  156. }
  157. void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hertz,int *flags ){
  158. _validateSize( context );
  159. *width=context->width;
  160. *height=context->height;
  161. *depth=context->depth;
  162. *hertz=context->hertz;
  163. *flags=context->flags;
  164. }
  165. static Bool WaitForNotify(Display *display,XEvent *event,XPointer arg){
  166. return (event->type==MapNotify) && (event->xmap.window==(Window)arg);
  167. }
  168. void bbGLGraphicsShareContexts(){
  169. if( _sharedContext ) return;
  170. _sharedContext=bbGLGraphicsCreateGraphics(0,0,0,0,0);
  171. }
  172. BBGLContext *bbGLGraphicsCreateGraphics( int width,int height,int depth,int hz,int flags ){
  173. XSetWindowAttributes swa;
  174. XVisualInfo *vizinfo;
  175. XEvent event;
  176. GLXContext context;
  177. int window;
  178. int count,i;
  179. int displaymode;
  180. int initingShared=0;
  181. GLXContext sharedcontext=0;
  182. char *appTitle;
  183. if (_initDisplay()) return 0;
  184. if( width==0 && height==0 )
  185. {
  186. width=100;
  187. height=100;
  188. initingShared=1;
  189. }
  190. else
  191. {
  192. if( _sharedContext ) sharedcontext=_sharedContext->glContext;
  193. //_initSharedContext();
  194. //sharedcontext=_sharedContext->glContext;
  195. }
  196. vizinfo=_chooseVisual(flags);
  197. if (depth)
  198. {
  199. XF86VidModeGetModeLine(xdisplay,xscreen,&_oldMode.dotclock,(XF86VidModeModeLine*)&_oldMode.hdisplay );
  200. XF86VidModeGetAllModeLines(xdisplay,xscreen,&count,&modes);
  201. mode=0;
  202. for (i=0;i<count;i++)
  203. {
  204. if (width==modes[i]->hdisplay && height==modes[i]->vdisplay && hz==_calchertz(modes[i]))
  205. {
  206. mode=modes[i];
  207. break;
  208. }
  209. }
  210. if (mode==0)
  211. {
  212. for (i=0;i<count;i++)
  213. {
  214. if (width==modes[i]->hdisplay && height==modes[i]->vdisplay)
  215. {
  216. mode=modes[i];
  217. break;
  218. }
  219. }
  220. }
  221. if (mode==0) return;
  222. width=mode->hdisplay;
  223. height=mode->vdisplay;
  224. vizinfo=_chooseVisual(flags);
  225. swa.border_pixel=0;
  226. swa.event_mask=StructureNotifyMask;
  227. swa.colormap=XCreateColormap(xdisplay,RootWindow(xdisplay,0),vizinfo->visual,AllocNone);
  228. swa.override_redirect=True;
  229. XF86VidModeSwitchToMode(xdisplay,xscreen,mode);
  230. XF86VidModeSetViewPort(xdisplay,xscreen,0,0);
  231. window=XCreateWindow(
  232. xdisplay,
  233. RootWindow(xdisplay,xscreen),
  234. 0,
  235. 0,
  236. width,height,
  237. 0,
  238. vizinfo->depth,
  239. InputOutput,
  240. vizinfo->visual,
  241. CWBorderPixel|CWEventMask|CWColormap|CWOverrideRedirect,
  242. &swa
  243. );
  244. xfullscreen=1;
  245. displaymode=MODE_DISPLAY;
  246. }
  247. else
  248. {
  249. Atom atom;
  250. XSizeHints *hints;
  251. swa.border_pixel=0;
  252. swa.event_mask=StructureNotifyMask;
  253. swa.colormap=XCreateColormap( xdisplay,RootWindow(xdisplay,0),vizinfo->visual,AllocNone );
  254. window=XCreateWindow(
  255. xdisplay,
  256. RootWindow(xdisplay,xscreen),
  257. 0,
  258. 0,
  259. width,height,
  260. 0,
  261. vizinfo->depth,
  262. InputOutput,
  263. vizinfo->visual,
  264. CWBorderPixel|CWColormap|CWEventMask,
  265. &swa
  266. );
  267. //Tell window to send us 'close window events'
  268. atom=XInternAtom( xdisplay,"WM_DELETE_WINDOW",True );
  269. XSetWMProtocols( xdisplay,window,&atom,1 );
  270. //Set window min/max size
  271. hints=XAllocSizeHints();
  272. hints->flags=PMinSize|PMaxSize;
  273. hints->min_width=hints->max_width=width;
  274. hints->min_height=hints->max_height=height;
  275. XSetWMNormalHints( xdisplay,window,hints );
  276. displaymode=MODE_WINDOW;
  277. }
  278. context=glXCreateContext(xdisplay,vizinfo,sharedcontext,True);
  279. if( !initingShared )
  280. {
  281. XMapRaised(xdisplay,window);
  282. if (xfullscreen)
  283. {
  284. XWarpPointer(xdisplay,None,window,0,0,0,0,0,0);
  285. XGrabKeyboard(xdisplay,window,True,GrabModeAsync,GrabModeAsync,CurrentTime);
  286. XGrabPointer(xdisplay,window,True,ButtonPressMask,GrabModeAsync,GrabModeAsync,window,None,CurrentTime);
  287. }
  288. glXMakeCurrent(xdisplay,window,context);
  289. XIfEvent(xdisplay,&event,WaitForNotify,(XPointer)window);
  290. XSelectInput(xdisplay,window,ResizeRedirectMask|PointerMotionMask|ButtonPressMask|ButtonReleaseMask|KeyPressMask|KeyReleaseMask);
  291. xwindow=window;
  292. bbSetSystemWindow(xwindow);
  293. }
  294. appTitle=bbTmpUTF8String( bbAppTitle );
  295. XChangeProperty( xdisplay,window,
  296. XInternAtom( xdisplay,"_NET_WM_NAME",True ),
  297. XInternAtom( xdisplay,"UTF8_STRING",True ),
  298. 8,PropModeReplace,appTitle,strlen( appTitle ) );
  299. // XStoreName( xdisplay,window,appTitle );
  300. bbSystemPoll();
  301. BBGLContext *bbcontext=(BBGLContext*)malloc( sizeof(BBGLContext) );
  302. memset( bbcontext,0,sizeof(BBGLContext) );
  303. bbcontext->mode=displaymode;
  304. bbcontext->width=width;
  305. bbcontext->height=height;
  306. bbcontext->depth=24;
  307. bbcontext->hertz=hz;
  308. bbcontext->flags=flags;
  309. bbcontext->sync=-1;
  310. bbcontext->window=window;
  311. bbcontext->glContext=context;
  312. return bbcontext;
  313. }
  314. void bbGLGraphicsSetGraphics( BBGLContext *context ){
  315. if( context ){
  316. _validateSize( context );
  317. _validateContext( context );
  318. }
  319. if( !context || context==_currentContext ) return;
  320. _makeCurrent(context);
  321. _activeContext=context;
  322. }
  323. void bbGLGraphicsFlip( int sync ){
  324. if( !_currentContext ) return;
  325. sync=sync ? 1 : 0;
  326. if( sync!=_currentContext->sync ){
  327. _currentContext->sync=sync;
  328. if ( glXSwapIntervalEXT ) {
  329. glXSwapIntervalEXT( sync );
  330. }
  331. }
  332. _swapBuffers( _currentContext );
  333. }
  334. void bbGLGraphicsClose( BBGLContext *context ){
  335. if (context){
  336. if (_currentContext==context) _currentContext=0;
  337. if (context->glContext)
  338. {
  339. glXMakeCurrent(xdisplay,None,NULL);
  340. glXDestroyContext(xdisplay,context->glContext);
  341. }
  342. if (context->window && context->mode!=MODE_WIDGET){
  343. XDestroyWindow(xdisplay,context->window);
  344. }
  345. if (context->mode==MODE_DISPLAY){
  346. XF86VidModeSwitchToMode(xdisplay,xscreen,&_oldMode);
  347. XF86VidModeSetViewPort(xdisplay,xscreen,0,0);
  348. XFlush(xdisplay);
  349. XFree(modes);
  350. modes=0;
  351. mode=0;
  352. xfullscreen=0;
  353. }
  354. free( context );
  355. }
  356. }
  357. void bbGLExit(){
  358. bbGLGraphicsClose( _currentContext );
  359. bbGLGraphicsClose( _sharedContext );
  360. _currentContext=0;
  361. _sharedContext=0;
  362. }