github.com/gop9/olt@v0.0.0-20200202132135-d956aad50b08/gio/app/internal/window/gl_macos.m (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  // +build darwin,!ios
     4  
     5  @import AppKit;
     6  
     7  #include <CoreFoundation/CoreFoundation.h>
     8  #include <OpenGL/OpenGL.h>
     9  #include <OpenGL/gl3.h>
    10  #include "os_macos.h"
    11  #include "gl_macos.h"
    12  #include "_cgo_export.h"
    13  
    14  static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFloat dy) {
    15  	NSPoint p = [view convertPoint:[event locationInWindow] fromView:nil];
    16  	if (!event.hasPreciseScrollingDeltas) {
    17  		// dx and dy are in rows and columns.
    18  		dx *= 10;
    19  		dy *= 10;
    20  	}
    21  	gio_onMouse((__bridge CFTypeRef)view, typ, [NSEvent pressedMouseButtons], p.x, p.y, dx, dy, [event timestamp], [event modifierFlags]);
    22  }
    23  
    24  static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) {
    25  	CFTypeRef view = (CFTypeRef *)displayLinkContext;
    26  	gio_onFrameCallback(view);
    27  	return kCVReturnSuccess;
    28  }
    29  
    30  @interface GioView : NSOpenGLView 
    31  @end
    32  
    33  @implementation GioView {
    34  CVDisplayLinkRef displayLink;
    35  }
    36  - (instancetype)initWithFrame:(NSRect)frameRect
    37  				  pixelFormat:(NSOpenGLPixelFormat *)format {
    38  	self = [super initWithFrame:frameRect pixelFormat:format];
    39  	if (self) {
    40  		CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
    41  		CVDisplayLinkSetOutputCallback(displayLink, displayLinkCallback, (__bridge void*)self);
    42  	}
    43  	return self;
    44  }
    45  - (void)dealloc {
    46  	CVDisplayLinkRelease(displayLink);
    47  }
    48  - (void)setAnimating:(BOOL)anim {
    49  	if (anim) {
    50  		CVDisplayLinkStart(displayLink);
    51  	} else {
    52  		CVDisplayLinkStop(displayLink);
    53  	}
    54  }
    55  - (void)updateDisplay:(CGDirectDisplayID)dispID {
    56  	CVDisplayLinkSetCurrentCGDisplay(displayLink, dispID);
    57  }
    58  - (void)prepareOpenGL {
    59  	[super prepareOpenGL];
    60  	// Bind a default VBA to emulate OpenGL ES 2.
    61  	GLuint defVBA;
    62  	glGenVertexArrays(1, &defVBA);
    63  	glBindVertexArray(defVBA);
    64  	glEnable(GL_FRAMEBUFFER_SRGB);
    65  }
    66  - (BOOL)isFlipped {
    67  	return YES;
    68  }
    69  - (void)update {
    70  	[super update];
    71  	[self setNeedsDisplay:YES];
    72  }
    73  - (void)drawRect:(NSRect)r {
    74  	gio_onDraw((__bridge CFTypeRef)self);
    75  }
    76  - (void)mouseDown:(NSEvent *)event {
    77  	handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
    78  }
    79  - (void)mouseUp:(NSEvent *)event {
    80  	handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
    81  }
    82  - (void)middleMouseDown:(NSEvent *)event {
    83  	handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
    84  }
    85  - (void)middletMouseUp:(NSEvent *)event {
    86  	handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
    87  }
    88  - (void)rightMouseDown:(NSEvent *)event {
    89  	handleMouse(self, event, GIO_MOUSE_DOWN, 0, 0);
    90  }
    91  - (void)rightMouseUp:(NSEvent *)event {
    92  	handleMouse(self, event, GIO_MOUSE_UP, 0, 0);
    93  }
    94  - (void)mouseMoved:(NSEvent *)event {
    95  	handleMouse(self, event, GIO_MOUSE_MOVE, 0, 0);
    96  }
    97  - (void)mouseDragged:(NSEvent *)event {
    98  	handleMouse(self, event, GIO_MOUSE_MOVE, 0, 0);
    99  }
   100  - (void)scrollWheel:(NSEvent *)event {
   101  	CGFloat dx = -event.scrollingDeltaX;
   102  	CGFloat dy = -event.scrollingDeltaY;
   103  	handleMouse(self, event, GIO_MOUSE_MOVE, dx, dy);
   104  }
   105  - (void)keyDown:(NSEvent *)event {
   106  	NSString *keys = [event charactersIgnoringModifiers];
   107  	gio_onKeys((__bridge CFTypeRef)self, (char *)[keys UTF8String], [event timestamp], [event modifierFlags]);
   108  	[self interpretKeyEvents:[NSArray arrayWithObject:event]];
   109  }
   110  - (void)insertText:(id)string {
   111  	const char *utf8 = [string UTF8String];
   112  	gio_onText((__bridge CFTypeRef)self, (char *)utf8);
   113  }
   114  - (void)doCommandBySelector:(SEL)sel {
   115  	// Don't pass commands up the responder chain.
   116  	// They will end up in a beep.
   117  }
   118  @end
   119  
   120  CFTypeRef gio_createGLView(void) {
   121  	@autoreleasepool {
   122  		NSOpenGLPixelFormatAttribute attr[] = {
   123  			NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
   124  			NSOpenGLPFAColorSize,     24,
   125  			NSOpenGLPFADepthSize,     16,
   126  			NSOpenGLPFAAccelerated,
   127  			// Opt-in to automatic GPU switching. CGL-only property.
   128  			kCGLPFASupportsAutomaticGraphicsSwitching,
   129  			NSOpenGLPFAAllowOfflineRenderers,
   130  			0
   131  		};
   132  		id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
   133  
   134  		NSRect frame = NSMakeRect(0, 0, 0, 0);
   135  		GioView* view = [[GioView alloc] initWithFrame:frame pixelFormat:pixFormat];
   136  
   137  		[view setWantsBestResolutionOpenGLSurface:YES];
   138  		[view setWantsLayer:YES]; // The default in Mojave.
   139  
   140  		return CFBridgingRetain(view);
   141  	}
   142  }
   143  
   144  void gio_updateDisplayLink(CFTypeRef viewRef, CGDirectDisplayID dispID) {
   145  	GioView *view = (__bridge GioView *)viewRef;
   146  	[view updateDisplay:dispID];
   147  }
   148  
   149  void gio_setAnimating(CFTypeRef viewRef, BOOL anim) {
   150  	GioView *view = (__bridge GioView *)viewRef;
   151  	dispatch_async(dispatch_get_main_queue(), ^{
   152  		[view setAnimating:anim];
   153  	});
   154  }
   155  
   156  CFTypeRef gio_contextForView(CFTypeRef viewRef) {
   157  	NSOpenGLView *view = (__bridge NSOpenGLView *)viewRef;
   158  	return (__bridge CFTypeRef)view.openGLContext;
   159  }
   160  
   161  void gio_clearCurrentContext(void) {
   162  	[NSOpenGLContext clearCurrentContext];
   163  }
   164  
   165  void gio_makeCurrentContext(CFTypeRef ctxRef) {
   166  	NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
   167  	[ctx makeCurrentContext];
   168  }
   169  
   170  void gio_lockContext(CFTypeRef ctxRef) {
   171  	NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
   172  	CGLLockContext([ctx CGLContextObj]);
   173  }
   174  
   175  void gio_unlockContext(CFTypeRef ctxRef) {
   176  	NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
   177  	CGLUnlockContext([ctx CGLContextObj]);
   178  }