_glgraphics.macos.m 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  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. };
  13. enum{
  14. MODE_WIDGET= 1,
  15. MODE_WINDOW= 2,
  16. MODE_DISPLAY= 3
  17. };
  18. @interface BBGLWindow : NSWindow{
  19. }
  20. @end
  21. @implementation BBGLWindow
  22. -(void)sendEvent:(NSEvent*)event{
  23. bbSystemEmitOSEvent( event,[self contentView],&bbNullObject );
  24. switch( [event type] ){
  25. case NSKeyDown:case NSKeyUp:
  26. //prevent 'beeps'!
  27. return;
  28. }
  29. [super sendEvent:event];
  30. }
  31. -(BOOL)windowShouldClose:(id)sender{
  32. bbSystemEmitEvent( BBEVENT_APPTERMINATE,&bbNullObject,0,0,0,0,&bbNullObject );
  33. return NO;
  34. }
  35. - (BOOL)canBecomeKeyWindow{
  36. return YES;
  37. }
  38. @end
  39. typedef struct BBGLContext BBGLContext;
  40. struct BBGLContext{
  41. int mode,width,height,depth,hertz,flags,sync;
  42. BBGLWindow *window;
  43. NSView *view;
  44. NSOpenGLContext *glContext;
  45. };
  46. static BBGLContext *_currentContext;
  47. static CFDictionaryRef oldDisplayMode;
  48. extern void bbFlushAutoreleasePool();
  49. void bbGLGraphicsClose( BBGLContext *context );
  50. void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hertz,int *flags );
  51. void bbGLGraphicsSetGraphics( BBGLContext *context );
  52. static int _initAttrs( CGLPixelFormatAttribute attrs[16],int flags ){
  53. int n=0;
  54. if( flags & FLAGS_BACKBUFFER ) attrs[n++]=kCGLPFADoubleBuffer;
  55. if( flags & FLAGS_ALPHABUFFER ){ attrs[n++]=kCGLPFAAlphaSize;attrs[n++]=1; }
  56. if( flags & FLAGS_DEPTHBUFFER ){ attrs[n++]=kCGLPFADepthSize;attrs[n++]=1; }
  57. if( flags & FLAGS_STENCILBUFFER ){ attrs[n++]=kCGLPFAStencilSize;attrs[n++]=1; }
  58. if( flags & FLAGS_ACCUMBUFFER ){ attrs[n++]=kCGLPFAAccumSize;attrs[n++]=1; }
  59. attrs[n++]=kCGLPFANoRecovery;
  60. attrs[n]=0;
  61. return n;
  62. }
  63. static NSOpenGLContext *_sharedContext;
  64. static void _validateSize( BBGLContext *context ){
  65. NSRect rect;
  66. if( !context || context->mode!=MODE_WIDGET ) return;
  67. rect=[context->view bounds];
  68. if( rect.size.width==context->width && rect.size.height==context->height ) return;
  69. context->width=rect.size.width;
  70. context->height=rect.size.height;
  71. if( context->glContext ) [context->glContext update];
  72. }
  73. static void _validateContext( BBGLContext *context ){
  74. int flags;
  75. NSOpenGLContext *shared;
  76. NSOpenGLContext *glContext;
  77. NSOpenGLPixelFormat *glFormat;
  78. CGLPixelFormatAttribute attrs[16];
  79. if( !context || context->glContext ) return;
  80. flags=context->flags;
  81. _initAttrs( attrs,flags );
  82. glFormat=[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
  83. glContext=[[NSOpenGLContext alloc] initWithFormat:glFormat shareContext:_sharedContext];
  84. [glFormat release];
  85. if( !glContext ) bbExThrowCString( "Unable to create GL Context" );
  86. context->glContext=glContext;
  87. [glContext setView:context->view];
  88. switch( context->mode ){
  89. case MODE_DISPLAY:
  90. CGLSetParameter( [glContext CGLContextObj],kCGLCPSurfaceBackingSize,&context->width );
  91. CGLEnable( [glContext CGLContextObj],kCGLCESurfaceBackingSize );
  92. break;
  93. }
  94. }
  95. void bbGLGraphicsShareContexts(){
  96. NSOpenGLPixelFormat *glFormat;
  97. CGLPixelFormatAttribute attrs[16];
  98. if( _sharedContext ) return;
  99. _initAttrs( attrs,0 );
  100. glFormat=[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
  101. _sharedContext=[[NSOpenGLContext alloc] initWithFormat:glFormat shareContext:0];
  102. [glFormat release];
  103. }
  104. int bbGLGraphicsGraphicsModes( int *modes,int count ){
  105. int i=0,n=0,sz;
  106. CFArrayRef displayModeArray;
  107. displayModeArray=CGDisplayAvailableModes( kCGDirectMainDisplay );
  108. sz=CFArrayGetCount( displayModeArray );
  109. while( i<sz && n<count ){
  110. CFNumberRef number;
  111. CFDictionaryRef displayMode;
  112. int width,height,depth,hertz;
  113. displayMode=(CFDictionaryRef)CFArrayGetValueAtIndex( displayModeArray,i++ );
  114. number=CFDictionaryGetValue( displayMode,kCGDisplayBitsPerPixel );
  115. CFNumberGetValue( number,kCFNumberLongType,&depth );
  116. if( depth<16 ) continue;
  117. number=CFDictionaryGetValue( displayMode,kCGDisplayWidth );
  118. CFNumberGetValue( number,kCFNumberLongType,&width );
  119. number=CFDictionaryGetValue( displayMode,kCGDisplayHeight );
  120. CFNumberGetValue( number,kCFNumberLongType,&height );
  121. number=CFDictionaryGetValue( displayMode,kCGDisplayRefreshRate );
  122. CFNumberGetValue( number,kCFNumberLongType,&hertz );
  123. *modes++=width;
  124. *modes++=height;
  125. *modes++=depth;
  126. *modes++=hertz;
  127. ++n;
  128. }
  129. return n;
  130. }
  131. BBGLContext *bbGLGraphicsAttachGraphics( NSView *view,int flags ){
  132. NSRect rect;
  133. BBGLContext *context;
  134. rect=[view bounds];
  135. context=(BBGLContext*)malloc( sizeof(BBGLContext) );
  136. memset( context,0,sizeof(BBGLContext) );
  137. context->mode=MODE_WIDGET;
  138. context->width=rect.size.width;
  139. context->height=rect.size.height;
  140. context->flags=flags;
  141. context->sync=-1;
  142. context->view=view;
  143. return context;
  144. }
  145. BBGLContext *bbGLGraphicsCreateGraphics( int width,int height,int depth,int hertz,int flags ){
  146. int mode;
  147. BBGLWindow *window=0;
  148. NSView *view=0;
  149. BBGLContext *context;
  150. int sysv=0;
  151. Gestalt( 'sysv',&sysv );
  152. //fullscreen mode only available in Tiger++
  153. //
  154. if( depth && sysv>=0x1070 ){
  155. view=[[NSView alloc] initWithFrame:[[NSScreen mainScreen] frame]];
  156. [view enterFullScreenMode:[NSScreen mainScreen] withOptions:nil];
  157. mode=MODE_DISPLAY;
  158. }else{
  159. window=[[BBGLWindow alloc]
  160. initWithContentRect:NSMakeRect( 0,0,width,height )
  161. styleMask:NSTitledWindowMask|NSClosableWindowMask
  162. backing:NSBackingStoreBuffered
  163. defer:YES];
  164. if( !window ) return 0;
  165. view=[window contentView];
  166. [window setDelegate:window];
  167. [window setAcceptsMouseMovedEvents:YES];
  168. [window setTitle:[NSString stringWithUTF8String:bbTmpUTF8String(bbAppTitle)]];
  169. [window center];
  170. [window makeKeyAndOrderFront:NSApp];
  171. mode=MODE_WINDOW;
  172. }
  173. context=(BBGLContext*)malloc( sizeof(BBGLContext) );
  174. memset( context,0,sizeof(BBGLContext) );
  175. context->mode=mode;
  176. context->width=width;
  177. context->height=height;
  178. context->depth=depth;
  179. context->hertz=hertz;
  180. context->flags=flags;
  181. context->sync=-1;
  182. context->window=window;
  183. context->view=view;
  184. return context;
  185. }
  186. void bbGLGraphicsGetSettings( BBGLContext *context,int *width,int *height,int *depth,int *hertz, int *flags ){
  187. _validateSize( context );
  188. *width=context->width;
  189. *height=context->height;
  190. *depth=context->depth;
  191. *hertz=context->hertz;
  192. *flags=context->flags;
  193. }
  194. void bbGLGraphicsClose( BBGLContext *context ){
  195. if( context==_currentContext ) bbGLGraphicsSetGraphics( 0 );
  196. [context->glContext clearDrawable];
  197. [context->glContext release];
  198. switch( context->mode ){
  199. case MODE_WINDOW:
  200. bbSystemViewClosed( [context->window contentView] );
  201. [context->window close];
  202. break;
  203. case MODE_DISPLAY:
  204. bbSystemViewClosed( context->view );
  205. [context->view exitFullScreenModeWithOptions:nil];
  206. [context->view release];
  207. break;
  208. }
  209. free( context );
  210. }
  211. void bbGLGraphicsSetGraphics( BBGLContext *context ){
  212. if( context ){
  213. _validateSize( context );
  214. _validateContext( context );
  215. [context->glContext makeCurrentContext];
  216. }else{
  217. [NSOpenGLContext clearCurrentContext];
  218. }
  219. _currentContext=context;
  220. }
  221. void bbGLGraphicsFlip( int sync ){
  222. if( !_currentContext ) return;
  223. sync=sync ? 1 : 0;
  224. static int _sync=-1;
  225. if( sync!=_currentContext->sync ){
  226. _currentContext->sync=sync;
  227. [_currentContext->glContext setValues:(long*)&sync forParameter:kCGLCPSwapInterval];
  228. }
  229. [_currentContext->glContext flushBuffer];
  230. }