glgraphics.linux.c 11 KB

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