glgraphics.macos.m 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #include <AppKit/AppKit.h>
  2. #include <Carbon/Carbon.h>
  3. #include <OpenGL/gl.h>
  4. #include <OpenGL/OpenGL.h>
  5. #include <brl.mod/system.mod/system.h>
  6. enum{
  7. FLAGS_BACKBUFFER= 0x2,
  8. FLAGS_ALPHABUFFER= 0x4,
  9. FLAGS_DEPTHBUFFER= 0x8,
  10. FLAGS_STENCILBUFFER=0x10,
  11. FLAGS_ACCUMBUFFER= 0x20,
  12. FLAGS_FULLSCREEN= 0x80000000
  13. };
  14. enum{
  15. MODE_WIDGET= 1,
  16. MODE_WINDOW= 2,
  17. MODE_DISPLAY= 3
  18. };
  19. @interface BBGLWindow : NSWindow{
  20. }
  21. @end
  22. @implementation BBGLWindow
  23. -(void)sendEvent:(NSEvent*)event{
  24. bbSystemEmitOSEvent( event,[self contentView],&bbNullObject );
  25. switch( [event type] ){
  26. case NSKeyDown:case NSKeyUp:
  27. //prevent 'beeps'!
  28. return;
  29. }
  30. [super sendEvent:event];
  31. }
  32. -(BOOL)windowShouldClose:(id)sender{
  33. bbSystemEmitEvent( BBEVENT_APPTERMINATE,&bbNullObject,0,0,0,0,&bbNullObject );
  34. return NO;
  35. }
  36. - (BOOL)canBecomeKeyWindow{
  37. return YES;
  38. }
  39. @end
  40. typedef struct BBGLContext BBGLContext;
  41. struct BBGLContext{
  42. int mode,width,height,depth,hertz,flags,sync;
  43. NSView *view;
  44. BBGLWindow *window;
  45. NSOpenGLContext *glContext;
  46. };
  47. static BBGLContext *_currentContext;
  48. static BBGLContext *_displayContext;
  49. static CFDictionaryRef oldDisplayMode;
  50. extern void bbFlushAutoreleasePool();
  51. void bbGLGraphicsClose( BBGLContext *context );
  52. void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hertz,int *flags );
  53. void bbGLGraphicsSetGraphics( BBGLContext *context );
  54. static int _initAttrs( CGLPixelFormatAttribute attrs[16],int flags ){
  55. int n=0;
  56. if( flags & FLAGS_BACKBUFFER ) attrs[n++]=kCGLPFADoubleBuffer;
  57. if( flags & FLAGS_ALPHABUFFER ){ attrs[n++]=kCGLPFAAlphaSize;attrs[n++]=1; }
  58. if( flags & FLAGS_DEPTHBUFFER ){ attrs[n++]=kCGLPFADepthSize;attrs[n++]=1; }
  59. if( flags & FLAGS_STENCILBUFFER ){ attrs[n++]=kCGLPFAStencilSize;attrs[n++]=1; }
  60. if( flags & FLAGS_ACCUMBUFFER ){ attrs[n++]=kCGLPFAAccumSize;attrs[n++]=1; }
  61. if( flags & FLAGS_FULLSCREEN ){
  62. attrs[n++]=kCGLPFAFullScreen;
  63. attrs[n++]=kCGLPFADisplayMask;
  64. attrs[n++]=CGDisplayIDToOpenGLDisplayMask( kCGDirectMainDisplay );
  65. }else{
  66. attrs[n++]=kCGLPFANoRecovery;
  67. }
  68. attrs[n]=0;
  69. return n;
  70. }
  71. static NSOpenGLContext *_sharedContext;
  72. static void _validateSize( BBGLContext *context ){
  73. NSRect rect;
  74. if( !context || context->mode!=MODE_WIDGET ) return;
  75. rect=[context->view bounds];
  76. if( rect.size.width==context->width && rect.size.height==context->height ) return;
  77. context->width=rect.size.width;
  78. context->height=rect.size.height;
  79. if( context->glContext ) [context->glContext update];
  80. }
  81. static void _validateContext( BBGLContext *context ){
  82. int flags;
  83. NSOpenGLContext *shared;
  84. NSOpenGLContext *glContext;
  85. NSOpenGLPixelFormat *glFormat;
  86. CGLPixelFormatAttribute attrs[16];
  87. if( !context || context->glContext ) return;
  88. flags=context->flags;
  89. // if( context->mode==MODE_DISPLAY ) flags|=FLAGS_FULLSCREEN;
  90. _initAttrs( attrs,flags );
  91. glFormat=[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
  92. glContext=[[NSOpenGLContext alloc] initWithFormat:glFormat shareContext:_sharedContext];
  93. [glFormat release];
  94. if( !glContext ) bbExThrowCString( "Unable to create GL Context" );
  95. switch( context->mode ){
  96. case MODE_WIDGET:
  97. [glContext setView:context->view];
  98. break;
  99. case MODE_WINDOW:
  100. case MODE_DISPLAY:
  101. [glContext setView:[context->window contentView]];
  102. break;
  103. }
  104. context->glContext=glContext;
  105. }
  106. void bbGLGraphicsShareContexts(){
  107. NSOpenGLPixelFormat *glFormat;
  108. CGLPixelFormatAttribute attrs[16];
  109. if( _sharedContext ) return;
  110. _initAttrs( attrs,0 );
  111. glFormat=[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
  112. _sharedContext=[[NSOpenGLContext alloc] initWithFormat:glFormat shareContext:0];
  113. [glFormat release];
  114. }
  115. int bbGLGraphicsGraphicsModes( int *modes,int count ){
  116. int i=0,n=0,sz;
  117. CFArrayRef displayModeArray;
  118. displayModeArray=CGDisplayAvailableModes( kCGDirectMainDisplay );
  119. sz=CFArrayGetCount( displayModeArray );
  120. while( i<sz && n<count ){
  121. CFNumberRef number;
  122. CFDictionaryRef displayMode;
  123. int width,height,depth,hertz;
  124. displayMode=(CFDictionaryRef)CFArrayGetValueAtIndex( displayModeArray,i++ );
  125. number=CFDictionaryGetValue( displayMode,kCGDisplayBitsPerPixel );
  126. CFNumberGetValue( number,kCFNumberLongType,&depth );
  127. if( depth<16 ) continue;
  128. number=CFDictionaryGetValue( displayMode,kCGDisplayWidth );
  129. CFNumberGetValue( number,kCFNumberLongType,&width );
  130. number=CFDictionaryGetValue( displayMode,kCGDisplayHeight );
  131. CFNumberGetValue( number,kCFNumberLongType,&height );
  132. number=CFDictionaryGetValue( displayMode,kCGDisplayRefreshRate );
  133. CFNumberGetValue( number,kCFNumberLongType,&hertz );
  134. *modes++=width;
  135. *modes++=height;
  136. *modes++=depth;
  137. *modes++=hertz;
  138. ++n;
  139. }
  140. return n;
  141. }
  142. BBGLContext *bbGLGraphicsAttachGraphics( NSView *view,int flags ){
  143. NSRect rect;
  144. BBGLContext *context;
  145. rect=[view bounds];
  146. context=(BBGLContext*)malloc( sizeof(BBGLContext) );
  147. memset( context,0,sizeof(BBGLContext) );
  148. context->mode=MODE_WIDGET;
  149. context->width=rect.size.width;
  150. context->height=rect.size.height;
  151. context->flags=flags;
  152. context->sync=-1;
  153. context->view=view;
  154. return context;
  155. }
  156. BBGLContext *bbGLGraphicsCreateGraphics( int width,int height,int depth,int hertz,int flags ){
  157. int mode;
  158. BBGLWindow *window=0;
  159. BBGLContext *context;
  160. int sysv=0;
  161. Gestalt( 'sysv',&sysv );
  162. if( depth ){
  163. CFDictionaryRef displayMode;
  164. CGCaptureAllDisplays();
  165. oldDisplayMode=CGDisplayCurrentMode( kCGDirectMainDisplay );
  166. CFRetain( (CFTypeRef)oldDisplayMode );
  167. if( !hertz ){
  168. displayMode=CGDisplayBestModeForParameters( kCGDirectMainDisplay,depth,width,height,0 );
  169. }else{
  170. displayMode=CGDisplayBestModeForParametersAndRefreshRate( kCGDirectMainDisplay,depth,width,height,hertz,0 );
  171. }
  172. if( CGDisplaySwitchToMode( kCGDirectMainDisplay,displayMode ) ){
  173. CFRelease( (CFTypeRef)oldDisplayMode );
  174. bbExThrowCString( "Unable to set display mode" );
  175. }
  176. HideMenuBar();
  177. window=[[NSWindow alloc]
  178. initWithContentRect:NSMakeRect( 0,0,width,height )
  179. styleMask:NSBorderlessWindowMask
  180. backing:NSBackingStoreBuffered
  181. defer:YES];
  182. [window setOpaque:YES];
  183. [window setBackgroundColor:[NSColor blackColor]];
  184. [window setLevel:CGShieldingWindowLevel()];
  185. [window makeKeyAndOrderFront:NSApp];
  186. mode=MODE_DISPLAY;
  187. }else{
  188. window=[[BBGLWindow alloc]
  189. initWithContentRect:NSMakeRect( 0,0,width,height )
  190. styleMask:NSTitledWindowMask|NSClosableWindowMask
  191. backing:NSBackingStoreBuffered
  192. defer:YES];
  193. if( !window ) return 0;
  194. [window setDelegate:window];
  195. [window setAcceptsMouseMovedEvents:YES];
  196. [window setTitle:[NSString stringWithUTF8String:bbTmpUTF8String(bbAppTitle)]];
  197. [window center];
  198. [window makeKeyAndOrderFront:NSApp];
  199. mode=MODE_WINDOW;
  200. }
  201. context=(BBGLContext*)malloc( sizeof(BBGLContext) );
  202. memset( context,0,sizeof(BBGLContext) );
  203. context->mode=mode;
  204. context->width=width;
  205. context->height=height;
  206. context->depth=depth;
  207. context->hertz=hertz;
  208. context->flags=flags;
  209. context->sync=-1;
  210. context->window=window;
  211. if( mode==MODE_DISPLAY ) _displayContext=context;
  212. return context;
  213. }
  214. void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hertz, int *flags ){
  215. _validateSize( context );
  216. *width=context->width;
  217. *height=context->height;
  218. *depth=context->depth;
  219. *hertz=context->hertz;
  220. *flags=context->flags;
  221. }
  222. void bbGLGraphicsClose( BBGLContext *context ){
  223. if( context==_currentContext ) bbGLGraphicsSetGraphics( 0 );
  224. [context->glContext clearDrawable];
  225. [context->glContext release];
  226. switch( context->mode ){
  227. case MODE_WINDOW:
  228. case MODE_DISPLAY:
  229. bbSystemViewClosed( [context->window contentView] );
  230. [context->window close];
  231. break;
  232. }
  233. if( context==_displayContext ){
  234. CGDisplaySwitchToMode( kCGDirectMainDisplay,oldDisplayMode );
  235. CFRelease( (CFTypeRef)oldDisplayMode );
  236. CGReleaseAllDisplays();
  237. CGDisplayShowCursor( kCGDirectMainDisplay );
  238. ShowMenuBar();
  239. _displayContext=0;
  240. }
  241. free( context );
  242. }
  243. void bbGLGraphicsSetGraphics( BBGLContext *context ){
  244. if( context ){
  245. _validateSize( context );
  246. _validateContext( context );
  247. [context->glContext makeCurrentContext];
  248. }else{
  249. [NSOpenGLContext clearCurrentContext];
  250. }
  251. _currentContext=context;
  252. }
  253. void bbGLGraphicsFlip( int sync ){
  254. if( !_currentContext ) return;
  255. sync=sync ? 1 : 0;
  256. static int _sync=-1;
  257. if( sync!=_currentContext->sync ){
  258. _currentContext->sync=sync;
  259. [_currentContext->glContext setValues:(long*)&sync forParameter:kCGLCPSwapInterval];
  260. }
  261. [_currentContext->glContext flushBuffer];
  262. }