mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 10:25:37 +00:00
gpu,app/internal/wm: add Metal port
The OpenGL (ES) implementations on Apple platforms are deprecated and don't support GPU compute programs. This change adds support for the replacement, the Metal GPU API. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+14
-10
@@ -1,11 +1,13 @@
|
|||||||
// SPDX-License-Identifier: Unlicense OR MIT
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
//go:build darwin && ios
|
//go:build darwin && ios && nometal
|
||||||
// +build darwin,ios
|
// +build darwin,ios,nometal
|
||||||
|
|
||||||
package wm
|
package wm
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@import UIKit;
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
#include <OpenGLES/ES2/gl.h>
|
#include <OpenGLES/ES2/gl.h>
|
||||||
#include <OpenGLES/ES2/glext.h>
|
#include <OpenGLES/ES2/glext.h>
|
||||||
@@ -15,6 +17,14 @@ __attribute__ ((visibility ("hidden"))) int gio_presentRenderbuffer(CFTypeRef ct
|
|||||||
__attribute__ ((visibility ("hidden"))) int gio_makeCurrent(CFTypeRef ctx);
|
__attribute__ ((visibility ("hidden"))) int gio_makeCurrent(CFTypeRef ctx);
|
||||||
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createContext(void);
|
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createContext(void);
|
||||||
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLLayer(void);
|
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createGLLayer(void);
|
||||||
|
|
||||||
|
static CFTypeRef getViewLayer(CFTypeRef viewRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
UIView *view = (__bridge UIView *)viewRef;
|
||||||
|
return CFBridgingRetain(view.layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
@@ -36,12 +46,6 @@ type context struct {
|
|||||||
colorBuffer gl.Renderbuffer
|
colorBuffer gl.Renderbuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
layerFactory = func() uintptr {
|
|
||||||
return uintptr(C.gio_createGLLayer())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newContext(w *window) (*context, error) {
|
func newContext(w *window) (*context, error) {
|
||||||
ctx := C.gio_createContext()
|
ctx := C.gio_createContext()
|
||||||
if ctx == 0 {
|
if ctx == 0 {
|
||||||
@@ -55,7 +59,7 @@ func newContext(w *window) (*context, error) {
|
|||||||
c := &context{
|
c := &context{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
owner: w,
|
owner: w,
|
||||||
layer: C.CFTypeRef(w.contextLayer()),
|
layer: C.getViewLayer(w.contextView()),
|
||||||
c: f,
|
c: f,
|
||||||
}
|
}
|
||||||
return c, nil
|
return c, nil
|
||||||
@@ -116,7 +120,7 @@ func (c *context) Refresh() error {
|
|||||||
c.frameBuffer = c.c.CreateFramebuffer()
|
c.frameBuffer = c.c.CreateFramebuffer()
|
||||||
c.colorBuffer = c.c.CreateRenderbuffer()
|
c.colorBuffer = c.c.CreateRenderbuffer()
|
||||||
}
|
}
|
||||||
if !c.owner.isVisible() {
|
if !c.owner.visible {
|
||||||
// Make sure any in-flight GL commands are complete.
|
// Make sure any in-flight GL commands are complete.
|
||||||
c.c.Finish()
|
c.c.Finish()
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
// SPDX-License-Identifier: Unlicense OR MIT
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
// +build darwin,ios
|
// +build darwin,ios,nometal
|
||||||
|
|
||||||
@import UIKit;
|
@import UIKit;
|
||||||
@import OpenGLES;
|
@import OpenGLES;
|
||||||
|
|
||||||
#include "_cgo_export.h"
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
|
Class gio_layerClass(void) {
|
||||||
|
return [CAEAGLLayer class];
|
||||||
|
}
|
||||||
|
|
||||||
int gio_renderbufferStorage(CFTypeRef ctxRef, CFTypeRef layerRef, GLenum buffer) {
|
int gio_renderbufferStorage(CFTypeRef ctxRef, CFTypeRef layerRef, GLenum buffer) {
|
||||||
EAGLContext *ctx = (__bridge EAGLContext *)ctxRef;
|
EAGLContext *ctx = (__bridge EAGLContext *)ctxRef;
|
||||||
CAEAGLLayer *layer = (__bridge CAEAGLLayer *)layerRef;
|
CAEAGLLayer *layer = (__bridge CAEAGLLayer *)layerRef;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: Unlicense OR MIT
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
//go:build darwin && !ios
|
//go:build darwin && !ios && nometal
|
||||||
// +build darwin,!ios
|
// +build darwin,!ios,nometal
|
||||||
|
|
||||||
package wm
|
package wm
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: Unlicense OR MIT
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
// +build darwin,!ios
|
// +build darwin,!ios,nometal
|
||||||
|
|
||||||
@import AppKit;
|
@import AppKit;
|
||||||
|
|
||||||
@@ -8,6 +8,12 @@
|
|||||||
#include <OpenGL/OpenGL.h>
|
#include <OpenGL/OpenGL.h>
|
||||||
#include "_cgo_export.h"
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
|
CALayer *gio_layerFactory(void) {
|
||||||
|
@autoreleasepool {
|
||||||
|
return [CALayer layer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CFTypeRef gio_createGLContext(void) {
|
CFTypeRef gio_createGLContext(void) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
NSOpenGLPixelFormatAttribute attr[] = {
|
NSOpenGLPixelFormatAttribute attr[] = {
|
||||||
|
|||||||
@@ -0,0 +1,178 @@
|
|||||||
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
|
//go:build !nometal
|
||||||
|
// +build !nometal
|
||||||
|
|
||||||
|
package wm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"gioui.org/gpu"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc
|
||||||
|
|
||||||
|
@import Metal;
|
||||||
|
@import QuartzCore.CAMetalLayer;
|
||||||
|
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
|
||||||
|
static CFTypeRef createMetalDevice(void) {
|
||||||
|
@autoreleasepool {
|
||||||
|
id<MTLDevice> dev = MTLCreateSystemDefaultDevice();
|
||||||
|
return CFBridgingRetain(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setupLayer(CFTypeRef layerRef, CFTypeRef devRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
CAMetalLayer *layer = (__bridge CAMetalLayer *)layerRef;
|
||||||
|
id<MTLDevice> dev = (__bridge id<MTLDevice>)devRef;
|
||||||
|
layer.device = dev;
|
||||||
|
// Package gpu assumes an sRGB-encoded framebuffer.
|
||||||
|
layer.pixelFormat = MTLPixelFormatBGRA8Unorm_sRGB;
|
||||||
|
if (@available(iOS 11.0, *)) {
|
||||||
|
// Never let nextDrawable time out and return nil.
|
||||||
|
layer.allowsNextDrawableTimeout = NO;
|
||||||
|
}
|
||||||
|
if (@available(iOS 11.2, *)) {
|
||||||
|
// Minimize latency from input to window and save a bit of memory.
|
||||||
|
layer.maximumDrawableCount = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CFTypeRef nextDrawable(CFTypeRef layerRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
CAMetalLayer *layer = (__bridge CAMetalLayer *)layerRef;
|
||||||
|
return CFBridgingRetain([layer nextDrawable]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CFTypeRef drawableTexture(CFTypeRef drawableRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
id<CAMetalDrawable> drawable = (__bridge id<CAMetalDrawable>)drawableRef;
|
||||||
|
return CFBridgingRetain(drawable.texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void presentDrawable(CFTypeRef queueRef, CFTypeRef drawableRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
id<MTLDrawable> drawable = (__bridge id<MTLDrawable>)drawableRef;
|
||||||
|
id<MTLCommandQueue> queue = (__bridge id<MTLCommandQueue>)queueRef;
|
||||||
|
id<MTLCommandBuffer> cmdBuffer = [queue commandBuffer];
|
||||||
|
[cmdBuffer presentDrawable:drawable];
|
||||||
|
[cmdBuffer commit];
|
||||||
|
[cmdBuffer waitUntilCompleted];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CFTypeRef newCommandQueue(CFTypeRef devRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
id<MTLDevice> dev = (__bridge id<MTLDevice>)devRef;
|
||||||
|
return CFBridgingRetain([dev newCommandQueue]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
type mtlContext struct {
|
||||||
|
dev C.CFTypeRef
|
||||||
|
view C.CFTypeRef
|
||||||
|
layer C.CFTypeRef
|
||||||
|
queue C.CFTypeRef
|
||||||
|
drawable C.CFTypeRef
|
||||||
|
texture C.CFTypeRef
|
||||||
|
}
|
||||||
|
|
||||||
|
func newMtlContext(w *window) (*mtlContext, error) {
|
||||||
|
dev := C.createMetalDevice()
|
||||||
|
if dev == 0 {
|
||||||
|
return nil, errors.New("metal: MTLCreateSystemDefaultDevice failed")
|
||||||
|
}
|
||||||
|
view := w.contextView()
|
||||||
|
layer := getMetalLayer(view)
|
||||||
|
if layer == 0 {
|
||||||
|
C.CFRelease(dev)
|
||||||
|
return nil, errors.New("metal: CAMetalLayer construction failed")
|
||||||
|
}
|
||||||
|
queue := C.newCommandQueue(dev)
|
||||||
|
if layer == 0 {
|
||||||
|
C.CFRelease(dev)
|
||||||
|
C.CFRelease(layer)
|
||||||
|
return nil, errors.New("metal: [MTLDevice newCommandQueue] failed")
|
||||||
|
}
|
||||||
|
C.setupLayer(layer, dev)
|
||||||
|
c := &mtlContext{
|
||||||
|
dev: dev,
|
||||||
|
view: view,
|
||||||
|
layer: layer,
|
||||||
|
queue: queue,
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mtlContext) RenderTarget() gpu.RenderTarget {
|
||||||
|
if c.drawable != 0 || c.texture != 0 {
|
||||||
|
panic("a previous RenderTarget wasn't Presented")
|
||||||
|
}
|
||||||
|
c.drawable = C.nextDrawable(c.layer)
|
||||||
|
if c.drawable == 0 {
|
||||||
|
panic("metal: [CAMetalLayer nextDrawable] failed")
|
||||||
|
}
|
||||||
|
c.texture = C.drawableTexture(c.drawable)
|
||||||
|
if c.texture == 0 {
|
||||||
|
panic("metal: CADrawable.texture is nil")
|
||||||
|
}
|
||||||
|
return gpu.MetalRenderTarget{
|
||||||
|
Texture: unsafe.Pointer(c.texture),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mtlContext) API() gpu.API {
|
||||||
|
return gpu.Metal{
|
||||||
|
Device: unsafe.Pointer(c.dev),
|
||||||
|
Queue: unsafe.Pointer(c.queue),
|
||||||
|
PixelFormat: int(C.MTLPixelFormatBGRA8Unorm_sRGB),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mtlContext) Release() {
|
||||||
|
C.CFRelease(c.queue)
|
||||||
|
C.CFRelease(c.dev)
|
||||||
|
C.CFRelease(c.layer)
|
||||||
|
if c.drawable != 0 {
|
||||||
|
C.CFRelease(c.drawable)
|
||||||
|
}
|
||||||
|
if c.texture != 0 {
|
||||||
|
C.CFRelease(c.texture)
|
||||||
|
}
|
||||||
|
*c = mtlContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mtlContext) Present() error {
|
||||||
|
C.CFRelease(c.texture)
|
||||||
|
c.texture = 0
|
||||||
|
C.presentDrawable(c.queue, c.drawable)
|
||||||
|
C.CFRelease(c.drawable)
|
||||||
|
c.drawable = 0
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mtlContext) Lock() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mtlContext) Unlock() {}
|
||||||
|
|
||||||
|
func (c *mtlContext) Refresh() error {
|
||||||
|
resizeDrawable(c.view, c.layer)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *window) NewContext() (Context, error) {
|
||||||
|
return newMtlContext(w)
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
|
//go:build !nometal
|
||||||
|
// +build !nometal
|
||||||
|
|
||||||
|
package wm
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc
|
||||||
|
|
||||||
|
@import UIKit;
|
||||||
|
|
||||||
|
@import QuartzCore.CAMetalLayer;
|
||||||
|
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
|
||||||
|
Class gio_layerClass(void) {
|
||||||
|
return [CAMetalLayer class];
|
||||||
|
}
|
||||||
|
|
||||||
|
static CFTypeRef getMetalLayer(CFTypeRef viewRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
UIView *view = (__bridge UIView *)viewRef;
|
||||||
|
return CFBridgingRetain(view.layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resizeDrawable(CFTypeRef viewRef, CFTypeRef layerRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
UIView *view = (__bridge UIView *)viewRef;
|
||||||
|
CAMetalLayer *layer = (__bridge CAMetalLayer *)layerRef;
|
||||||
|
layer.contentsScale = view.contentScaleFactor;
|
||||||
|
CGSize size = layer.bounds.size;
|
||||||
|
size.width *= layer.contentsScale;
|
||||||
|
size.height *= layer.contentsScale;
|
||||||
|
layer.drawableSize = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func getMetalLayer(view C.CFTypeRef) C.CFTypeRef {
|
||||||
|
return C.getMetalLayer(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resizeDrawable(view, layer C.CFTypeRef) {
|
||||||
|
C.resizeDrawable(view, layer)
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
|
//go:build darwin && !ios && !nometal
|
||||||
|
// +build darwin,!ios,!nometal
|
||||||
|
|
||||||
|
package wm
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc
|
||||||
|
|
||||||
|
@import AppKit;
|
||||||
|
|
||||||
|
@import QuartzCore.CAMetalLayer;
|
||||||
|
|
||||||
|
#include <CoreFoundation/CoreFoundation.h>
|
||||||
|
|
||||||
|
CALayer *gio_layerFactory(void) {
|
||||||
|
@autoreleasepool {
|
||||||
|
return [CAMetalLayer layer];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CFTypeRef getMetalLayer(CFTypeRef viewRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
NSView *view = (__bridge NSView *)viewRef;
|
||||||
|
return CFBridgingRetain(view.layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resizeDrawable(CFTypeRef viewRef, CFTypeRef layerRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
NSView *view = (__bridge NSView *)viewRef;
|
||||||
|
CAMetalLayer *layer = (__bridge CAMetalLayer *)layerRef;
|
||||||
|
CGSize size = layer.bounds.size;
|
||||||
|
size.width *= layer.contentsScale;
|
||||||
|
size.height *= layer.contentsScale;
|
||||||
|
layer.drawableSize = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func getMetalLayer(view C.CFTypeRef) C.CFTypeRef {
|
||||||
|
return C.getMetalLayer(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resizeDrawable(view, layer C.CFTypeRef) {
|
||||||
|
C.resizeDrawable(view, layer)
|
||||||
|
}
|
||||||
@@ -46,24 +46,6 @@ static void hideTextInput(CFTypeRef viewRef) {
|
|||||||
[view resignFirstResponder];
|
[view resignFirstResponder];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addLayerToView(CFTypeRef viewRef, CFTypeRef layerRef) {
|
|
||||||
UIView *view = (__bridge UIView *)viewRef;
|
|
||||||
CALayer *layer = (__bridge CALayer *)layerRef;
|
|
||||||
[view.layer addSublayer:layer];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void updateView(CFTypeRef viewRef, CFTypeRef layerRef) {
|
|
||||||
UIView *view = (__bridge UIView *)viewRef;
|
|
||||||
CAEAGLLayer *layer = (__bridge CAEAGLLayer *)layerRef;
|
|
||||||
layer.contentsScale = view.contentScaleFactor;
|
|
||||||
layer.bounds = view.bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void removeLayer(CFTypeRef layerRef) {
|
|
||||||
CALayer *layer = (__bridge CALayer *)layerRef;
|
|
||||||
[layer removeFromSuperlayer];
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct drawParams viewDrawParams(CFTypeRef viewRef) {
|
static struct drawParams viewDrawParams(CFTypeRef viewRef) {
|
||||||
UIView *v = (__bridge UIView *)viewRef;
|
UIView *v = (__bridge UIView *)viewRef;
|
||||||
struct drawParams params;
|
struct drawParams params;
|
||||||
@@ -92,7 +74,6 @@ import (
|
|||||||
"image"
|
"image"
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf16"
|
"unicode/utf16"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -112,8 +93,7 @@ type window struct {
|
|||||||
w Callbacks
|
w Callbacks
|
||||||
displayLink *displayLink
|
displayLink *displayLink
|
||||||
|
|
||||||
layer C.CFTypeRef
|
visible bool
|
||||||
visible atomic.Value
|
|
||||||
cursor pointer.CursorName
|
cursor pointer.CursorName
|
||||||
|
|
||||||
pointerMap []C.CFTypeRef
|
pointerMap []C.CFTypeRef
|
||||||
@@ -121,8 +101,6 @@ type window struct {
|
|||||||
|
|
||||||
var mainWindow = newWindowRendezvous()
|
var mainWindow = newWindowRendezvous()
|
||||||
|
|
||||||
var layerFactory func() uintptr
|
|
||||||
|
|
||||||
var views = make(map[C.CFTypeRef]*window)
|
var views = make(map[C.CFTypeRef]*window)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -145,9 +123,6 @@ func onCreate(view C.CFTypeRef) {
|
|||||||
wopts := <-mainWindow.out
|
wopts := <-mainWindow.out
|
||||||
w.w = wopts.window
|
w.w = wopts.window
|
||||||
w.w.SetDriver(w)
|
w.w.SetDriver(w)
|
||||||
w.visible.Store(false)
|
|
||||||
w.layer = C.CFTypeRef(layerFactory())
|
|
||||||
C.addLayerToView(view, w.layer)
|
|
||||||
views[view] = w
|
views[view] = w
|
||||||
w.w.Event(system.StageEvent{Stage: system.StagePaused})
|
w.w.Event(system.StageEvent{Stage: system.StagePaused})
|
||||||
}
|
}
|
||||||
@@ -163,9 +138,8 @@ func (w *window) draw(sync bool) {
|
|||||||
if params.width == 0 || params.height == 0 {
|
if params.width == 0 || params.height == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
wasVisible := w.isVisible()
|
wasVisible := w.visible
|
||||||
w.visible.Store(true)
|
w.visible = true
|
||||||
C.updateView(w.view, w.layer)
|
|
||||||
if !wasVisible {
|
if !wasVisible {
|
||||||
w.w.Event(system.StageEvent{Stage: system.StageRunning})
|
w.w.Event(system.StageEvent{Stage: system.StageRunning})
|
||||||
}
|
}
|
||||||
@@ -195,7 +169,7 @@ func (w *window) draw(sync bool) {
|
|||||||
//export onStop
|
//export onStop
|
||||||
func onStop(view C.CFTypeRef) {
|
func onStop(view C.CFTypeRef) {
|
||||||
w := views[view]
|
w := views[view]
|
||||||
w.visible.Store(false)
|
w.visible = false
|
||||||
w.w.Event(system.StageEvent{Stage: system.StagePaused})
|
w.w.Event(system.StageEvent{Stage: system.StagePaused})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,9 +179,6 @@ func onDestroy(view C.CFTypeRef) {
|
|||||||
delete(views, view)
|
delete(views, view)
|
||||||
w.w.Event(system.DestroyEvent{})
|
w.w.Event(system.DestroyEvent{})
|
||||||
w.displayLink.Close()
|
w.displayLink.Close()
|
||||||
C.removeLayer(w.layer)
|
|
||||||
C.CFRelease(w.layer)
|
|
||||||
w.layer = 0
|
|
||||||
w.view = 0
|
w.view = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,12 +312,8 @@ func (w *window) lookupTouch(last bool, touch C.CFTypeRef) pointer.ID {
|
|||||||
return pointer.ID(id)
|
return pointer.ID(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) contextLayer() uintptr {
|
func (w *window) contextView() C.CFTypeRef {
|
||||||
return uintptr(w.layer)
|
return w.view
|
||||||
}
|
|
||||||
|
|
||||||
func (w *window) isVisible() bool {
|
|
||||||
return w.visible.Load().(bool)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) ShowTextInput(show bool) {
|
func (w *window) ShowTextInput(show bool) {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "_cgo_export.h"
|
#include "_cgo_export.h"
|
||||||
#include "framework_ios.h"
|
#include "framework_ios.h"
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("hidden"))) Class gio_layerClass(void);
|
||||||
|
|
||||||
@interface GioView: UIView <UIKeyInput>
|
@interface GioView: UIView <UIKeyInput>
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -125,6 +127,9 @@ NSArray<UIKeyCommand *> *_keyCommands;
|
|||||||
gio_onFrameCallback((__bridge CFTypeRef)link);
|
gio_onFrameCallback((__bridge CFTypeRef)link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (Class)layerClass {
|
||||||
|
return gio_layerClass();
|
||||||
|
}
|
||||||
- (void)willMoveToWindow:(UIWindow *)newWindow {
|
- (void)willMoveToWindow:(UIWindow *)newWindow {
|
||||||
if (self.window != nil) {
|
if (self.window != nil) {
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||||
@@ -157,9 +162,6 @@ NSArray<UIKeyCommand *> *_keyCommands;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc {
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
|
||||||
handleTouches(0, self, touches, event);
|
handleTouches(0, self, touches, event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -423,11 +423,9 @@ func gio_onClose(view C.CFTypeRef) {
|
|||||||
deleteView(view)
|
deleteView(view)
|
||||||
w.w.Event(system.DestroyEvent{})
|
w.w.Event(system.DestroyEvent{})
|
||||||
w.displayLink.Close()
|
w.displayLink.Close()
|
||||||
w.displayLink = nil
|
|
||||||
C.CFRelease(w.view)
|
C.CFRelease(w.view)
|
||||||
w.view = 0
|
|
||||||
C.CFRelease(w.window)
|
C.CFRelease(w.window)
|
||||||
w.window = 0
|
*w = window{}
|
||||||
}
|
}
|
||||||
|
|
||||||
//export gio_onHide
|
//export gio_onHide
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "_cgo_export.h"
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
|
__attribute__ ((visibility ("hidden"))) CALayer *gio_layerFactory(void);
|
||||||
|
|
||||||
@interface GioAppDelegate : NSObject<NSApplicationDelegate>
|
@interface GioAppDelegate : NSObject<NSApplicationDelegate>
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -54,13 +56,24 @@ static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFlo
|
|||||||
gio_onMouse((__bridge CFTypeRef)view, typ, [NSEvent pressedMouseButtons], p.x, height - p.y, dx, dy, [event timestamp], [event modifierFlags]);
|
gio_onMouse((__bridge CFTypeRef)view, typ, [NSEvent pressedMouseButtons], p.x, height - p.y, dx, dy, [event timestamp], [event modifierFlags]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@interface GioView : NSView
|
@interface GioView : NSView <CALayerDelegate>
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GioView
|
@implementation GioView
|
||||||
|
// drawRect is called when OpenGL is used, displayLayer otherwise.
|
||||||
|
// Don't know why.
|
||||||
- (void)drawRect:(NSRect)r {
|
- (void)drawRect:(NSRect)r {
|
||||||
gio_onDraw((__bridge CFTypeRef)self);
|
gio_onDraw((__bridge CFTypeRef)self);
|
||||||
}
|
}
|
||||||
|
- (void)displayLayer:(CALayer *)layer {
|
||||||
|
layer.contentsScale = self.window.backingScaleFactor;
|
||||||
|
gio_onDraw((__bridge CFTypeRef)self);
|
||||||
|
}
|
||||||
|
- (CALayer *)makeBackingLayer {
|
||||||
|
CALayer *layer = gio_layerFactory();
|
||||||
|
layer.delegate = self;
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
- (void)mouseDown:(NSEvent *)event {
|
- (void)mouseDown:(NSEvent *)event {
|
||||||
handleMouse(self, event, MOUSE_DOWN, 0, 0);
|
handleMouse(self, event, MOUSE_DOWN, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -221,6 +234,7 @@ CFTypeRef gio_createView(void) {
|
|||||||
NSRect frame = NSMakeRect(0, 0, 0, 0);
|
NSRect frame = NSMakeRect(0, 0, 0, 0);
|
||||||
GioView* view = [[GioView alloc] initWithFrame:frame];
|
GioView* view = [[GioView alloc] initWithFrame:frame];
|
||||||
[view setWantsLayer:YES];
|
[view setWantsLayer:YES];
|
||||||
|
view.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
|
||||||
return CFBridgingRetain(view);
|
return CFBridgingRetain(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2
|
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2
|
||||||
gioui.org/shader v0.0.0-20210820085839-484f7c0305de
|
gioui.org/shader v0.0.0-20210821062758-133bba6632c7
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7
|
|||||||
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
||||||
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJGFDjINIPi1jtO6pc=
|
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 h1:AGDDxsJE1RpcXTAxPG2B4jrwVUJGFDjINIPi1jtO6pc=
|
||||||
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=
|
||||||
gioui.org/shader v0.0.0-20210820085839-484f7c0305de h1:fkcZh0i9T0SzMlqiDm2GBVqXZsbX6bevHcJHfR0llcg=
|
gioui.org/shader v0.0.0-20210821062758-133bba6632c7 h1:DzpPjbWzoI5cg+WBXWSF2007lzdViHKYZR5NUOKD55k=
|
||||||
gioui.org/shader v0.0.0-20210820085839-484f7c0305de/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM=
|
gioui.org/shader v0.0.0-20210821062758-133bba6632c7/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
|
|||||||
@@ -17,8 +17,14 @@ type OpenGLRenderTarget = driver.OpenGLRenderTarget
|
|||||||
// Direct3D11RenderTarget is a render target suitable for the Direct3D 11 backend.
|
// Direct3D11RenderTarget is a render target suitable for the Direct3D 11 backend.
|
||||||
type Direct3D11RenderTarget = driver.Direct3D11RenderTarget
|
type Direct3D11RenderTarget = driver.Direct3D11RenderTarget
|
||||||
|
|
||||||
|
// MetalRenderTarget is a render target suitable for the Metal backend.
|
||||||
|
type MetalRenderTarget = driver.MetalRenderTarget
|
||||||
|
|
||||||
// OpenGL denotes the OpenGL or OpenGL ES API.
|
// OpenGL denotes the OpenGL or OpenGL ES API.
|
||||||
type OpenGL = driver.OpenGL
|
type OpenGL = driver.OpenGL
|
||||||
|
|
||||||
// Direct3D11 denotes the Direct3D API.
|
// Direct3D11 denotes the Direct3D API.
|
||||||
type Direct3D11 = driver.Direct3D11
|
type Direct3D11 = driver.Direct3D11
|
||||||
|
|
||||||
|
// Metal denotes the Apple Metal API.
|
||||||
|
type Metal = driver.Metal
|
||||||
|
|||||||
+2
-1
@@ -36,6 +36,7 @@ import (
|
|||||||
|
|
||||||
// Register backends.
|
// Register backends.
|
||||||
_ "gioui.org/gpu/internal/d3d11"
|
_ "gioui.org/gpu/internal/d3d11"
|
||||||
|
_ "gioui.org/gpu/internal/metal"
|
||||||
_ "gioui.org/gpu/internal/opengl"
|
_ "gioui.org/gpu/internal/opengl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -135,7 +136,7 @@ type imageOp struct {
|
|||||||
|
|
||||||
// shaderModuleVersion is the exact version of gioui.org/shader expected by
|
// shaderModuleVersion is the exact version of gioui.org/shader expected by
|
||||||
// this package. Shader programs are not backwards or forwards compatible.
|
// this package. Shader programs are not backwards or forwards compatible.
|
||||||
const shaderModuleVersion = "v0.0.0-20210820085839-484f7c0305de"
|
const shaderModuleVersion = "v0.0.0-20210821062758-133bba6632c7"
|
||||||
|
|
||||||
func decodeStrokeOp(data []byte) clip.StrokeStyle {
|
func decodeStrokeOp(data []byte) clip.StrokeStyle {
|
||||||
_ = data[4]
|
_ = data[4]
|
||||||
|
|||||||
@@ -3,46 +3,69 @@
|
|||||||
package headless
|
package headless
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"gioui.org/gpu"
|
"gioui.org/gpu"
|
||||||
_ "gioui.org/internal/cocoainit"
|
_ "gioui.org/internal/cocoainit"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo CFLAGS: -DGL_SILENCE_DEPRECATION -Werror -Wno-deprecated-declarations -fmodules -fobjc-arc -x objective-c
|
#cgo CFLAGS: -Werror -Wno-deprecated-declarations -fmodules -fobjc-arc -x objective-c
|
||||||
|
#cgo LDFLAGS: -framework CoreGraphics
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
@import Metal;
|
||||||
|
|
||||||
__attribute__ ((visibility ("hidden"))) CFTypeRef gio_headless_newContext(void);
|
static CFTypeRef createDevice(void) {
|
||||||
__attribute__ ((visibility ("hidden"))) void gio_headless_clearCurrentContext(CFTypeRef ctxRef);
|
@autoreleasepool {
|
||||||
__attribute__ ((visibility ("hidden"))) void gio_headless_makeCurrentContext(CFTypeRef ctxRef);
|
id dev = MTLCreateSystemDefaultDevice();
|
||||||
|
return CFBridgingRetain(dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CFTypeRef newCommandQueue(CFTypeRef devRef) {
|
||||||
|
@autoreleasepool {
|
||||||
|
id<MTLDevice> dev = (__bridge id<MTLDevice>)devRef;
|
||||||
|
return CFBridgingRetain([dev newCommandQueue]);
|
||||||
|
}
|
||||||
|
}
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
type nsContext struct {
|
type mtlContext struct {
|
||||||
ctx C.CFTypeRef
|
dev C.CFTypeRef
|
||||||
|
queue C.CFTypeRef
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContext() (context, error) {
|
func newContext() (context, error) {
|
||||||
ctx := C.gio_headless_newContext()
|
dev := C.createDevice()
|
||||||
return &nsContext{ctx: ctx}, nil
|
if dev == 0 {
|
||||||
|
return nil, errors.New("headless: failed to create Metal device")
|
||||||
|
}
|
||||||
|
queue := C.newCommandQueue(dev)
|
||||||
|
if queue == 0 {
|
||||||
|
C.CFRelease(dev)
|
||||||
|
return nil, errors.New("headless: failed to create MTLQueue")
|
||||||
|
}
|
||||||
|
return &mtlContext{dev: dev, queue: queue}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *nsContext) API() gpu.API {
|
func (c *mtlContext) API() gpu.API {
|
||||||
return gpu.OpenGL{}
|
return gpu.Metal{
|
||||||
|
Device: unsafe.Pointer(c.dev),
|
||||||
|
Queue: unsafe.Pointer(c.queue),
|
||||||
|
PixelFormat: int(C.MTLPixelFormatRGBA8Unorm_sRGB),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *nsContext) MakeCurrent() error {
|
func (c *mtlContext) MakeCurrent() error {
|
||||||
C.gio_headless_makeCurrentContext(c.ctx)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *nsContext) ReleaseCurrent() {
|
func (c *mtlContext) ReleaseCurrent() {}
|
||||||
C.gio_headless_clearCurrentContext(c.ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *nsContext) Release() {
|
func (d *mtlContext) Release() {
|
||||||
if d.ctx != 0 {
|
C.CFRelease(d.dev)
|
||||||
C.CFRelease(d.ctx)
|
C.CFRelease(d.queue)
|
||||||
d.ctx = 0
|
*d = mtlContext{}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Unlicense OR MIT
|
|
||||||
|
|
||||||
// +build darwin,ios
|
|
||||||
|
|
||||||
@import OpenGLES;
|
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
#include "_cgo_export.h"
|
|
||||||
|
|
||||||
CFTypeRef gio_headless_newContext(void) {
|
|
||||||
EAGLContext *ctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
|
|
||||||
if (ctx == nil) {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
return CFBridgingRetain(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gio_headless_clearCurrentContext(CFTypeRef ctxRef) {
|
|
||||||
[EAGLContext setCurrentContext:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
void gio_headless_makeCurrentContext(CFTypeRef ctxRef) {
|
|
||||||
EAGLContext *ctx = (__bridge EAGLContext *)ctxRef;
|
|
||||||
[EAGLContext setCurrentContext:ctx];
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
// SPDX-License-Identifier: Unlicense OR MIT
|
|
||||||
|
|
||||||
// +build darwin,!ios
|
|
||||||
|
|
||||||
@import AppKit;
|
|
||||||
@import OpenGL;
|
|
||||||
@import OpenGL.GL;
|
|
||||||
@import OpenGL.GL3;
|
|
||||||
|
|
||||||
#include <CoreFoundation/CoreFoundation.h>
|
|
||||||
#include "_cgo_export.h"
|
|
||||||
|
|
||||||
CFTypeRef gio_headless_newContext(void) {
|
|
||||||
NSOpenGLPixelFormatAttribute attr[] = {
|
|
||||||
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
|
|
||||||
NSOpenGLPFAColorSize, 24,
|
|
||||||
NSOpenGLPFAAccelerated,
|
|
||||||
// Opt-in to automatic GPU switching. CGL-only property.
|
|
||||||
kCGLPFASupportsAutomaticGraphicsSwitching,
|
|
||||||
NSOpenGLPFAAllowOfflineRenderers,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
NSOpenGLPixelFormat *pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
|
|
||||||
if (pixFormat == nil) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:pixFormat shareContext:nil];
|
|
||||||
return CFBridgingRetain(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gio_headless_clearCurrentContext(CFTypeRef ctxRef) {
|
|
||||||
NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
|
|
||||||
CGLUnlockContext([ctx CGLContextObj]);
|
|
||||||
[NSOpenGLContext clearCurrentContext];
|
|
||||||
}
|
|
||||||
|
|
||||||
void gio_headless_makeCurrentContext(CFTypeRef ctxRef) {
|
|
||||||
NSOpenGLContext *ctx = (__bridge NSOpenGLContext *)ctxRef;
|
|
||||||
[ctx makeCurrentContext];
|
|
||||||
CGLLockContext([ctx CGLContextObj]);
|
|
||||||
}
|
|
||||||
@@ -26,6 +26,11 @@ type Direct3D11RenderTarget struct {
|
|||||||
RenderTarget unsafe.Pointer
|
RenderTarget unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MetalRenderTarget struct {
|
||||||
|
// Texture is a MTLTexture.
|
||||||
|
Texture unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
type OpenGL struct {
|
type OpenGL struct {
|
||||||
// ES forces the use of ANGLE OpenGL ES libraries on macOS. It is
|
// ES forces the use of ANGLE OpenGL ES libraries on macOS. It is
|
||||||
// ignored on all other platforms.
|
// ignored on all other platforms.
|
||||||
@@ -41,10 +46,20 @@ type Direct3D11 struct {
|
|||||||
Device unsafe.Pointer
|
Device unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Metal struct {
|
||||||
|
// Device is an MTLDevice.
|
||||||
|
Device unsafe.Pointer
|
||||||
|
// Queue is a MTLCommandQueue.
|
||||||
|
Queue unsafe.Pointer
|
||||||
|
// PixelFormat is the MTLPixelFormat of the default framebuffer.
|
||||||
|
PixelFormat int
|
||||||
|
}
|
||||||
|
|
||||||
// API specific device constructors.
|
// API specific device constructors.
|
||||||
var (
|
var (
|
||||||
NewOpenGLDevice func(api OpenGL) (Device, error)
|
NewOpenGLDevice func(api OpenGL) (Device, error)
|
||||||
NewDirect3D11Device func(api Direct3D11) (Device, error)
|
NewDirect3D11Device func(api Direct3D11) (Device, error)
|
||||||
|
NewMetalDevice func(api Metal) (Device, error)
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewDevice creates a new Device given the api.
|
// NewDevice creates a new Device given the api.
|
||||||
@@ -62,11 +77,17 @@ func NewDevice(api API) (Device, error) {
|
|||||||
if NewDirect3D11Device != nil {
|
if NewDirect3D11Device != nil {
|
||||||
return NewDirect3D11Device(api)
|
return NewDirect3D11Device(api)
|
||||||
}
|
}
|
||||||
|
case Metal:
|
||||||
|
if NewMetalDevice != nil {
|
||||||
|
return NewMetalDevice(api)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("driver: no driver available for the API %T", api)
|
return nil, fmt.Errorf("driver: no driver available for the API %T", api)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (OpenGL) implementsAPI() {}
|
func (OpenGL) implementsAPI() {}
|
||||||
func (Direct3D11) implementsAPI() {}
|
func (Direct3D11) implementsAPI() {}
|
||||||
|
func (Metal) implementsAPI() {}
|
||||||
func (OpenGLRenderTarget) ImplementsRenderTarget() {}
|
func (OpenGLRenderTarget) ImplementsRenderTarget() {}
|
||||||
func (Direct3D11RenderTarget) ImplementsRenderTarget() {}
|
func (Direct3D11RenderTarget) ImplementsRenderTarget() {}
|
||||||
|
func (MetalRenderTarget) ImplementsRenderTarget() {}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
|
// This file exists so this package builds on non-Darwin platforms.
|
||||||
|
|
||||||
|
package metal
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user