gl_macos.go raw
1 // SPDX-License-Identifier: Unlicense OR MIT
2
3 // +build darwin,!ios
4
5 package wm
6
7 import (
8 "github.com/p9c/p9/pkg/gel/gio/gpu"
9 "github.com/p9c/p9/pkg/gel/gio/internal/gl"
10 )
11
12 /*
13 #include <CoreFoundation/CoreFoundation.h>
14 #include <CoreGraphics/CoreGraphics.h>
15 #include <AppKit/AppKit.h>
16 #include <OpenGL/gl3.h>
17
18 __attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLView(void);
19 __attribute__ ((visibility ("hidden"))) CFTypeRef gio_contextForView(CFTypeRef viewRef);
20 __attribute__ ((visibility ("hidden"))) void gio_makeCurrentContext(CFTypeRef ctx);
21 __attribute__ ((visibility ("hidden"))) void gio_flushContextBuffer(CFTypeRef ctx);
22 __attribute__ ((visibility ("hidden"))) void gio_clearCurrentContext(void);
23 __attribute__ ((visibility ("hidden"))) void gio_lockContext(CFTypeRef ctxRef);
24 __attribute__ ((visibility ("hidden"))) void gio_unlockContext(CFTypeRef ctxRef);
25 */
26 import "C"
27
28 type context struct {
29 c *gl.Functions
30 ctx C.CFTypeRef
31 view C.CFTypeRef
32 }
33
34 func init() {
35 viewFactory = func() C.CFTypeRef {
36 return C.gio_createGLView()
37 }
38 }
39
40 func newContext(w *window) (*context, error) {
41 view := w.contextView()
42 ctx := C.gio_contextForView(view)
43 c := &context{
44 ctx: ctx,
45 view: view,
46 }
47 return c, nil
48 }
49
50 func (c *context) API() gpu.API {
51 return gpu.OpenGL{}
52 }
53
54 func (c *context) Release() {
55 c.Lock()
56 defer c.Unlock()
57 C.gio_clearCurrentContext()
58 // We could release the context with [view clearGLContext]
59 // and rely on [view openGLContext] auto-creating a new context.
60 // However that second context is not properly set up by
61 // OpenGLContextView, so we'll stay on the safe side and keep
62 // the first context around.
63 }
64
65 func (c *context) Present() error {
66 // Assume the caller already locked the context.
67 C.glFlush()
68 return nil
69 }
70
71 func (c *context) Lock() {
72 C.gio_lockContext(c.ctx)
73 }
74
75 func (c *context) Unlock() {
76 C.gio_unlockContext(c.ctx)
77 }
78
79 func (c *context) MakeCurrent() error {
80 c.Lock()
81 defer c.Unlock()
82 C.gio_makeCurrentContext(c.ctx)
83 return nil
84 }
85
86 func (w *window) NewContext() (Context, error) {
87 return newContext(w)
88 }
89