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:
Elias Naur
2021-08-03 16:53:42 +02:00
parent a7f08eedf3
commit 3b2992c37e
21 changed files with 1603 additions and 151 deletions
+44 -21
View File
@@ -3,46 +3,69 @@
package headless
import (
"errors"
"unsafe"
"gioui.org/gpu"
_ "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);
__attribute__ ((visibility ("hidden"))) void gio_headless_clearCurrentContext(CFTypeRef ctxRef);
__attribute__ ((visibility ("hidden"))) void gio_headless_makeCurrentContext(CFTypeRef ctxRef);
static CFTypeRef createDevice(void) {
@autoreleasepool {
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"
type nsContext struct {
ctx C.CFTypeRef
type mtlContext struct {
dev C.CFTypeRef
queue C.CFTypeRef
}
func newContext() (context, error) {
ctx := C.gio_headless_newContext()
return &nsContext{ctx: ctx}, nil
dev := C.createDevice()
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 {
return gpu.OpenGL{}
func (c *mtlContext) API() gpu.API {
return gpu.Metal{
Device: unsafe.Pointer(c.dev),
Queue: unsafe.Pointer(c.queue),
PixelFormat: int(C.MTLPixelFormatRGBA8Unorm_sRGB),
}
}
func (c *nsContext) MakeCurrent() error {
C.gio_headless_makeCurrentContext(c.ctx)
func (c *mtlContext) MakeCurrent() error {
return nil
}
func (c *nsContext) ReleaseCurrent() {
C.gio_headless_clearCurrentContext(c.ctx)
}
func (c *mtlContext) ReleaseCurrent() {}
func (d *nsContext) Release() {
if d.ctx != 0 {
C.CFRelease(d.ctx)
d.ctx = 0
}
func (d *mtlContext) Release() {
C.CFRelease(d.dev)
C.CFRelease(d.queue)
*d = mtlContext{}
}
-25
View File
@@ -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];
}
-41
View File
@@ -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]);
}