github.com/cybriq/giocore@v0.0.7-0.20210703034601-cfb9cb5f3900/app/internal/wm/gl_macos.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 // +build darwin,!ios 4 5 package wm 6 7 import ( 8 "errors" 9 10 "github.com/cybriq/giocore/gpu" 11 "github.com/cybriq/giocore/internal/gl" 12 ) 13 14 /* 15 #include <CoreFoundation/CoreFoundation.h> 16 #include <CoreGraphics/CoreGraphics.h> 17 #include <AppKit/AppKit.h> 18 19 __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLContext(void); 20 __attribute__ ((visibility ("hidden"))) void gio_setContextView(CFTypeRef ctx, CFTypeRef view); 21 __attribute__ ((visibility ("hidden"))) void gio_makeCurrentContext(CFTypeRef ctx); 22 __attribute__ ((visibility ("hidden"))) void gio_updateContext(CFTypeRef ctx); 23 __attribute__ ((visibility ("hidden"))) void gio_flushContextBuffer(CFTypeRef ctx); 24 __attribute__ ((visibility ("hidden"))) void gio_clearCurrentContext(void); 25 __attribute__ ((visibility ("hidden"))) void gio_lockContext(CFTypeRef ctxRef); 26 __attribute__ ((visibility ("hidden"))) void gio_unlockContext(CFTypeRef ctxRef); 27 */ 28 import "C" 29 30 type context struct { 31 c *gl.Functions 32 ctx C.CFTypeRef 33 view C.CFTypeRef 34 } 35 36 func newContext(w *window) (*context, error) { 37 view := w.contextView() 38 ctx := C.gio_createGLContext() 39 if ctx == 0 { 40 return nil, errors.New("gl: failed to create NSOpenGLContext") 41 } 42 // [NSOpenGLContext setView] must run on the main thread. Fortunately, 43 // newContext is only called during a [NSView draw] on the main thread. 44 w.w.Run(func() { 45 C.gio_setContextView(ctx, view) 46 }) 47 c := &context{ 48 ctx: ctx, 49 view: view, 50 } 51 return c, nil 52 } 53 54 func (c *context) API() gpu.API { 55 return gpu.OpenGL{} 56 } 57 58 func (c *context) Release() { 59 if c.ctx != 0 { 60 C.gio_clearCurrentContext() 61 C.CFRelease(c.ctx) 62 c.ctx = 0 63 } 64 } 65 66 func (c *context) Present() error { 67 return nil 68 } 69 70 func (c *context) Lock() { 71 C.gio_lockContext(c.ctx) 72 } 73 74 func (c *context) Unlock() { 75 C.gio_unlockContext(c.ctx) 76 } 77 78 func (c *context) Refresh() error { 79 c.Lock() 80 defer c.Unlock() 81 C.gio_updateContext(c.ctx) 82 return nil 83 } 84 85 func (c *context) MakeCurrent() error { 86 c.Lock() 87 defer c.Unlock() 88 C.gio_makeCurrentContext(c.ctx) 89 return nil 90 } 91 92 func (w *window) NewContext() (Context, error) { 93 return newContext(w) 94 }