forked from joejulian/gio
7d84e419c9
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>
96 lines
2.1 KiB
Go
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)
|
|
}
|