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 }