Files
gio/app/internal/wm/gl_macos.go
T
Elias Naur 7d84e419c9 gpu,gpu/headless,app/internal/wm: add explicit RenderTarget API
Both the OpenGL and the Direct3D API are stateful and gpu.GPU renders to
the render target current when Frame is called.

Modern GPU API such as Metal don't have a concept of a current render
target, and the target even changes each frame.

Add RenderTarget and add an explicit target argument to GPU.Frame as
well as the underlying driver.Device.BeginFrame.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-08-08 13:45:23 +01:00

96 lines
2.1 KiB
Go

// SPDX-License-Identifier: Unlicense OR MIT
//go:build darwin && !ios
// +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>
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLContext(void);
__attribute__ ((visibility ("hidden"))) void gio_setContextView(CFTypeRef ctx, CFTypeRef view);
__attribute__ ((visibility ("hidden"))) void gio_makeCurrentContext(CFTypeRef ctx);
__attribute__ ((visibility ("hidden"))) void gio_updateContext(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
}
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.Run(func() {
C.gio_setContextView(ctx, view)
})
c := &context{
ctx: ctx,
view: view,
}
return c, nil
}
func (c *context) RenderTarget() gpu.RenderTarget {
return gpu.OpenGLRenderTarget{}
}
func (c *context) API() gpu.API {
return gpu.OpenGL{}
}
func (c *context) Release() {
if c.ctx != 0 {
C.gio_clearCurrentContext()
C.CFRelease(c.ctx)
c.ctx = 0
}
}
func (c *context) Present() error {
return nil
}
func (c *context) Lock() error {
C.gio_lockContext(c.ctx)
C.gio_makeCurrentContext(c.ctx)
return nil
}
func (c *context) Unlock() {
C.gio_clearCurrentContext()
C.gio_unlockContext(c.ctx)
}
func (c *context) Refresh() error {
c.Lock()
defer c.Unlock()
C.gio_updateContext(c.ctx)
return nil
}
func (w *window) NewContext() (Context, error) {
return newContext(w)
}