#include #include #include #include #include /* Added by BaH */ #include #include extern void bbSystemPoll(); extern Display *bbSystemDisplay(); extern void bbSetSystemWindow(int window); static XF86VidModeModeInfo **modes,*mode; static Display *xdisplay; static int xscreen,xwindow,xfullscreen; typedef int (* GLXSWAPINTERVALEXT) (int); GLXSWAPINTERVALEXT glXSwapIntervalEXT; void *glXExtension(Display *dpy,int screen,const char *catagory,const char *name){ const char *extensions; extensions=glXQueryExtensionsString(dpy,screen); if (strstr(extensions,catagory)) { return (void*)glXGetProcAddressARB(name); } return (void*)0; } enum{ MODE_SHARED=0, MODE_WIDGET=1, MODE_WINDOW=2, MODE_DISPLAY=3 }; enum{ FLAGS_BACKBUFFER= 0x2, FLAGS_ALPHABUFFER= 0x4, FLAGS_DEPTHBUFFER= 0x8, FLAGS_STENCILBUFFER=0x10, FLAGS_ACCUMBUFFER= 0x20, FLAGS_BORDERLESS= 0x40, FLAGS_FULLSCREEN_DESKTOP=0x80 }; typedef struct BBGLContext BBGLContext; struct BBGLContext{ int mode,width,height,depth,hertz; BBInt64 flags; int sync; Window window; GLXContext glContext; }; // glgraphics.bmx interface int bbGLGraphicsGraphicsModes( int *imodes,int maxcount ); BBGLContext *bbGLGraphicsAttachGraphics( void * window,BBInt64 flags ); BBGLContext *bbGLGraphicsCreateGraphics( int width,int height,int depth,int hz,BBInt64 flags, int x, int y ); void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hz,BBInt64 *flags ); void bbGLGraphicsClose( BBGLContext *context ); void bbGLGraphicsSetGraphics( BBGLContext *context ); void bbGLGraphicsFlip( int sync ); void bbGLExit(); static BBGLContext *_currentContext; static BBGLContext *_activeContext; static BBGLContext *_sharedContext; #define INTERLACE 0x010 #define DBLSCAN 0x020 static XF86VidModeModeInfo _oldMode; int _calchertz(XF86VidModeModeInfo *m){ int freq; freq=(m->dotclock*1000.0)/(m->htotal*m->vtotal)+.5; if (m->flags&INTERLACE) freq<<=1; if (m->flags&DBLSCAN) freq>>=1; return freq; } int _initDisplay(){ int major,minor; if (xdisplay) return 0; xdisplay=bbSystemDisplay(); if (!xdisplay) return -1; if (glXQueryVersion(xdisplay,&major,&minor)==0) return -1; // printf("glXVersion=%d.%d\n",major,minor);fflush(stdout); XF86VidModeQueryVersion(xdisplay,&major,&minor); // printf("XF86VidModeExtension-Version %d.%d\n", major,minor); xscreen=DefaultScreen(xdisplay); // glXSwapIntervalEXT=(GLXSWAPINTERVALEXT)glXGetProcAddressARB("glXSwapIntervalSGI"); glXSwapIntervalEXT=(GLXSWAPINTERVALEXT)glXExtension(xdisplay,xscreen,"GLX_SGI_swap_control","glXSwapIntervalSGI"); atexit( bbGLExit ); return 0; } int bbGLGraphicsGraphicsModes( int *imodes,int maxcount ){ XF86VidModeModeInfo **xmodes,*m; int count,i; if (_initDisplay()) return 0; XF86VidModeGetAllModeLines(xdisplay,xscreen,&count,&xmodes); if (count>maxcount) count=maxcount; for (i=0;ihdisplay; //width *imodes++=m->vdisplay; //height; *imodes++=24; *imodes++=_calchertz(m); } XFree(xmodes); return count; } static void _swapBuffers( BBGLContext *context ){ if( !context ) return; glXSwapBuffers(xdisplay,context->window); bbSystemPoll(); } BBGLContext *bbGLGraphicsAttachGraphics( void * window,BBInt64 flags ){ BBGLContext *context=(BBGLContext*)malloc( sizeof(BBGLContext) ); memset( context,0,sizeof(BBGLContext) ); context->mode=MODE_WIDGET; context->flags=flags; context->sync=-1; context->window=(Window)window; return context; } XVisualInfo *_chooseVisual(BBInt64 flags){ int glspec[32],*s; s=glspec; *s++=GLX_RGBA; if (flags&FLAGS_BACKBUFFER) *s++=GLX_DOUBLEBUFFER; if (flags&FLAGS_ALPHABUFFER) {*s++=GLX_ALPHA_SIZE;*s++=1;} if (flags&FLAGS_DEPTHBUFFER) {*s++=GLX_DEPTH_SIZE;*s++=1;} if (flags&FLAGS_STENCILBUFFER) {*s++=GLX_STENCIL_SIZE;*s++=1;} if (flags&FLAGS_ACCUMBUFFER) { *s++=GLX_ACCUM_RED_SIZE;*s++=1; *s++=GLX_ACCUM_GREEN_SIZE;*s++=1; *s++=GLX_ACCUM_BLUE_SIZE;*s++=1; *s++=GLX_ACCUM_ALPHA_SIZE;*s++=1; } *s++=None; return glXChooseVisual(xdisplay,xscreen,glspec); } void _makeCurrent( BBGLContext *context ){ glXMakeCurrent(xdisplay,context->window,context->glContext); _currentContext=context; } static void _validateSize( BBGLContext *context ){ Window root_return; int x,y; unsigned int w,h,border,d; if( !context || context->mode!=MODE_WIDGET ) return; if (_initDisplay()) return; XGetGeometry(xdisplay,context->window,&root_return,&x,&y,&w,&h,&border,&d); context->width=w; context->height=h; } static void _validateContext( BBGLContext *context ){ GLXContext sharedcontext=0; XVisualInfo *vizinfo; if( !context || context->glContext ) return; if (_initDisplay()) return; //_initSharedContext(); if( _sharedContext ) sharedcontext=_sharedContext->glContext; vizinfo=_chooseVisual(context->flags); context->glContext=glXCreateContext(xdisplay,vizinfo,sharedcontext,True); glXMakeCurrent(xdisplay,context->window,context->glContext); bbSetSystemWindow(context->window); } void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hertz,BBInt64 *flags ){ _validateSize( context ); *width=context->width; *height=context->height; *depth=context->depth; *hertz=context->hertz; *flags=context->flags; } static Bool WaitForNotify(Display *display,XEvent *event,XPointer arg){ return (event->type==MapNotify) && (event->xmap.window==(Window)arg); } void bbGLGraphicsShareContexts(){ if( _sharedContext ) return; _sharedContext=bbGLGraphicsCreateGraphics(0,0,0,0,0,0,0); } BBGLContext *bbGLGraphicsCreateGraphics( int width,int height,int depth,int hz,BBInt64 flags, int x, int y ){ XSetWindowAttributes swa; XVisualInfo *vizinfo; XEvent event; GLXContext context; int window; int count,i; int displaymode; int initingShared=0; GLXContext sharedcontext=0; char *appTitle; if (_initDisplay()) return 0; if( width==0 && height==0 ) { width=100; height=100; initingShared=1; } else { if( _sharedContext ) sharedcontext=_sharedContext->glContext; //_initSharedContext(); //sharedcontext=_sharedContext->glContext; } vizinfo=_chooseVisual(flags); int border = (flags & FLAGS_BORDERLESS) ? 0 : CWBorderPixel; if (depth) { XF86VidModeGetModeLine(xdisplay,xscreen,&_oldMode.dotclock,(XF86VidModeModeLine*)&_oldMode.hdisplay ); XF86VidModeGetAllModeLines(xdisplay,xscreen,&count,&modes); mode=0; for (i=0;ihdisplay && height==modes[i]->vdisplay && hz==_calchertz(modes[i])) { mode=modes[i]; break; } } if (mode==0) { for (i=0;ihdisplay && height==modes[i]->vdisplay) { mode=modes[i]; break; } } } if (mode==0) return; width=mode->hdisplay; height=mode->vdisplay; vizinfo=_chooseVisual(flags); swa.border_pixel=0; swa.event_mask=StructureNotifyMask; swa.colormap=XCreateColormap(xdisplay,RootWindow(xdisplay,0),vizinfo->visual,AllocNone); swa.override_redirect=True; XF86VidModeSwitchToMode(xdisplay,xscreen,mode); XF86VidModeSetViewPort(xdisplay,xscreen,0,0); window=XCreateWindow( xdisplay, RootWindow(xdisplay,xscreen), 0, 0, width,height, 0, vizinfo->depth, InputOutput, vizinfo->visual, border|CWEventMask|CWColormap|CWOverrideRedirect, &swa ); xfullscreen=1; displaymode=MODE_DISPLAY; } else { Atom atom; XSizeHints *hints; if (x < 0) x = 0 ; if (y < 0) y = 0 ; swa.border_pixel=0; swa.event_mask=StructureNotifyMask; swa.colormap=XCreateColormap( xdisplay,RootWindow(xdisplay,0),vizinfo->visual,AllocNone ); window=XCreateWindow( xdisplay, RootWindow(xdisplay,xscreen), x, y, width,height, 0, vizinfo->depth, InputOutput, vizinfo->visual, border|CWColormap|CWEventMask, &swa ); //Tell window to send us 'close window events' atom=XInternAtom( xdisplay,"WM_DELETE_WINDOW",True ); XSetWMProtocols( xdisplay,window,&atom,1 ); //Set window min/max size hints=XAllocSizeHints(); hints->flags=PMinSize|PMaxSize|PPosition; hints->x = x; hints->y = y; hints->min_width=hints->max_width=width; hints->min_height=hints->max_height=height; XSetWMNormalHints( xdisplay,window,hints ); displaymode=MODE_WINDOW; } context=glXCreateContext(xdisplay,vizinfo,sharedcontext,True); if( !initingShared ) { XMapRaised(xdisplay,window); if (xfullscreen) { XWarpPointer(xdisplay,None,window,0,0,0,0,0,0); XGrabKeyboard(xdisplay,window,True,GrabModeAsync,GrabModeAsync,CurrentTime); XGrabPointer(xdisplay,window,True,ButtonPressMask,GrabModeAsync,GrabModeAsync,window,None,CurrentTime); } glXMakeCurrent(xdisplay,window,context); XIfEvent(xdisplay,&event,WaitForNotify,(XPointer)window); XSelectInput(xdisplay,window,ResizeRedirectMask|FocusChangeMask|PointerMotionMask|ButtonPressMask|ButtonReleaseMask|KeyPressMask|KeyReleaseMask); xwindow=window; bbSetSystemWindow(xwindow); } appTitle=bbStringToUTF8String( bbAppTitle ); XChangeProperty( xdisplay,window, XInternAtom( xdisplay,"_NET_WM_NAME",True ), XInternAtom( xdisplay,"UTF8_STRING",True ), 8,PropModeReplace,appTitle,strlen( appTitle ) ); bbMemFree(appTitle); // XStoreName( xdisplay,window,appTitle ); bbSystemPoll(); BBGLContext *bbcontext=(BBGLContext*)malloc( sizeof(BBGLContext) ); memset( bbcontext,0,sizeof(BBGLContext) ); bbcontext->mode=displaymode; bbcontext->width=width; bbcontext->height=height; bbcontext->depth=24; bbcontext->hertz=hz; bbcontext->flags=flags; bbcontext->sync=-1; bbcontext->window=window; bbcontext->glContext=context; return bbcontext; } void bbGLGraphicsSetGraphics( BBGLContext *context ){ if( context ){ _validateSize( context ); _validateContext( context ); } if( !context || context==_currentContext ) return; _makeCurrent(context); _activeContext=context; } void bbGLGraphicsFlip( int sync ){ if( !_currentContext ) return; sync=sync ? 1 : 0; if( sync!=_currentContext->sync ){ _currentContext->sync=sync; if ( glXSwapIntervalEXT ) { glXSwapIntervalEXT( sync ); } } _swapBuffers( _currentContext ); } void bbGLGraphicsClose( BBGLContext *context ){ if (context){ if (_currentContext==context) _currentContext=0; if (context->glContext) { glXMakeCurrent(xdisplay,None,NULL); glXDestroyContext(xdisplay,context->glContext); } if (context->window && context->mode!=MODE_WIDGET){ XDestroyWindow(xdisplay,context->window); } if (context->mode==MODE_DISPLAY){ XF86VidModeSwitchToMode(xdisplay,xscreen,&_oldMode); XF86VidModeSetViewPort(xdisplay,xscreen,0,0); XFlush(xdisplay); XFree(modes); modes=0; mode=0; xfullscreen=0; } free( context ); } } void bbGLExit(){ bbGLGraphicsClose( _currentContext ); bbGLGraphicsClose( _sharedContext ); _currentContext=0; _sharedContext=0; }