glgraphics.win32.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. #include <windows.h>
  2. #include <gl/gl.h>
  3. #include <brl.mod/system.mod/system.h>
  4. enum{
  5. _BACKBUFFER= 0x2,
  6. _ALPHABUFFER= 0x4,
  7. _DEPTHBUFFER= 0x8,
  8. _STENCILBUFFER= 0x10,
  9. _ACCUMBUFFER= 0x20,
  10. };
  11. enum{
  12. MODE_SHARED,
  13. MODE_WIDGET,
  14. MODE_WINDOW,
  15. MODE_DISPLAY
  16. };
  17. extern int _bbusew;
  18. static const char *CLASS_NAME="BlitzMax GLGraphics";
  19. static const wchar_t *CLASS_NAMEW=L"BlitzMax GLGraphics";
  20. typedef struct BBGLContext BBGLContext;
  21. struct BBGLContext{
  22. BBGLContext *succ;
  23. int mode,width,height,depth,hertz,flags;
  24. HDC hdc;
  25. HWND hwnd;
  26. HGLRC hglrc;
  27. };
  28. static BBGLContext *_contexts;
  29. static BBGLContext *_sharedContext;
  30. static BBGLContext *_currentContext;
  31. typedef BOOL (APIENTRY * WGLSWAPINTERVALEXT) (int);
  32. void bbGLGraphicsClose( BBGLContext *context );
  33. void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hertz,int *flags );
  34. void bbGLGraphicsSetGraphics( BBGLContext *context );
  35. static const char *appTitle(){
  36. return bbTmpCString( bbAppTitle );
  37. }
  38. static const wchar_t *appTitleW(){
  39. return bbTmpWString( bbAppTitle );
  40. }
  41. static void _initPfd( PIXELFORMATDESCRIPTOR *pfd,int flags ){
  42. memset( pfd,0,sizeof(*pfd) );
  43. pfd->nSize=sizeof(pfd);
  44. pfd->nVersion=1;
  45. pfd->cColorBits=1;
  46. pfd->iPixelType=PFD_TYPE_RGBA;
  47. pfd->iLayerType=PFD_MAIN_PLANE;
  48. pfd->dwFlags=PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL;
  49. pfd->dwFlags|=(flags & _BACKBUFFER) ? PFD_DOUBLEBUFFER : 0;
  50. pfd->cAlphaBits=(flags & _ALPHABUFFER) ? 1 : 0;
  51. pfd->cDepthBits=(flags & _DEPTHBUFFER) ? 1 : 0;
  52. pfd->cStencilBits=(flags & _STENCILBUFFER) ? 1 : 0;
  53. pfd->cAccumBits=(flags & _ACCUMBUFFER) ? 1 : 0;
  54. }
  55. static int _setSwapInterval( int n ){
  56. WGLSWAPINTERVALEXT wglSwapIntervalEXT=(WGLSWAPINTERVALEXT)wglGetProcAddress("wglSwapIntervalEXT");
  57. if( wglSwapIntervalEXT ) wglSwapIntervalEXT( n );
  58. }
  59. static _stdcall long _wndProc( HWND hwnd,UINT msg,WPARAM wp,LPARAM lp ){
  60. static HWND _fullScreen;
  61. BBGLContext *c;
  62. for( c=_contexts;c && c->hwnd!=hwnd;c=c->succ ){}
  63. if( !c ){
  64. return _bbusew ? DefWindowProcW( hwnd,msg,wp,lp ) : DefWindowProc( hwnd,msg,wp,lp );
  65. }
  66. bbSystemEmitOSEvent( hwnd,msg,wp,lp,&bbNullObject );
  67. switch( msg ){
  68. case WM_CLOSE:
  69. return 0;
  70. case WM_SYSCOMMAND:
  71. if (wp==SC_SCREENSAVE) return 1;
  72. if (wp==SC_MONITORPOWER) return 1;
  73. break;
  74. case WM_SYSKEYDOWN:
  75. if( wp!=VK_F4 ) return 0;
  76. break;
  77. case WM_SETFOCUS:
  78. if( c && c->mode==MODE_DISPLAY && hwnd!=_fullScreen ){
  79. DEVMODE dm;
  80. int swapInt=0;
  81. memset( &dm,0,sizeof(dm) );
  82. dm.dmSize=sizeof(dm);
  83. dm.dmPelsWidth=c->width;
  84. dm.dmPelsHeight=c->height;
  85. dm.dmBitsPerPel=c->depth;
  86. dm.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL;
  87. if( c->hertz ){
  88. dm.dmDisplayFrequency=c->hertz;
  89. dm.dmFields|=DM_DISPLAYFREQUENCY;
  90. swapInt=1;
  91. }
  92. if( ChangeDisplaySettings( &dm,CDS_FULLSCREEN )==DISP_CHANGE_SUCCESSFUL ){
  93. _fullScreen=hwnd;
  94. }else if( dm.dmFields & DM_DISPLAYFREQUENCY ){
  95. dm.dmDisplayFrequency=0;
  96. dm.dmFields&=~DM_DISPLAYFREQUENCY;
  97. if( ChangeDisplaySettings( &dm,CDS_FULLSCREEN )==DISP_CHANGE_SUCCESSFUL ){
  98. _fullScreen=hwnd;
  99. swapInt=0;
  100. }
  101. }
  102. if( !_fullScreen ) bbExThrowCString( "GLGraphicsDriver failed to set display mode" );
  103. _setSwapInterval( swapInt );
  104. }
  105. return 0;
  106. case WM_DESTROY:
  107. case WM_KILLFOCUS:
  108. if( hwnd==_fullScreen ){
  109. ChangeDisplaySettings( 0,CDS_FULLSCREEN );
  110. ShowWindow( hwnd,SW_MINIMIZE );
  111. _setSwapInterval( 0 );
  112. _fullScreen=0;
  113. }
  114. return 0;
  115. case WM_PAINT:
  116. ValidateRect( hwnd,0 );
  117. return 0;
  118. }
  119. return _bbusew ? DefWindowProcW( hwnd,msg,wp,lp ) : DefWindowProc( hwnd,msg,wp,lp );
  120. }
  121. static void _initWndClass(){
  122. static int _done;
  123. if( _done ) return;
  124. if( _bbusew ){
  125. WNDCLASSEXW wc={sizeof(wc)};
  126. wc.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
  127. wc.lpfnWndProc=(WNDPROC)_wndProc;
  128. wc.hInstance=GetModuleHandle(0);
  129. wc.lpszClassName=CLASS_NAMEW;
  130. wc.hCursor=(HCURSOR)LoadCursor( 0,IDC_ARROW );
  131. wc.hbrBackground=0;
  132. if( !RegisterClassExW( &wc ) ) exit( -1 );
  133. }else{
  134. WNDCLASSEX wc={sizeof(wc)};
  135. wc.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
  136. wc.lpfnWndProc=(WNDPROC)_wndProc;
  137. wc.hInstance=GetModuleHandle(0);
  138. wc.lpszClassName=CLASS_NAME;
  139. wc.hCursor=(HCURSOR)LoadCursor( 0,IDC_ARROW );
  140. wc.hbrBackground=0;
  141. if( !RegisterClassEx( &wc ) ) exit( -1 );
  142. }
  143. _done=1;
  144. }
  145. static void _validateSize( BBGLContext *context ){
  146. if( context->mode==MODE_WIDGET ){
  147. RECT rect;
  148. GetClientRect( context->hwnd,&rect );
  149. context->width=rect.right-rect.left;
  150. context->height=rect.bottom-rect.top;
  151. }
  152. }
  153. void bbGLGraphicsShareContexts(){
  154. BBGLContext *context;
  155. HDC hdc;
  156. HWND hwnd;
  157. HGLRC hglrc;
  158. long pf;
  159. PIXELFORMATDESCRIPTOR pfd;
  160. if( _sharedContext ) return;
  161. _initWndClass();
  162. if( _bbusew ){
  163. hwnd=CreateWindowExW( 0,CLASS_NAMEW,0,WS_POPUP,0,0,1,1,0,0,GetModuleHandle(0),0 );
  164. }else{
  165. hwnd=CreateWindowEx( 0,CLASS_NAME,0,WS_POPUP,0,0,1,1,0,0,GetModuleHandle(0),0 );
  166. }
  167. _initPfd( &pfd,0 );
  168. hdc=GetDC( hwnd );
  169. pf=ChoosePixelFormat( hdc,&pfd );
  170. if( !pf ){
  171. exit(0);
  172. DestroyWindow( hwnd );
  173. return;
  174. }
  175. SetPixelFormat( hdc,pf,&pfd );
  176. hglrc=wglCreateContext( hdc );
  177. if( !hglrc ) exit(0);
  178. _sharedContext=(BBGLContext*)malloc( sizeof(BBGLContext) );
  179. memset( _sharedContext,0,sizeof(BBGLContext) );
  180. _sharedContext->mode=MODE_SHARED;
  181. _sharedContext->width=1;
  182. _sharedContext->height=1;
  183. _sharedContext->hdc=hdc;
  184. _sharedContext->hwnd=hwnd;
  185. _sharedContext->hglrc=hglrc;
  186. }
  187. int bbGLGraphicsGraphicsModes( int *modes,int count ){
  188. int i=0,n=0;
  189. while( n<count ){
  190. DEVMODE mode;
  191. mode.dmSize=sizeof(DEVMODE);
  192. mode.dmDriverExtra=0;
  193. if( !EnumDisplaySettings(0,i++,&mode) ) break;
  194. if( mode.dmBitsPerPel<16 ) continue;
  195. *modes++=mode.dmPelsWidth;
  196. *modes++=mode.dmPelsHeight;
  197. *modes++=mode.dmBitsPerPel;
  198. *modes++=mode.dmDisplayFrequency;
  199. ++n;
  200. }
  201. return n;
  202. }
  203. BBGLContext *bbGLGraphicsAttachGraphics( HWND hwnd,int flags ){
  204. BBGLContext *context;
  205. HDC hdc;
  206. HGLRC hglrc;
  207. long pf;
  208. PIXELFORMATDESCRIPTOR pfd;
  209. RECT rect;
  210. _initWndClass();
  211. hdc=GetDC( hwnd );
  212. if( !hdc ) return 0;
  213. _initPfd( &pfd,flags );
  214. pf=ChoosePixelFormat( hdc,&pfd );
  215. if( !pf ) return 0;
  216. SetPixelFormat( hdc,pf,&pfd );
  217. hglrc=wglCreateContext( hdc );
  218. if( _sharedContext ) wglShareLists( _sharedContext->hglrc,hglrc );
  219. GetClientRect( hwnd,&rect );
  220. context=(BBGLContext*)malloc( sizeof(BBGLContext) );
  221. memset( context,0,sizeof(*context) );
  222. context->mode=MODE_WIDGET;
  223. context->width=rect.right;
  224. context->height=rect.bottom;
  225. context->flags=flags;
  226. context->hdc=hdc;
  227. context->hwnd=hwnd;
  228. context->hglrc=hglrc;
  229. context->succ=_contexts;
  230. _contexts=context;
  231. return context;
  232. }
  233. BBGLContext *bbGLGraphicsCreateGraphics( int width,int height,int depth,int hertz,int flags ){
  234. BBGLContext *context;
  235. int mode;
  236. HDC hdc;
  237. HWND hwnd;
  238. HGLRC hglrc;
  239. long pf;
  240. PIXELFORMATDESCRIPTOR pfd;
  241. int hwnd_style;
  242. RECT rect={0,0,width,height};
  243. _initWndClass();
  244. if( depth ){
  245. mode=MODE_DISPLAY;
  246. hwnd_style=WS_POPUP;
  247. }else{
  248. HWND desktop = GetDesktopWindow();
  249. RECT desktopRect;
  250. GetWindowRect(desktop, &desktopRect);
  251. rect.left=desktopRect.right/2-width/2;
  252. rect.top=desktopRect.bottom/2-height/2;
  253. rect.right=rect.left+width;
  254. rect.bottom=rect.top+height;
  255. mode=MODE_WINDOW;
  256. hwnd_style=WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX;
  257. }
  258. AdjustWindowRectEx( &rect,hwnd_style,0,0 );
  259. if( _bbusew ){
  260. hwnd=CreateWindowExW(
  261. 0,CLASS_NAMEW,appTitleW(),
  262. hwnd_style,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,0,0,GetModuleHandle(0),0 );
  263. }else{
  264. hwnd=CreateWindowEx(
  265. 0,CLASS_NAME,appTitle(),
  266. hwnd_style,rect.left,rect.top,rect.right-rect.left,rect.bottom-rect.top,0,0,GetModuleHandle(0),0 );
  267. }
  268. if( !hwnd ) return 0;
  269. GetClientRect( hwnd,&rect );
  270. width=rect.right-rect.left;
  271. height=rect.bottom-rect.top;
  272. _initPfd( &pfd,flags );
  273. hdc=GetDC( hwnd );
  274. pf=ChoosePixelFormat( hdc,&pfd );
  275. if( !pf ){
  276. DestroyWindow( hwnd );
  277. return 0;
  278. }
  279. SetPixelFormat( hdc,pf,&pfd );
  280. hglrc=wglCreateContext( hdc );
  281. if( _sharedContext ) wglShareLists( _sharedContext->hglrc,hglrc );
  282. context=(BBGLContext*)malloc( sizeof(BBGLContext) );
  283. memset( context,0,sizeof(context) );
  284. context->mode=mode;
  285. context->width=width;
  286. context->height=height;
  287. context->depth=depth;
  288. context->hertz=hertz;
  289. context->flags=flags;
  290. context->hdc=hdc;
  291. context->hwnd=hwnd;
  292. context->hglrc=hglrc;
  293. context->succ=_contexts;
  294. _contexts=context;
  295. ShowWindow( hwnd,SW_SHOW );
  296. return context;
  297. }
  298. void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hertz,int *flags ){
  299. _validateSize( context );
  300. *width=context->width;
  301. *height=context->height;
  302. *depth=context->depth;
  303. *hertz=context->hertz;
  304. *flags=context->flags;
  305. }
  306. void bbGLGraphicsClose( BBGLContext *context ){
  307. BBGLContext **p,*t;
  308. for( p=&_contexts;(t=*p) && (t!=context);p=&t->succ ){}
  309. if( !t ) return;
  310. if( t==_currentContext ){
  311. bbGLGraphicsSetGraphics( 0 );
  312. }
  313. wglDeleteContext( context->hglrc );
  314. if( t->mode==MODE_DISPLAY || t->mode==MODE_WINDOW ){
  315. DestroyWindow( t->hwnd );
  316. }
  317. *p=t->succ;
  318. }
  319. void bbGLGraphicsSetGraphics( BBGLContext *context ){
  320. if( context==_currentContext ) return;
  321. _currentContext=context;
  322. if( context ){
  323. wglMakeCurrent( context->hdc,context->hglrc );
  324. }else{
  325. wglMakeCurrent( 0,0 );
  326. }
  327. }
  328. void bbGLGraphicsFlip( int sync ){
  329. if( !_currentContext ) return;
  330. _setSwapInterval( sync ? 1 : 0 );
  331. /*
  332. static int _sync=-1;
  333. sync=sync ? 1 : 0;
  334. if( sync!=_sync ){
  335. _sync=sync;
  336. _setSwapInterval( _sync );
  337. }
  338. */
  339. SwapBuffers( _currentContext->hdc );
  340. }