Files
gio/app/internal/wm/gl_macos.go
T
Elias Naur 1d4bf04aa1 app/internal/wm: [macOS] use NSView+NSOpenGLContext, not NSOpenGLContextView
NSOpenGLContextView couples the window manager logic tightly with
OpenGL. Use generic NSViews, and attach NSOpenGLContext just like the
other platforms.

This change prepares for supporting GPU contexts created by clients as
well as a future Metal port.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-14 20:23:06 +02:00

94 lines
2.1 KiB
Go

// SPDX-License-Identifier: Unlicense OR MIT
// +build darwin,!ios
package wm
import (
"errors"
"gioui.org/gpu"
"gioui.org/internal/gl"
)
/*
#include <CoreFoundation/CoreFoundation.h>
#include <CoreGraphics/CoreGraphics.h>
#include <AppKit/AppKit.h>
#include <OpenGL/gl3.h>
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLContext(void);
__attribute__ ((visibility ("hidden"))) void gio_prepareContext(void);
__attribute__ ((visibility ("hidden"))) void gio_setContextView(CFTypeRef ctx, CFTypeRef view);
__attribute__ ((visibility ("hidden"))) void gio_makeCurrentContext(CFTypeRef ctx);
__attribute__ ((visibility ("hidden"))) void gio_flushContextBuffer(CFTypeRef ctx);
__attribute__ ((visibility ("hidden"))) void gio_clearCurrentContext(void);
__attribute__ ((visibility ("hidden"))) void gio_lockContext(CFTypeRef ctxRef);
__attribute__ ((visibility ("hidden"))) void gio_unlockContext(CFTypeRef ctxRef);
*/
import "C"
type context struct {
c *gl.Functions
ctx C.CFTypeRef
view C.CFTypeRef
prepared bool
}
func newContext(w *window) (*context, error) {
view := w.contextView()
ctx := C.gio_createGLContext()
if ctx == 0 {
return nil, errors.New("gl: failed to create NSOpenGLContext")
}
// [NSOpenGLContext setView] must run on the main thread. Fortunately,
// newContext is only called during a [NSView draw] on the main thread.
w.w.Func(func() {
C.gio_setContextView(ctx, view)
})
c := &context{
ctx: ctx,
view: view,
}
return c, nil
}
func (c *context) API() gpu.API {
return gpu.OpenGL{}
}
func (c *context) Release() {
C.gio_clearCurrentContext()
C.CFRelease(c.ctx)
c.ctx = 0
}
func (c *context) Present() error {
// Assume the caller already locked the context.
C.glFlush()
return nil
}
func (c *context) Lock() {
C.gio_lockContext(c.ctx)
}
func (c *context) Unlock() {
C.gio_unlockContext(c.ctx)
}
func (c *context) MakeCurrent() error {
c.Lock()
defer c.Unlock()
C.gio_makeCurrentContext(c.ctx)
if !c.prepared {
c.prepared = true
C.gio_prepareContext()
}
return nil
}
func (w *window) NewContext() (Context, error) {
return newContext(w)
}