mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-05 17:35:36 +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:
@@ -17,8 +17,14 @@ type OpenGLRenderTarget = driver.OpenGLRenderTarget
|
||||
// Direct3D11RenderTarget is a render target suitable for the Direct3D 11 backend.
|
||||
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.
|
||||
type OpenGL = driver.OpenGL
|
||||
|
||||
// Direct3D11 denotes the Direct3D API.
|
||||
type Direct3D11 = driver.Direct3D11
|
||||
|
||||
// Metal denotes the Apple Metal API.
|
||||
type Metal = driver.Metal
|
||||
|
||||
+2
-1
@@ -36,6 +36,7 @@ import (
|
||||
|
||||
// Register backends.
|
||||
_ "gioui.org/gpu/internal/d3d11"
|
||||
_ "gioui.org/gpu/internal/metal"
|
||||
_ "gioui.org/gpu/internal/opengl"
|
||||
)
|
||||
|
||||
@@ -135,7 +136,7 @@ type imageOp struct {
|
||||
|
||||
// shaderModuleVersion is the exact version of gioui.org/shader expected by
|
||||
// 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 {
|
||||
_ = data[4]
|
||||
|
||||
@@ -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{}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
type MetalRenderTarget struct {
|
||||
// Texture is a MTLTexture.
|
||||
Texture unsafe.Pointer
|
||||
}
|
||||
|
||||
type OpenGL struct {
|
||||
// ES forces the use of ANGLE OpenGL ES libraries on macOS. It is
|
||||
// ignored on all other platforms.
|
||||
@@ -41,10 +46,20 @@ type Direct3D11 struct {
|
||||
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.
|
||||
var (
|
||||
NewOpenGLDevice func(api OpenGL) (Device, error)
|
||||
NewDirect3D11Device func(api Direct3D11) (Device, error)
|
||||
NewMetalDevice func(api Metal) (Device, error)
|
||||
)
|
||||
|
||||
// NewDevice creates a new Device given the api.
|
||||
@@ -62,11 +77,17 @@ func NewDevice(api API) (Device, error) {
|
||||
if NewDirect3D11Device != nil {
|
||||
return NewDirect3D11Device(api)
|
||||
}
|
||||
case Metal:
|
||||
if NewMetalDevice != nil {
|
||||
return NewMetalDevice(api)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("driver: no driver available for the API %T", api)
|
||||
}
|
||||
|
||||
func (OpenGL) implementsAPI() {}
|
||||
func (Direct3D11) implementsAPI() {}
|
||||
func (Metal) implementsAPI() {}
|
||||
func (OpenGLRenderTarget) 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