mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
internal/graphicsdriver/metal: remove C for macOS (#2243)
Updates #1162
This commit is contained in:
parent
fb775d806c
commit
05470f7706
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module github.com/hajimehoshi/ebiten/v2
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/ebitengine/purego v0.0.0-20220729024107-78cdc2949de6
|
||||
github.com/ebitengine/purego v0.0.0-20220816145426-8dbe340b03f1
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad
|
||||
github.com/hajimehoshi/bitmapfont/v2 v2.2.1
|
||||
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41
|
||||
|
3
go.sum
3
go.sum
@ -1,6 +1,7 @@
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/ebitengine/purego v0.0.0-20220729024107-78cdc2949de6 h1:kc3Im5Yj31aW0r3VdXHk+urwClkQilDBAYYp0TXeqE8=
|
||||
github.com/ebitengine/purego v0.0.0-20220729024107-78cdc2949de6/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
|
||||
github.com/ebitengine/purego v0.0.0-20220816145426-8dbe340b03f1 h1:kf5uxeNGrfkESJQe81OvrxJG1jZaafBjssteag0GbPQ=
|
||||
github.com/ebitengine/purego v0.0.0-20220816145426-8dbe340b03f1/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad h1:kX51IjbsJPCvzV9jUoVQG9GEUqIq5hjfYzXTqQ52Rh8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/hajimehoshi/bitmapfont/v2 v2.2.1 h1:y7zcy02/UgO24IL3COqYtrRZzhRucNBtmCo/SNU648k=
|
||||
|
138
internal/cocoa/api_cocoa_darwin.go
Normal file
138
internal/cocoa/api_cocoa_darwin.go
Normal file
@ -0,0 +1,138 @@
|
||||
// Copyright 2022 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cocoa
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ebitengine/purego/objc"
|
||||
)
|
||||
|
||||
var (
|
||||
class_NSInvocation = objc.GetClass("NSInvocation")
|
||||
class_NSMethodSignature = objc.GetClass("NSMethodSignature")
|
||||
class_NSAutoreleasePool = objc.GetClass("NSAutoreleasePool")
|
||||
class_NSString = objc.GetClass("NSString")
|
||||
)
|
||||
|
||||
var (
|
||||
sel_alloc = objc.RegisterName("alloc")
|
||||
sel_new = objc.RegisterName("new")
|
||||
sel_release = objc.RegisterName("release")
|
||||
sel_invocationWithMethodSignature = objc.RegisterName("invocationWithMethodSignature:")
|
||||
sel_setSelector = objc.RegisterName("setSelector:")
|
||||
sel_setTarget = objc.RegisterName("setTarget:")
|
||||
sel_setArgumentAtIndex = objc.RegisterName("setArgument:atIndex:")
|
||||
sel_getReturnValue = objc.RegisterName("getReturnValue:")
|
||||
sel_invoke = objc.RegisterName("invoke")
|
||||
sel_instanceMethodSignatureForSelector = objc.RegisterName("instanceMethodSignatureForSelector:")
|
||||
sel_signatureWithObjCTypes = objc.RegisterName("signatureWithObjCTypes:")
|
||||
sel_initWithUTF8String = objc.RegisterName("initWithUTF8String:")
|
||||
sel_UTF8String = objc.RegisterName("UTF8String")
|
||||
sel_length = objc.RegisterName("length")
|
||||
)
|
||||
|
||||
type CGFloat float64
|
||||
|
||||
type CGSize struct {
|
||||
Width, Height CGFloat
|
||||
}
|
||||
|
||||
type NSError struct {
|
||||
objc.ID
|
||||
}
|
||||
|
||||
// NSInvocation is being used to call functions that can't be called directly with purego.SyscallN.
|
||||
// See the downsides of that function for what it cannot do.
|
||||
type NSInvocation struct {
|
||||
objc.ID
|
||||
}
|
||||
|
||||
func NSInvocation_invocationWithMethodSignature(sig NSMethodSignature) NSInvocation {
|
||||
return NSInvocation{objc.ID(class_NSInvocation).Send(sel_invocationWithMethodSignature, sig.ID)}
|
||||
}
|
||||
|
||||
func (inv NSInvocation) SetSelector(_cmd objc.SEL) {
|
||||
inv.Send(sel_setSelector, _cmd)
|
||||
}
|
||||
|
||||
func (inv NSInvocation) SetTarget(target objc.ID) {
|
||||
inv.Send(sel_setTarget, target)
|
||||
}
|
||||
|
||||
func (inv NSInvocation) SetArgumentAtIndex(arg unsafe.Pointer, idx int) {
|
||||
inv.Send(sel_setArgumentAtIndex, arg, idx)
|
||||
}
|
||||
|
||||
func (inv NSInvocation) GetReturnValue(ret unsafe.Pointer) {
|
||||
inv.Send(sel_getReturnValue, ret)
|
||||
}
|
||||
|
||||
func (inv NSInvocation) Invoke() {
|
||||
inv.Send(sel_invoke)
|
||||
}
|
||||
|
||||
type NSMethodSignature struct {
|
||||
objc.ID
|
||||
}
|
||||
|
||||
func NSMethodSignature_instanceMethodSignatureForSelector(self objc.ID, _cmd objc.SEL) NSMethodSignature {
|
||||
return NSMethodSignature{self.Send(sel_instanceMethodSignatureForSelector, _cmd)}
|
||||
}
|
||||
|
||||
// NSMethodSignature_signatureWithObjCTypes takes a string that represents the type signature of a method.
|
||||
// It follows the encoding specified in the Apple Docs.
|
||||
//
|
||||
// [Apple Docs]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100
|
||||
func NSMethodSignature_signatureWithObjCTypes(types string) NSMethodSignature {
|
||||
return NSMethodSignature{objc.ID(class_NSMethodSignature).Send(sel_signatureWithObjCTypes, types)}
|
||||
}
|
||||
|
||||
type NSAutoreleasePool struct {
|
||||
objc.ID
|
||||
}
|
||||
|
||||
func NSAutoreleasePool_new() NSAutoreleasePool {
|
||||
return NSAutoreleasePool{objc.ID(class_NSAutoreleasePool).Send(sel_new)}
|
||||
}
|
||||
|
||||
func (pool NSAutoreleasePool) Release() {
|
||||
pool.Send(sel_release)
|
||||
}
|
||||
|
||||
type NSString struct {
|
||||
objc.ID
|
||||
}
|
||||
|
||||
func NSString_alloc() NSString {
|
||||
return NSString{objc.ID(class_NSString).Send(sel_alloc)}
|
||||
}
|
||||
|
||||
func (s NSString) InitWithUTF8String(utf8 string) NSString {
|
||||
return NSString{s.Send(sel_initWithUTF8String, utf8)}
|
||||
}
|
||||
|
||||
func (s NSString) String() string {
|
||||
// this will be nicer with unsafe.Slice once ebitengine requires 1.17
|
||||
// reflect.SliceHeader is used because it will force Go to copy the string
|
||||
// into Go memory when casted to a string
|
||||
var b []byte
|
||||
header := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
header.Data = uintptr(s.Send(sel_UTF8String))
|
||||
header.Len = int(s.Send(sel_length))
|
||||
header.Cap = header.Len
|
||||
return string(b)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2018 The Ebiten Authors
|
||||
// Copyright 2022 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -12,10 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "stdint.h"
|
||||
//go:build ios
|
||||
// +build ios
|
||||
|
||||
void *Window_ContentView(uintptr_t window);
|
||||
package cocoa
|
||||
|
||||
void View_SetLayer(void *view, void *layer);
|
||||
void View_SetWantsLayer(void *view, unsigned char wantsLayer);
|
||||
uint8_t View_IsInFullScreenMode(void *view);
|
||||
const IsIOS = true
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2018 The Ebiten Authors
|
||||
// Copyright 2022 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -12,21 +12,9 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ns_darwin.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
//go:build !ios
|
||||
// +build !ios
|
||||
|
||||
void *Window_ContentView(uintptr_t window) {
|
||||
return ((NSWindow *)window).contentView;
|
||||
}
|
||||
package cocoa
|
||||
|
||||
void View_SetLayer(void *view, void *layer) {
|
||||
((NSView *)view).layer = (CALayer *)layer;
|
||||
}
|
||||
|
||||
void View_SetWantsLayer(void *view, unsigned char wantsLayer) {
|
||||
((NSView *)view).wantsLayer = (BOOL)wantsLayer;
|
||||
}
|
||||
|
||||
uint8_t View_IsInFullScreenMode(void *view) {
|
||||
return ((NSView *)view).isInFullScreenMode;
|
||||
}
|
||||
const IsIOS = false
|
@ -21,21 +21,16 @@ package ca
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ebitengine/purego"
|
||||
"github.com/ebitengine/purego/objc"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/cocoa"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/mtl"
|
||||
)
|
||||
|
||||
// Suppress the warnings about availability guard with -Wno-unguarded-availability-new.
|
||||
// It is because old Xcode (8 or older?) does not accept @available syntax.
|
||||
|
||||
// #cgo CFLAGS: -Wno-unguarded-availability-new
|
||||
// #cgo !ios CFLAGS: -mmacosx-version-min=10.12
|
||||
// #cgo LDFLAGS: -framework QuartzCore -framework Foundation -framework CoreGraphics
|
||||
//
|
||||
// #include "ca_darwin.h"
|
||||
import "C"
|
||||
|
||||
// Layer is an object that manages image-based content and
|
||||
// allows you to perform animations on that content.
|
||||
//
|
||||
@ -49,40 +44,51 @@ type Layer interface {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer.
|
||||
type MetalLayer struct {
|
||||
metalLayer unsafe.Pointer
|
||||
metalLayer objc.ID
|
||||
}
|
||||
|
||||
var (
|
||||
coreGraphics = purego.Dlopen("/System/Library/Frameworks/CoreGraphics.framework/Versions/Current/CoreGraphics", purego.RTLD_GLOBAL)
|
||||
_CGColorSpaceCreateWithName = purego.Dlsym(coreGraphics, "CGColorSpaceCreateWithName")
|
||||
_CGColorSpaceRelease = purego.Dlsym(coreGraphics, "CGColorSpaceRelease")
|
||||
kCGColorSpaceDisplayP3 = purego.Dlsym(coreGraphics, "kCGColorSpaceDisplayP3")
|
||||
)
|
||||
|
||||
// MakeMetalLayer creates a new Core Animation Metal layer.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer.
|
||||
func MakeMetalLayer() MetalLayer {
|
||||
return MetalLayer{C.MakeMetalLayer()}
|
||||
layer := objc.ID(objc.GetClass("CAMetalLayer")).Send(objc.RegisterName("new"))
|
||||
if !cocoa.IsIOS {
|
||||
colorspace, _, _ := purego.SyscallN(_CGColorSpaceCreateWithName, **(**uintptr)(unsafe.Pointer(&kCGColorSpaceDisplayP3))) // Dlsym returns pointer to symbol so dereference it
|
||||
layer.Send(objc.RegisterName("setColorspace:"), colorspace)
|
||||
purego.SyscallN(_CGColorSpaceRelease, colorspace)
|
||||
}
|
||||
return MetalLayer{layer}
|
||||
}
|
||||
|
||||
// Layer implements the Layer interface.
|
||||
func (ml MetalLayer) Layer() unsafe.Pointer { return ml.metalLayer }
|
||||
func (ml MetalLayer) Layer() unsafe.Pointer {
|
||||
return *(*unsafe.Pointer)(unsafe.Pointer(&ml.metalLayer))
|
||||
}
|
||||
|
||||
// PixelFormat returns the pixel format of textures for rendering layer content.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/1478155-pixelformat.
|
||||
func (ml MetalLayer) PixelFormat() mtl.PixelFormat {
|
||||
return mtl.PixelFormat(C.MetalLayer_PixelFormat(ml.metalLayer))
|
||||
return mtl.PixelFormat(ml.metalLayer.Send(objc.RegisterName("pixelFormat")))
|
||||
}
|
||||
|
||||
// SetDevice sets the Metal device responsible for the layer's drawable resources.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/1478163-device.
|
||||
func (ml MetalLayer) SetDevice(device mtl.Device) {
|
||||
C.MetalLayer_SetDevice(ml.metalLayer, device.Device())
|
||||
ml.metalLayer.Send(objc.RegisterName("setDevice:"), uintptr(device.Device()))
|
||||
}
|
||||
|
||||
// SetOpaque a Boolean value indicating whether the layer contains completely opaque content.
|
||||
func (ml MetalLayer) SetOpaque(opaque bool) {
|
||||
if opaque {
|
||||
C.MetalLayer_SetOpaque(ml.metalLayer, 1)
|
||||
} else {
|
||||
C.MetalLayer_SetOpaque(ml.metalLayer, 0)
|
||||
}
|
||||
ml.metalLayer.Send(objc.RegisterName("setOpaque:"), opaque)
|
||||
}
|
||||
|
||||
// SetPixelFormat controls the pixel format of textures for rendering layer content.
|
||||
@ -93,10 +99,12 @@ func (ml MetalLayer) SetOpaque(opaque bool) {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/1478155-pixelformat.
|
||||
func (ml MetalLayer) SetPixelFormat(pf mtl.PixelFormat) {
|
||||
e := C.MetalLayer_SetPixelFormat(ml.metalLayer, C.uint16_t(pf))
|
||||
if e != nil {
|
||||
panic(errors.New(C.GoString(e)))
|
||||
switch pf {
|
||||
case mtl.PixelFormatRGBA8UNorm, mtl.PixelFormatRGBA8UNormSRGB, mtl.PixelFormatBGRA8UNorm, mtl.PixelFormatBGRA8UNormSRGB, mtl.PixelFormatStencil8:
|
||||
default:
|
||||
panic(errors.New(fmt.Sprintf("invalid pixel format %d", pf)))
|
||||
}
|
||||
ml.metalLayer.Send(objc.RegisterName("setPixelFormat:"), uint(pf))
|
||||
}
|
||||
|
||||
// SetMaximumDrawableCount controls the number of Metal drawables in the resource pool
|
||||
@ -106,10 +114,10 @@ func (ml MetalLayer) SetPixelFormat(pf mtl.PixelFormat) {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/2938720-maximumdrawablecount.
|
||||
func (ml MetalLayer) SetMaximumDrawableCount(count int) {
|
||||
e := C.MetalLayer_SetMaximumDrawableCount(ml.metalLayer, C.uint_t(count))
|
||||
if e != nil {
|
||||
panic(errors.New(C.GoString(e)))
|
||||
if count < 2 || count > 3 {
|
||||
panic(errors.New(fmt.Sprintf("failed trying to set maximumDrawableCount to %d outside of the valid range of [2, 3]", count)))
|
||||
}
|
||||
ml.metalLayer.Send(objc.RegisterName("setMaximumDrawableCount:"), count)
|
||||
}
|
||||
|
||||
// SetDisplaySyncEnabled controls whether the Metal layer and its drawables
|
||||
@ -117,30 +125,34 @@ func (ml MetalLayer) SetMaximumDrawableCount(count int) {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/2887087-displaysyncenabled.
|
||||
func (ml MetalLayer) SetDisplaySyncEnabled(enabled bool) {
|
||||
switch enabled {
|
||||
case true:
|
||||
C.MetalLayer_SetDisplaySyncEnabled(ml.metalLayer, 1)
|
||||
case false:
|
||||
C.MetalLayer_SetDisplaySyncEnabled(ml.metalLayer, 0)
|
||||
if cocoa.IsIOS {
|
||||
return
|
||||
}
|
||||
ml.metalLayer.Send(objc.RegisterName("setDisplaySyncEnabled:"), enabled)
|
||||
}
|
||||
|
||||
// SetDrawableSize sets the size, in pixels, of textures for rendering layer content.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/1478174-drawablesize.
|
||||
func (ml MetalLayer) SetDrawableSize(width, height int) {
|
||||
C.MetalLayer_SetDrawableSize(ml.metalLayer, C.double(width), C.double(height))
|
||||
// TODO: once objc supports calling functions with struct arguments replace this with just a ID.Send call
|
||||
var sel_setDrawableSize = objc.RegisterName("setDrawableSize:")
|
||||
sig := cocoa.NSMethodSignature_instanceMethodSignatureForSelector(objc.ID(objc.GetClass("CAMetalLayer")), sel_setDrawableSize)
|
||||
inv := cocoa.NSInvocation_invocationWithMethodSignature(sig)
|
||||
inv.SetTarget(ml.metalLayer)
|
||||
inv.SetSelector(sel_setDrawableSize)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&cocoa.CGSize{Width: cocoa.CGFloat(width), Height: cocoa.CGFloat(height)}), 2)
|
||||
inv.Invoke()
|
||||
}
|
||||
|
||||
// NextDrawable returns a Metal drawable.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/1478172-nextdrawable.
|
||||
func (ml MetalLayer) NextDrawable() (MetalDrawable, error) {
|
||||
md := C.MetalLayer_NextDrawable(ml.metalLayer)
|
||||
if md == nil {
|
||||
md := ml.metalLayer.Send(objc.RegisterName("nextDrawable"))
|
||||
if md == 0 {
|
||||
return MetalDrawable{}, errors.New("nextDrawable returned nil")
|
||||
}
|
||||
|
||||
return MetalDrawable{md}, nil
|
||||
}
|
||||
|
||||
@ -148,52 +160,45 @@ func (ml MetalLayer) NextDrawable() (MetalDrawable, error) {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/1478157-presentswithtransaction
|
||||
func (ml MetalLayer) PresentsWithTransaction() bool {
|
||||
return C.MetalLayer_PresentsWithTransaction(ml.metalLayer) != 0
|
||||
return ml.metalLayer.Send(objc.RegisterName("presentsWithTransaction")) != 0
|
||||
}
|
||||
|
||||
// SetPresentsWithTransaction sets a Boolean value that determines whether the layer presents its content using a Core Animation transaction.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametallayer/1478157-presentswithtransaction
|
||||
func (ml MetalLayer) SetPresentsWithTransaction(presentsWithTransaction bool) {
|
||||
if presentsWithTransaction {
|
||||
C.MetalLayer_SetPresentsWithTransaction(ml.metalLayer, 1)
|
||||
} else {
|
||||
C.MetalLayer_SetPresentsWithTransaction(ml.metalLayer, 0)
|
||||
}
|
||||
ml.metalLayer.Send(objc.RegisterName("setPresentsWithTransaction:"), presentsWithTransaction)
|
||||
}
|
||||
|
||||
// SetFramebufferOnly sets a Boolean value that determines whether the layer’s textures are used only for rendering.
|
||||
//
|
||||
// https://developer.apple.com/documentation/quartzcore/cametallayer/1478168-framebufferonly
|
||||
func (ml MetalLayer) SetFramebufferOnly(framebufferOnly bool) {
|
||||
switch framebufferOnly {
|
||||
case true:
|
||||
C.MetalLayer_SetFramebufferOnly(ml.metalLayer, 1)
|
||||
case false:
|
||||
C.MetalLayer_SetFramebufferOnly(ml.metalLayer, 0)
|
||||
}
|
||||
ml.metalLayer.Send(objc.RegisterName("setFramebufferOnly:"), framebufferOnly)
|
||||
}
|
||||
|
||||
// MetalDrawable is a displayable resource that can be rendered or written to by Metal.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametaldrawable.
|
||||
type MetalDrawable struct {
|
||||
metalDrawable unsafe.Pointer
|
||||
metalDrawable objc.ID
|
||||
}
|
||||
|
||||
// Drawable implements the mtl.Drawable interface.
|
||||
func (md MetalDrawable) Drawable() unsafe.Pointer { return md.metalDrawable }
|
||||
func (md MetalDrawable) Drawable() unsafe.Pointer {
|
||||
return *(*unsafe.Pointer)(unsafe.Pointer(&md.metalDrawable))
|
||||
}
|
||||
|
||||
// Texture returns a Metal texture object representing the drawable object's content.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/quartzcore/cametaldrawable/1478159-texture.
|
||||
func (md MetalDrawable) Texture() mtl.Texture {
|
||||
return mtl.NewTexture(C.MetalDrawable_Texture(md.metalDrawable))
|
||||
return mtl.NewTexture(md.metalDrawable.Send(objc.RegisterName("texture")))
|
||||
}
|
||||
|
||||
// Present presents the drawable onscreen as soon as possible.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldrawable/1470284-present.
|
||||
func (md MetalDrawable) Present() {
|
||||
C.MetalDrawable_Present(md.metalDrawable)
|
||||
md.metalDrawable.Send(objc.RegisterName("present"))
|
||||
}
|
||||
|
@ -1,37 +0,0 @@
|
||||
// Copyright 2018 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned long uint_t;
|
||||
|
||||
void *MakeMetalLayer();
|
||||
|
||||
uint16_t MetalLayer_PixelFormat(void *metalLayer);
|
||||
void MetalLayer_SetDevice(void *metalLayer, void *device);
|
||||
void MetalLayer_SetOpaque(void *metalLayer, unsigned char opaque);
|
||||
const char *MetalLayer_SetPixelFormat(void *metalLayer, uint16_t pixelFormat);
|
||||
const char *MetalLayer_SetMaximumDrawableCount(void *metalLayer,
|
||||
uint_t maximumDrawableCount);
|
||||
void MetalLayer_SetDisplaySyncEnabled(void *metalLayer,
|
||||
uint8_t displaySyncEnabled);
|
||||
void MetalLayer_SetDrawableSize(void *metalLayer, double width, double height);
|
||||
void MetalLayer_SetPresentsWithTransaction(void *metalLayer,
|
||||
uint8_t presentsWithTransaction);
|
||||
void *MetalLayer_NextDrawable(void *metalLayer);
|
||||
void MetalLayer_SetFramebufferOnly(void *metalLayer, uint8_t framebufferOnly);
|
||||
uint8_t MetalLayer_PresentsWithTransaction(void *metalLayer);
|
||||
|
||||
void *MetalDrawable_Texture(void *drawable);
|
||||
void MetalDrawable_Present(void *drawable);
|
@ -1,116 +0,0 @@
|
||||
// Copyright 2018 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ca_darwin.h"
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
void *MakeMetalLayer() {
|
||||
CAMetalLayer *layer = [[CAMetalLayer alloc] init];
|
||||
// TODO: Expose a function to set color space.
|
||||
// TODO: Enable colorspace on iOS: this will be available as of iOS 13.0.
|
||||
#if !TARGET_OS_IPHONE
|
||||
CGColorSpaceRef colorspace =
|
||||
CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);
|
||||
layer.colorspace = colorspace;
|
||||
CGColorSpaceRelease(colorspace);
|
||||
#endif
|
||||
return layer;
|
||||
}
|
||||
|
||||
uint16_t MetalLayer_PixelFormat(void *metalLayer) {
|
||||
return ((CAMetalLayer *)metalLayer).pixelFormat;
|
||||
}
|
||||
|
||||
void MetalLayer_SetDevice(void *metalLayer, void *device) {
|
||||
((CAMetalLayer *)metalLayer).device = (id<MTLDevice>)device;
|
||||
}
|
||||
|
||||
void MetalLayer_SetOpaque(void *metalLayer, unsigned char opaque) {
|
||||
((CAMetalLayer *)metalLayer).opaque = (BOOL)opaque;
|
||||
}
|
||||
|
||||
const char *MetalLayer_SetPixelFormat(void *metalLayer, uint16_t pixelFormat) {
|
||||
@try {
|
||||
((CAMetalLayer *)metalLayer).pixelFormat = (MTLPixelFormat)pixelFormat;
|
||||
} @catch (NSException *exception) {
|
||||
return exception.reason.UTF8String;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *MetalLayer_SetMaximumDrawableCount(void *metalLayer,
|
||||
uint_t maximumDrawableCount) {
|
||||
// @available syntax is not available for old Xcode (#781)
|
||||
//
|
||||
// If possible, we'd want to write the guard like:
|
||||
//
|
||||
// if (@available(macOS 10.13.2, *)) { ...
|
||||
|
||||
@try {
|
||||
if ([(CAMetalLayer *)metalLayer
|
||||
respondsToSelector:@selector(setMaximumDrawableCount:)]) {
|
||||
[((CAMetalLayer *)metalLayer)
|
||||
setMaximumDrawableCount:(NSUInteger)maximumDrawableCount];
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
return exception.reason.UTF8String;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MetalLayer_SetDisplaySyncEnabled(void *metalLayer,
|
||||
uint8_t displaySyncEnabled) {
|
||||
// @available syntax is not available for old Xcode (#781)
|
||||
//
|
||||
// If possible, we'd want to write the guard like:
|
||||
//
|
||||
// if (@available(macOS 10.13, *)) { ...
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
if ([(CAMetalLayer *)metalLayer
|
||||
respondsToSelector:@selector(setDisplaySyncEnabled:)]) {
|
||||
[((CAMetalLayer *)metalLayer) setDisplaySyncEnabled:displaySyncEnabled];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MetalLayer_SetDrawableSize(void *metalLayer, double width, double height) {
|
||||
((CAMetalLayer *)metalLayer).drawableSize = (CGSize){width, height};
|
||||
}
|
||||
|
||||
void MetalLayer_SetPresentsWithTransaction(void *metalLayer,
|
||||
uint8_t presentsWithTransaction) {
|
||||
[((CAMetalLayer *)metalLayer)
|
||||
setPresentsWithTransaction:presentsWithTransaction];
|
||||
}
|
||||
|
||||
void *MetalLayer_NextDrawable(void *metalLayer) {
|
||||
return [(CAMetalLayer *)metalLayer nextDrawable];
|
||||
}
|
||||
|
||||
void *MetalDrawable_Texture(void *metalDrawable) {
|
||||
return ((id<CAMetalDrawable>)metalDrawable).texture;
|
||||
}
|
||||
|
||||
void MetalDrawable_Present(void *metalDrawable) {
|
||||
[((id<CAMetalDrawable>)metalDrawable) present];
|
||||
}
|
||||
|
||||
void MetalLayer_SetFramebufferOnly(void *metalLayer, uint8_t framebufferOnly) {
|
||||
[((CAMetalLayer *)metalLayer) setFramebufferOnly:framebufferOnly];
|
||||
}
|
||||
|
||||
uint8_t MetalLayer_PresentsWithTransaction(void *metalLayer) {
|
||||
return [((CAMetalLayer *)metalLayer) presentsWithTransaction];
|
||||
}
|
@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/cocoa"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/ca"
|
||||
@ -28,21 +29,6 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/shaderir"
|
||||
)
|
||||
|
||||
// #cgo CFLAGS: -x objective-c
|
||||
// #cgo !ios CFLAGS: -mmacosx-version-min=10.12
|
||||
// #cgo LDFLAGS: -framework Foundation
|
||||
//
|
||||
// #import <Foundation/Foundation.h>
|
||||
//
|
||||
// static void* allocAutoreleasePool() {
|
||||
// return [[NSAutoreleasePool alloc] init];
|
||||
// }
|
||||
//
|
||||
// static void releaseAutoreleasePool(void* pool) {
|
||||
// [(NSAutoreleasePool*)pool release];
|
||||
// }
|
||||
import "C"
|
||||
|
||||
const source = `#include <metal_stdlib>
|
||||
|
||||
#define FILTER_NEAREST {{.FilterNearest}}
|
||||
@ -332,7 +318,7 @@ type Graphics struct {
|
||||
maxImageSize int
|
||||
tmpTextures []mtl.Texture
|
||||
|
||||
pool unsafe.Pointer
|
||||
pool cocoa.NSAutoreleasePool
|
||||
}
|
||||
|
||||
type stencilMode int
|
||||
@ -367,15 +353,15 @@ func NewGraphics() (graphicsdriver.Graphics, error) {
|
||||
func (g *Graphics) Begin() error {
|
||||
// NSAutoreleasePool is required to release drawable correctly (#847).
|
||||
// https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/Drawables.html
|
||||
g.pool = C.allocAutoreleasePool()
|
||||
g.pool = cocoa.NSAutoreleasePool_new()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Graphics) End(present bool) error {
|
||||
g.flushIfNeeded(present)
|
||||
g.screenDrawable = ca.MetalDrawable{}
|
||||
C.releaseAutoreleasePool(g.pool)
|
||||
g.pool = nil
|
||||
g.pool.Release()
|
||||
g.pool.ID = 0
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -23,11 +23,21 @@ import (
|
||||
"os"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ebitengine/purego"
|
||||
"golang.org/x/image/math/f32"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/mtl"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// for these tests to pass Metal must be linked directly.
|
||||
// it is not needed for any of the others nor for Ebitengine to work properly.
|
||||
//go:cgo_import_dynamic _ _ "Metal.framework/Metal"
|
||||
|
||||
// It is also necessary for CoreGraphics to be linked
|
||||
purego.Dlopen("/System/Library/Frameworks/CoreGraphics.framework/Versions/Current/CoreGraphics", purego.RTLD_GLOBAL)
|
||||
}
|
||||
|
||||
func Example_listDevices() {
|
||||
device, ok := mtl.CreateSystemDefaultDevice()
|
||||
if !ok {
|
||||
|
@ -25,15 +25,14 @@ package mtl
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// #cgo !ios CFLAGS: -mmacosx-version-min=10.12
|
||||
// #cgo LDFLAGS: -framework Metal -framework CoreGraphics -framework Foundation
|
||||
//
|
||||
// #include "mtl_darwin.h"
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
"github.com/ebitengine/purego"
|
||||
"github.com/ebitengine/purego/objc"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/cocoa"
|
||||
)
|
||||
|
||||
// FeatureSet defines a specific platform, hardware, and software configuration.
|
||||
//
|
||||
@ -338,6 +337,11 @@ const (
|
||||
CommandBufferStatusError CommandBufferStatus = 5 // Execution of the command buffer was aborted due to an error during execution.
|
||||
)
|
||||
|
||||
var (
|
||||
metal = purego.Dlopen("Metal.framework/Metal", purego.RTLD_GLOBAL)
|
||||
_MTLCreateSystemDefaultDevice = purego.Dlsym(metal, "MTLCreateSystemDefaultDevice")
|
||||
)
|
||||
|
||||
// Resource represents a memory allocation for storing specialized data
|
||||
// that is accessible to the GPU.
|
||||
//
|
||||
@ -445,7 +449,7 @@ type TextureDescriptor struct {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldevice.
|
||||
type Device struct {
|
||||
device unsafe.Pointer
|
||||
device objc.ID
|
||||
|
||||
// Headless indicates whether a device is configured as headless.
|
||||
Headless bool
|
||||
@ -457,38 +461,133 @@ type Device struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
var (
|
||||
class_MTLRenderPipelineDescriptor = objc.GetClass("MTLRenderPipelineDescriptor")
|
||||
class_MTLTextureDescriptor = objc.GetClass("MTLTextureDescriptor")
|
||||
class_MTLDepthStencilDescriptor = objc.GetClass("MTLDepthStencilDescriptor")
|
||||
class_MTLRenderPassDescriptor = objc.GetClass("MTLRenderPassDescriptor")
|
||||
)
|
||||
|
||||
var (
|
||||
sel_class = objc.RegisterName("class")
|
||||
sel_length = objc.RegisterName("length")
|
||||
sel_isHeadless = objc.RegisterName("isHeadless")
|
||||
sel_isLowPower = objc.RegisterName("isLowPower")
|
||||
sel_name = objc.RegisterName("name")
|
||||
sel_supportsFeatureSet = objc.RegisterName("supportsFeatureSet:")
|
||||
sel_newCommandQueue = objc.RegisterName("newCommandQueue")
|
||||
sel_newLibraryWithSource_options_error = objc.RegisterName("newLibraryWithSource:options:error:")
|
||||
sel_release = objc.RegisterName("release")
|
||||
sel_retain = objc.RegisterName("retain")
|
||||
sel_new = objc.RegisterName("new")
|
||||
sel_localizedDescription = objc.RegisterName("localizedDescription")
|
||||
sel_setVertexFunction = objc.RegisterName("setVertexFunction:")
|
||||
sel_setFragmentFunction = objc.RegisterName("setFragmentFunction:")
|
||||
sel_colorAttachments = objc.RegisterName("colorAttachments")
|
||||
sel_objectAtIndexedSubscript = objc.RegisterName("objectAtIndexedSubscript:")
|
||||
sel_setPixelFormat = objc.RegisterName("setPixelFormat:")
|
||||
sel_setBlendingEnabled = objc.RegisterName("setBlendingEnabled:")
|
||||
sel_setDestinationAlphaBlendFactor = objc.RegisterName("setDestinationAlphaBlendFactor:")
|
||||
sel_setDestinationRGBBlendFactor = objc.RegisterName("setDestinationRGBBlendFactor:")
|
||||
sel_setSourceAlphaBlendFactor = objc.RegisterName("setSourceAlphaBlendFactor:")
|
||||
sel_setSourceRGBBlendFactor = objc.RegisterName("setSourceRGBBlendFactor:")
|
||||
sel_setWriteMask = objc.RegisterName("setWriteMask:")
|
||||
sel_setStencilAttachmentPixelFormat = objc.RegisterName("setStencilAttachmentPixelFormat:")
|
||||
sel_newRenderPipelineStateWithDescriptor_error = objc.RegisterName("newRenderPipelineStateWithDescriptor:error:")
|
||||
sel_newBufferWithBytes_length_options = objc.RegisterName("newBufferWithBytes:length:options:")
|
||||
sel_newBufferWithLength_options = objc.RegisterName("newBufferWithLength:options:")
|
||||
sel_setTextureType = objc.RegisterName("setTextureType:")
|
||||
sel_didModifyRange = objc.RegisterName("didModifyRange:")
|
||||
sel_setWidth = objc.RegisterName("setWidth:")
|
||||
sel_setHeight = objc.RegisterName("setHeight:")
|
||||
sel_width = objc.RegisterName("width")
|
||||
sel_height = objc.RegisterName("height")
|
||||
sel_contents = objc.RegisterName("contents")
|
||||
sel_setStorageMode = objc.RegisterName("setStorageMode:")
|
||||
sel_setUsage = objc.RegisterName("setUsage:")
|
||||
sel_newTextureWithDescriptor = objc.RegisterName("newTextureWithDescriptor:")
|
||||
sel_commandBuffer = objc.RegisterName("commandBuffer")
|
||||
sel_status = objc.RegisterName("status")
|
||||
sel_presentDrawable = objc.RegisterName("presentDrawable:")
|
||||
sel_commit = objc.RegisterName("commit")
|
||||
sel_waitUntilCompleted = objc.RegisterName("waitUntilCompleted")
|
||||
sel_waitUntilScheduled = objc.RegisterName("waitUntilScheduled")
|
||||
sel_renderCommandEncoderWithDescriptor = objc.RegisterName("renderCommandEncoderWithDescriptor:")
|
||||
sel_stencilAttachment = objc.RegisterName("stencilAttachment")
|
||||
sel_setLoadAction = objc.RegisterName("setLoadAction:")
|
||||
sel_setStoreAction = objc.RegisterName("setStoreAction:")
|
||||
sel_setTexture = objc.RegisterName("setTexture:")
|
||||
sel_setClearColor = objc.RegisterName("setClearColor:")
|
||||
sel_blitCommandEncoder = objc.RegisterName("blitCommandEncoder")
|
||||
sel_endEncoding = objc.RegisterName("endEncoding")
|
||||
sel_setRenderPipelineState = objc.RegisterName("setRenderPipelineState:")
|
||||
sel_setViewport = objc.RegisterName("setViewport:")
|
||||
sel_setScissorRect = objc.RegisterName("setScissorRect:")
|
||||
sel_setVertexBuffer_offset_atIndex = objc.RegisterName("setVertexBuffer:offset:atIndex:")
|
||||
sel_setVertexBytes_length_atIndex = objc.RegisterName("setVertexBytes:length:atIndex:")
|
||||
sel_setFragmentBytes_length_atIndex = objc.RegisterName("setFragmentBytes:length:atIndex:")
|
||||
sel_setFragmentTexture_atIndex = objc.RegisterName("setFragmentTexture:atIndex:")
|
||||
sel_setBlendColorRedGreenBlueAlpha = objc.RegisterName("setBlendColorRed:green:blue:alpha:")
|
||||
sel_setDepthStencilState = objc.RegisterName("setDepthStencilState:")
|
||||
sel_drawPrimitives_vertexStart_vertexCount = objc.RegisterName("drawPrimitives:vertexStart:vertexCount:")
|
||||
sel_drawIndexedPrimitives_indexCount_indexType_indexBuffer_indexBufferOffset = objc.RegisterName("drawIndexedPrimitives:indexCount:indexType:indexBuffer:indexBufferOffset:")
|
||||
sel_synchronizeResource = objc.RegisterName("synchronizeResource:")
|
||||
sel_synchronizeTexture_slice_level = objc.RegisterName("synchronizeTexture:slice:level:")
|
||||
sel_copyFromTexture_sourceSlice_sourceLevel_sourceOrigin_sourceSize_toTexture_destinationSlice_destinationLevel_destinationOrigin = objc.RegisterName("copyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toTexture:destinationSlice:destinationLevel:destinationOrigin:")
|
||||
sel_newFunctionWithName = objc.RegisterName("newFunctionWithName:")
|
||||
sel_backFaceStencil = objc.RegisterName("backFaceStencil")
|
||||
sel_frontFaceStencil = objc.RegisterName("frontFaceStencil")
|
||||
sel_setStencilFailureOperation = objc.RegisterName("setStencilFailureOperation:")
|
||||
sel_setDepthFailureOperation = objc.RegisterName("setDepthFailureOperation:")
|
||||
sel_setDepthStencilPassOperation = objc.RegisterName("setDepthStencilPassOperation:")
|
||||
sel_setStencilCompareFunction = objc.RegisterName("setStencilCompareFunction:")
|
||||
sel_newDepthStencilStateWithDescriptor = objc.RegisterName("newDepthStencilStateWithDescriptor:")
|
||||
sel_replaceRegion_mipmapLevel_withBytes_bytesPerRow = objc.RegisterName("replaceRegion:mipmapLevel:withBytes:bytesPerRow:")
|
||||
sel_getBytes_bytesPerRow_fromRegion_mipmapLevel = objc.RegisterName("getBytes:bytesPerRow:fromRegion:mipmapLevel:")
|
||||
)
|
||||
|
||||
// CreateSystemDefaultDevice returns the preferred system default Metal device.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/1433401-mtlcreatesystemdefaultdevice.
|
||||
func CreateSystemDefaultDevice() (Device, bool) {
|
||||
d := C.CreateSystemDefaultDevice()
|
||||
if d.Device == nil {
|
||||
d, _, _ := purego.SyscallN(_MTLCreateSystemDefaultDevice)
|
||||
if d == 0 {
|
||||
return Device{}, false
|
||||
}
|
||||
var (
|
||||
headless bool
|
||||
lowPower bool
|
||||
name string
|
||||
)
|
||||
if !cocoa.IsIOS {
|
||||
headless = int(objc.ID(d).Send(sel_isHeadless)) != 0
|
||||
lowPower = int(objc.ID(d).Send(sel_isLowPower)) != 0
|
||||
}
|
||||
name = cocoa.NSString{ID: objc.ID(d).Send(sel_name)}.String()
|
||||
|
||||
return Device{
|
||||
device: d.Device,
|
||||
Headless: d.Headless != 0,
|
||||
LowPower: d.LowPower != 0,
|
||||
Name: C.GoString(d.Name),
|
||||
device: objc.ID(d),
|
||||
Headless: headless,
|
||||
LowPower: lowPower,
|
||||
Name: name,
|
||||
}, true
|
||||
}
|
||||
|
||||
// Device returns the underlying id<MTLDevice> pointer.
|
||||
func (d Device) Device() unsafe.Pointer { return d.device }
|
||||
func (d Device) Device() unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&d.device)) }
|
||||
|
||||
// SupportsFeatureSet reports whether device d supports feature set fs.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldevice/1433418-supportsfeatureset.
|
||||
func (d Device) SupportsFeatureSet(fs FeatureSet) bool {
|
||||
return C.Device_SupportsFeatureSet(d.device, C.uint16_t(fs)) != 0
|
||||
return d.device.Send(sel_supportsFeatureSet, uintptr(fs)) != 0
|
||||
}
|
||||
|
||||
// MakeCommandQueue creates a serial command submission queue.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldevice/1433388-makecommandqueue.
|
||||
func (d Device) MakeCommandQueue() CommandQueue {
|
||||
return CommandQueue{C.Device_MakeCommandQueue(d.device)}
|
||||
return CommandQueue{d.device.Send(sel_newCommandQueue)}
|
||||
}
|
||||
|
||||
// MakeLibrary creates a new library that contains
|
||||
@ -496,44 +595,47 @@ func (d Device) MakeCommandQueue() CommandQueue {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldevice/1433431-makelibrary.
|
||||
func (d Device) MakeLibrary(source string, opt CompileOptions) (Library, error) {
|
||||
cs := C.CString(source)
|
||||
defer C.free(unsafe.Pointer(cs))
|
||||
|
||||
l := C.Device_MakeLibrary(d.device, cs, C.size_t(len(source)))
|
||||
if l.Library == nil {
|
||||
return Library{}, errors.New(C.GoString(l.Error))
|
||||
var err cocoa.NSError
|
||||
l := d.device.Send(
|
||||
sel_newLibraryWithSource_options_error,
|
||||
cocoa.NSString_alloc().InitWithUTF8String(source).ID,
|
||||
0,
|
||||
unsafe.Pointer(&err),
|
||||
)
|
||||
if l == 0 {
|
||||
return Library{}, errors.New(cocoa.NSString{ID: err.Send(sel_localizedDescription)}.String())
|
||||
}
|
||||
|
||||
return Library{l.Library}, nil
|
||||
return Library{l}, nil
|
||||
}
|
||||
|
||||
// MakeRenderPipelineState creates a render pipeline state object.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldevice/1433369-makerenderpipelinestate.
|
||||
func (d Device) MakeRenderPipelineState(rpd RenderPipelineDescriptor) (RenderPipelineState, error) {
|
||||
blendingEnabled := 0
|
||||
if rpd.ColorAttachments[0].BlendingEnabled {
|
||||
blendingEnabled = 1
|
||||
}
|
||||
c := &rpd.ColorAttachments[0]
|
||||
descriptor := C.struct_RenderPipelineDescriptor{
|
||||
VertexFunction: rpd.VertexFunction.function,
|
||||
FragmentFunction: rpd.FragmentFunction.function,
|
||||
ColorAttachment0PixelFormat: C.uint16_t(c.PixelFormat),
|
||||
ColorAttachment0BlendingEnabled: C.uint8_t(blendingEnabled),
|
||||
ColorAttachment0DestinationAlphaBlendFactor: C.uint8_t(c.DestinationAlphaBlendFactor),
|
||||
ColorAttachment0DestinationRGBBlendFactor: C.uint8_t(c.DestinationRGBBlendFactor),
|
||||
ColorAttachment0SourceAlphaBlendFactor: C.uint8_t(c.SourceAlphaBlendFactor),
|
||||
ColorAttachment0SourceRGBBlendFactor: C.uint8_t(c.SourceRGBBlendFactor),
|
||||
ColorAttachment0WriteMask: C.uint8_t(c.WriteMask),
|
||||
StencilAttachmentPixelFormat: C.uint8_t(rpd.StencilAttachmentPixelFormat),
|
||||
}
|
||||
rps := C.Device_MakeRenderPipelineState(d.device, descriptor)
|
||||
if rps.RenderPipelineState == nil {
|
||||
return RenderPipelineState{}, errors.New(C.GoString(rps.Error))
|
||||
renderPipelineDescriptor := objc.ID(class_MTLRenderPipelineDescriptor).Send(sel_new)
|
||||
renderPipelineDescriptor.Send(sel_setVertexFunction, rpd.VertexFunction.function)
|
||||
renderPipelineDescriptor.Send(sel_setFragmentFunction, rpd.FragmentFunction.function)
|
||||
colorAttachments0 := renderPipelineDescriptor.Send(sel_colorAttachments).Send(sel_objectAtIndexedSubscript, 0)
|
||||
colorAttachments0.Send(sel_setPixelFormat, uintptr(rpd.ColorAttachments[0].PixelFormat))
|
||||
colorAttachments0.Send(sel_setBlendingEnabled, rpd.ColorAttachments[0].BlendingEnabled)
|
||||
colorAttachments0.Send(sel_setDestinationAlphaBlendFactor, uintptr(rpd.ColorAttachments[0].DestinationAlphaBlendFactor))
|
||||
colorAttachments0.Send(sel_setDestinationRGBBlendFactor, uintptr(rpd.ColorAttachments[0].DestinationRGBBlendFactor))
|
||||
colorAttachments0.Send(sel_setSourceAlphaBlendFactor, uintptr(rpd.ColorAttachments[0].SourceAlphaBlendFactor))
|
||||
colorAttachments0.Send(sel_setSourceRGBBlendFactor, uintptr(rpd.ColorAttachments[0].SourceRGBBlendFactor))
|
||||
colorAttachments0.Send(sel_setWriteMask, uintptr(rpd.ColorAttachments[0].WriteMask))
|
||||
renderPipelineDescriptor.Send(sel_setStencilAttachmentPixelFormat, uintptr(rpd.StencilAttachmentPixelFormat))
|
||||
var err cocoa.NSError
|
||||
renderPipelineState := d.device.Send(sel_newRenderPipelineStateWithDescriptor_error,
|
||||
renderPipelineDescriptor,
|
||||
unsafe.Pointer(&err),
|
||||
)
|
||||
renderPipelineDescriptor.Send(sel_release)
|
||||
if renderPipelineState == 0 {
|
||||
return RenderPipelineState{}, errors.New(cocoa.NSString{ID: err.Send(sel_localizedDescription)}.String())
|
||||
}
|
||||
|
||||
return RenderPipelineState{rps.RenderPipelineState}, nil
|
||||
return RenderPipelineState{renderPipelineState}, nil
|
||||
}
|
||||
|
||||
// MakeBufferWithBytes allocates a new buffer of a given length
|
||||
@ -541,14 +643,14 @@ func (d Device) MakeRenderPipelineState(rpd RenderPipelineDescriptor) (RenderPip
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldevice/1433429-makebuffer.
|
||||
func (d Device) MakeBufferWithBytes(bytes unsafe.Pointer, length uintptr, opt ResourceOptions) Buffer {
|
||||
return Buffer{C.Device_MakeBufferWithBytes(d.device, bytes, C.size_t(length), C.uint16_t(opt))}
|
||||
return Buffer{d.device.Send(sel_newBufferWithBytes_length_options, bytes, length, uintptr(opt))}
|
||||
}
|
||||
|
||||
// MakeBufferWithLength allocates a new zero-filled buffer of a given length.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldevice/1433375-newbufferwithlength
|
||||
func (d Device) MakeBufferWithLength(length uintptr, opt ResourceOptions) Buffer {
|
||||
return Buffer{C.Device_MakeBufferWithLength(d.device, C.size_t(length), C.uint16_t(opt))}
|
||||
return Buffer{d.device.Send(sel_newBufferWithLength_options, length, uintptr(opt))}
|
||||
}
|
||||
|
||||
// MakeTexture creates a texture object with privately owned storage
|
||||
@ -556,16 +658,17 @@ func (d Device) MakeBufferWithLength(length uintptr, opt ResourceOptions) Buffer
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldevice/1433425-maketexture.
|
||||
func (d Device) MakeTexture(td TextureDescriptor) Texture {
|
||||
descriptor := C.struct_TextureDescriptor{
|
||||
TextureType: C.uint16_t(td.TextureType),
|
||||
PixelFormat: C.uint16_t(td.PixelFormat),
|
||||
Width: C.uint_t(td.Width),
|
||||
Height: C.uint_t(td.Height),
|
||||
StorageMode: C.uint8_t(td.StorageMode),
|
||||
Usage: C.uint8_t(td.Usage),
|
||||
}
|
||||
textureDescriptor := objc.ID(class_MTLTextureDescriptor).Send(sel_new)
|
||||
textureDescriptor.Send(sel_setTextureType, uintptr(td.TextureType))
|
||||
textureDescriptor.Send(sel_setPixelFormat, uintptr(td.PixelFormat))
|
||||
textureDescriptor.Send(sel_setWidth, uintptr(td.Width))
|
||||
textureDescriptor.Send(sel_setHeight, uintptr(td.Height))
|
||||
textureDescriptor.Send(sel_setStorageMode, uintptr(td.StorageMode))
|
||||
textureDescriptor.Send(sel_setUsage, uintptr(td.Usage))
|
||||
texture := d.device.Send(sel_newTextureWithDescriptor, textureDescriptor)
|
||||
textureDescriptor.Send(sel_release)
|
||||
return Texture{
|
||||
texture: C.Device_MakeTexture(d.device, descriptor),
|
||||
texture: texture,
|
||||
}
|
||||
}
|
||||
|
||||
@ -573,18 +676,21 @@ func (d Device) MakeTexture(td TextureDescriptor) Texture {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldevice/1433412-makedepthstencilstate
|
||||
func (d Device) MakeDepthStencilState(dsd DepthStencilDescriptor) DepthStencilState {
|
||||
descriptor := C.struct_DepthStencilDescriptor{
|
||||
BackFaceStencilStencilFailureOperation: C.uint8_t(dsd.BackFaceStencil.StencilFailureOperation),
|
||||
BackFaceStencilDepthFailureOperation: C.uint8_t(dsd.BackFaceStencil.DepthFailureOperation),
|
||||
BackFaceStencilDepthStencilPassOperation: C.uint8_t(dsd.BackFaceStencil.DepthStencilPassOperation),
|
||||
BackFaceStencilStencilCompareFunction: C.uint8_t(dsd.BackFaceStencil.StencilCompareFunction),
|
||||
FrontFaceStencilStencilFailureOperation: C.uint8_t(dsd.FrontFaceStencil.StencilFailureOperation),
|
||||
FrontFaceStencilDepthFailureOperation: C.uint8_t(dsd.FrontFaceStencil.DepthFailureOperation),
|
||||
FrontFaceStencilDepthStencilPassOperation: C.uint8_t(dsd.FrontFaceStencil.DepthStencilPassOperation),
|
||||
FrontFaceStencilStencilCompareFunction: C.uint8_t(dsd.FrontFaceStencil.StencilCompareFunction),
|
||||
}
|
||||
depthStencilDescriptor := objc.ID(class_MTLDepthStencilDescriptor).Send(sel_new)
|
||||
backFaceStencil := depthStencilDescriptor.Send(sel_backFaceStencil)
|
||||
backFaceStencil.Send(sel_setStencilFailureOperation, uintptr(dsd.BackFaceStencil.StencilFailureOperation))
|
||||
backFaceStencil.Send(sel_setDepthFailureOperation, uintptr(dsd.BackFaceStencil.DepthFailureOperation))
|
||||
backFaceStencil.Send(sel_setDepthStencilPassOperation, uintptr(dsd.BackFaceStencil.DepthStencilPassOperation))
|
||||
backFaceStencil.Send(sel_setStencilCompareFunction, uintptr(dsd.BackFaceStencil.StencilCompareFunction)) //TODO
|
||||
frontFaceStencil := depthStencilDescriptor.Send(sel_frontFaceStencil)
|
||||
frontFaceStencil.Send(sel_setStencilFailureOperation, uintptr(dsd.FrontFaceStencil.StencilFailureOperation))
|
||||
frontFaceStencil.Send(sel_setDepthFailureOperation, uintptr(dsd.FrontFaceStencil.DepthFailureOperation))
|
||||
frontFaceStencil.Send(sel_setDepthStencilPassOperation, uintptr(dsd.FrontFaceStencil.DepthStencilPassOperation))
|
||||
frontFaceStencil.Send(sel_setStencilCompareFunction, uintptr(dsd.FrontFaceStencil.StencilCompareFunction))
|
||||
depthStencilState := d.device.Send(sel_newDepthStencilStateWithDescriptor, depthStencilDescriptor)
|
||||
depthStencilDescriptor.Send(sel_release)
|
||||
return DepthStencilState{
|
||||
depthStencilState: C.Device_MakeDepthStencilState(d.device, descriptor),
|
||||
depthStencilState: depthStencilState,
|
||||
}
|
||||
}
|
||||
|
||||
@ -609,18 +715,18 @@ type Drawable interface {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandqueue.
|
||||
type CommandQueue struct {
|
||||
commandQueue unsafe.Pointer
|
||||
commandQueue objc.ID
|
||||
}
|
||||
|
||||
func (c CommandQueue) Release() {
|
||||
C.CommandQueue_Release(c.commandQueue)
|
||||
func (cq CommandQueue) Release() {
|
||||
cq.commandQueue.Send(sel_release)
|
||||
}
|
||||
|
||||
// MakeCommandBuffer creates a command buffer.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandqueue/1508686-makecommandbuffer.
|
||||
func (cq CommandQueue) MakeCommandBuffer() CommandBuffer {
|
||||
return CommandBuffer{C.CommandQueue_MakeCommandBuffer(cq.commandQueue)}
|
||||
return CommandBuffer{cq.commandQueue.Send(sel_commandBuffer)}
|
||||
}
|
||||
|
||||
// CommandBuffer is a container that stores encoded commands
|
||||
@ -628,50 +734,50 @@ func (cq CommandQueue) MakeCommandBuffer() CommandBuffer {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer.
|
||||
type CommandBuffer struct {
|
||||
commandBuffer unsafe.Pointer
|
||||
commandBuffer objc.ID
|
||||
}
|
||||
|
||||
func (cb CommandBuffer) Retain() {
|
||||
C.CommandBuffer_Retain(cb.commandBuffer)
|
||||
cb.commandBuffer.Send(sel_retain)
|
||||
}
|
||||
|
||||
func (cb CommandBuffer) Release() {
|
||||
C.CommandBuffer_Release(cb.commandBuffer)
|
||||
cb.commandBuffer.Send(sel_release)
|
||||
}
|
||||
|
||||
// Status returns the current stage in the lifetime of the command buffer.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443048-status
|
||||
func (cb CommandBuffer) Status() CommandBufferStatus {
|
||||
return CommandBufferStatus(C.CommandBuffer_Status(cb.commandBuffer))
|
||||
return CommandBufferStatus(cb.commandBuffer.Send(sel_status))
|
||||
}
|
||||
|
||||
// PresentDrawable registers a drawable presentation to occur as soon as possible.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443029-presentdrawable.
|
||||
func (cb CommandBuffer) PresentDrawable(d Drawable) {
|
||||
C.CommandBuffer_PresentDrawable(cb.commandBuffer, d.Drawable())
|
||||
cb.commandBuffer.Send(sel_presentDrawable, d.Drawable())
|
||||
}
|
||||
|
||||
// Commit commits this command buffer for execution as soon as possible.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443003-commit.
|
||||
func (cb CommandBuffer) Commit() {
|
||||
C.CommandBuffer_Commit(cb.commandBuffer)
|
||||
cb.commandBuffer.Send(sel_commit)
|
||||
}
|
||||
|
||||
// WaitUntilCompleted waits for the execution of this command buffer to complete.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443039-waituntilcompleted.
|
||||
func (cb CommandBuffer) WaitUntilCompleted() {
|
||||
C.CommandBuffer_WaitUntilCompleted(cb.commandBuffer)
|
||||
cb.commandBuffer.Send(sel_waitUntilCompleted)
|
||||
}
|
||||
|
||||
// WaitUntilScheduled blocks execution of the current thread until the command buffer is scheduled.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443036-waituntilscheduled.
|
||||
func (cb CommandBuffer) WaitUntilScheduled() {
|
||||
C.CommandBuffer_WaitUntilScheduled(cb.commandBuffer)
|
||||
cb.commandBuffer.Send(sel_waitUntilScheduled)
|
||||
}
|
||||
|
||||
// MakeRenderCommandEncoder creates an encoder object that can
|
||||
@ -679,21 +785,24 @@ func (cb CommandBuffer) WaitUntilScheduled() {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1442999-makerendercommandencoder.
|
||||
func (cb CommandBuffer) MakeRenderCommandEncoder(rpd RenderPassDescriptor) RenderCommandEncoder {
|
||||
descriptor := C.struct_RenderPassDescriptor{
|
||||
ColorAttachment0LoadAction: C.uint8_t(rpd.ColorAttachments[0].LoadAction),
|
||||
ColorAttachment0StoreAction: C.uint8_t(rpd.ColorAttachments[0].StoreAction),
|
||||
ColorAttachment0ClearColor: C.struct_ClearColor{
|
||||
Red: C.double(rpd.ColorAttachments[0].ClearColor.Red),
|
||||
Green: C.double(rpd.ColorAttachments[0].ClearColor.Green),
|
||||
Blue: C.double(rpd.ColorAttachments[0].ClearColor.Blue),
|
||||
Alpha: C.double(rpd.ColorAttachments[0].ClearColor.Alpha),
|
||||
},
|
||||
ColorAttachment0Texture: rpd.ColorAttachments[0].Texture.texture,
|
||||
StencilAttachmentLoadAction: C.uint8_t(rpd.StencilAttachment.LoadAction),
|
||||
StencilAttachmentStoreAction: C.uint8_t(rpd.StencilAttachment.StoreAction),
|
||||
StencilAttachmentTexture: rpd.StencilAttachment.Texture.texture,
|
||||
}
|
||||
return RenderCommandEncoder{CommandEncoder{C.CommandBuffer_MakeRenderCommandEncoder(cb.commandBuffer, descriptor)}}
|
||||
var renderPassDescriptor = objc.ID(class_MTLRenderPassDescriptor).Send(sel_new)
|
||||
var colorAttachments0 = renderPassDescriptor.Send(sel_colorAttachments).Send(sel_objectAtIndexedSubscript, 0)
|
||||
colorAttachments0.Send(sel_setLoadAction, int(rpd.ColorAttachments[0].LoadAction))
|
||||
colorAttachments0.Send(sel_setStoreAction, int(rpd.ColorAttachments[0].StoreAction))
|
||||
colorAttachments0.Send(sel_setTexture, rpd.ColorAttachments[0].Texture.texture)
|
||||
sig := cocoa.NSMethodSignature_instanceMethodSignatureForSelector(colorAttachments0.Send(sel_class), sel_setClearColor)
|
||||
inv := cocoa.NSInvocation_invocationWithMethodSignature(sig)
|
||||
inv.SetTarget(colorAttachments0)
|
||||
inv.SetSelector(sel_setClearColor)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&rpd.ColorAttachments[0].ClearColor), 2)
|
||||
inv.Invoke()
|
||||
var stencilAttachment = renderPassDescriptor.Send(sel_stencilAttachment)
|
||||
stencilAttachment.Send(sel_setLoadAction, int(rpd.StencilAttachment.LoadAction))
|
||||
stencilAttachment.Send(sel_setStoreAction, int(rpd.StencilAttachment.StoreAction))
|
||||
stencilAttachment.Send(sel_setTexture, rpd.StencilAttachment.Texture.texture)
|
||||
var rce = cb.commandBuffer.Send(sel_renderCommandEncoderWithDescriptor, renderPassDescriptor)
|
||||
renderPassDescriptor.Send(sel_release)
|
||||
return RenderCommandEncoder{CommandEncoder{rce}}
|
||||
}
|
||||
|
||||
// MakeBlitCommandEncoder creates an encoder object that can encode
|
||||
@ -701,7 +810,8 @@ func (cb CommandBuffer) MakeRenderCommandEncoder(rpd RenderPassDescriptor) Rende
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandbuffer/1443001-makeblitcommandencoder.
|
||||
func (cb CommandBuffer) MakeBlitCommandEncoder() BlitCommandEncoder {
|
||||
return BlitCommandEncoder{CommandEncoder{C.CommandBuffer_MakeBlitCommandEncoder(cb.commandBuffer)}}
|
||||
ce := cb.commandBuffer.Send(sel_blitCommandEncoder)
|
||||
return BlitCommandEncoder{CommandEncoder{ce}}
|
||||
}
|
||||
|
||||
// CommandEncoder is an encoder that writes sequential GPU commands
|
||||
@ -709,14 +819,14 @@ func (cb CommandBuffer) MakeBlitCommandEncoder() BlitCommandEncoder {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandencoder.
|
||||
type CommandEncoder struct {
|
||||
commandEncoder unsafe.Pointer
|
||||
commandEncoder objc.ID
|
||||
}
|
||||
|
||||
// EndEncoding declares that all command generation from this encoder is completed.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlcommandencoder/1458038-endencoding.
|
||||
func (ce CommandEncoder) EndEncoding() {
|
||||
C.CommandEncoder_EndEncoding(ce.commandEncoder)
|
||||
ce.commandEncoder.Send(sel_endEncoding)
|
||||
}
|
||||
|
||||
// RenderCommandEncoder is an encoder that specifies graphics-rendering commands
|
||||
@ -728,25 +838,33 @@ type RenderCommandEncoder struct {
|
||||
}
|
||||
|
||||
func (rce RenderCommandEncoder) Release() {
|
||||
C.RenderCommandEncoder_Release(rce.commandEncoder)
|
||||
rce.commandEncoder.Send(sel_release)
|
||||
}
|
||||
|
||||
// SetRenderPipelineState sets the current render pipeline state object.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515811-setrenderpipelinestate.
|
||||
func (rce RenderCommandEncoder) SetRenderPipelineState(rps RenderPipelineState) {
|
||||
C.RenderCommandEncoder_SetRenderPipelineState(rce.commandEncoder, rps.renderPipelineState)
|
||||
rce.commandEncoder.Send(sel_setRenderPipelineState, rps.renderPipelineState)
|
||||
}
|
||||
|
||||
func (rce RenderCommandEncoder) SetViewport(viewport Viewport) {
|
||||
C.RenderCommandEncoder_SetViewport(rce.commandEncoder, viewport.c())
|
||||
inv := cocoa.NSInvocation_invocationWithMethodSignature(cocoa.NSMethodSignature_signatureWithObjCTypes("v@:{MTLViewport=dddddd}"))
|
||||
inv.SetTarget(rce.commandEncoder)
|
||||
inv.SetSelector(sel_setViewport)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&viewport), 2)
|
||||
inv.Invoke()
|
||||
}
|
||||
|
||||
// SetScissorRect sets the scissor rectangle for a fragment scissor test.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515583-setscissorrect
|
||||
func (rce RenderCommandEncoder) SetScissorRect(scissorRect ScissorRect) {
|
||||
C.RenderCommandEncoder_SetScissorRect(rce.commandEncoder, scissorRect.c())
|
||||
inv := cocoa.NSInvocation_invocationWithMethodSignature(cocoa.NSMethodSignature_signatureWithObjCTypes("v@:{MTLScissorRect=qqqq}"))
|
||||
inv.SetTarget(rce.commandEncoder)
|
||||
inv.SetSelector(sel_setScissorRect)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&scissorRect), 2)
|
||||
inv.Invoke()
|
||||
}
|
||||
|
||||
// SetVertexBuffer sets a buffer for the vertex shader function at an index
|
||||
@ -754,36 +872,43 @@ func (rce RenderCommandEncoder) SetScissorRect(scissorRect ScissorRect) {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515829-setvertexbuffer.
|
||||
func (rce RenderCommandEncoder) SetVertexBuffer(buf Buffer, offset, index int) {
|
||||
C.RenderCommandEncoder_SetVertexBuffer(rce.commandEncoder, buf.buffer, C.uint_t(offset), C.uint_t(index))
|
||||
rce.commandEncoder.Send(sel_setVertexBuffer_offset_atIndex, buf.buffer, offset, index)
|
||||
}
|
||||
|
||||
// SetVertexBytes sets a block of data for the vertex function.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515846-setvertexbytes.
|
||||
func (rce RenderCommandEncoder) SetVertexBytes(bytes unsafe.Pointer, length uintptr, index int) {
|
||||
C.RenderCommandEncoder_SetVertexBytes(rce.commandEncoder, bytes, C.size_t(length), C.uint_t(index))
|
||||
rce.commandEncoder.Send(sel_setVertexBytes_length_atIndex, bytes, length, index)
|
||||
}
|
||||
|
||||
func (rce RenderCommandEncoder) SetFragmentBytes(bytes unsafe.Pointer, length uintptr, index int) {
|
||||
C.RenderCommandEncoder_SetFragmentBytes(rce.commandEncoder, bytes, C.size_t(length), C.uint_t(index))
|
||||
rce.commandEncoder.Send(sel_setFragmentBytes_length_atIndex, bytes, length, index)
|
||||
}
|
||||
|
||||
// SetFragmentTexture sets a texture for the fragment function at an index in the texture argument table.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515390-setfragmenttexture
|
||||
func (rce RenderCommandEncoder) SetFragmentTexture(texture Texture, index int) {
|
||||
C.RenderCommandEncoder_SetFragmentTexture(rce.commandEncoder, texture.texture, C.uint_t(index))
|
||||
rce.commandEncoder.Send(sel_setFragmentTexture_atIndex, texture.texture, index)
|
||||
}
|
||||
|
||||
func (rce RenderCommandEncoder) SetBlendColor(red, green, blue, alpha float32) {
|
||||
C.RenderCommandEncoder_SetBlendColor(rce.commandEncoder, C.float(red), C.float(green), C.float(blue), C.float(alpha))
|
||||
inv := cocoa.NSInvocation_invocationWithMethodSignature(cocoa.NSMethodSignature_signatureWithObjCTypes("v@:ffff"))
|
||||
inv.SetTarget(rce.commandEncoder)
|
||||
inv.SetSelector(sel_setBlendColorRedGreenBlueAlpha)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&red), 2)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&green), 3)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&blue), 4)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&alpha), 5)
|
||||
inv.Invoke()
|
||||
}
|
||||
|
||||
// SetDepthStencilState sets the depth and stencil test state.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1516119-setdepthstencilstate
|
||||
func (rce RenderCommandEncoder) SetDepthStencilState(depthStencilState DepthStencilState) {
|
||||
C.RenderCommandEncoder_SetDepthStencilState(rce.commandEncoder, depthStencilState.depthStencilState)
|
||||
rce.commandEncoder.Send(sel_setDepthStencilState, depthStencilState.depthStencilState)
|
||||
}
|
||||
|
||||
// DrawPrimitives renders one instance of primitives using vertex data
|
||||
@ -791,14 +916,16 @@ func (rce RenderCommandEncoder) SetDepthStencilState(depthStencilState DepthSten
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1516326-drawprimitives.
|
||||
func (rce RenderCommandEncoder) DrawPrimitives(typ PrimitiveType, vertexStart, vertexCount int) {
|
||||
C.RenderCommandEncoder_DrawPrimitives(rce.commandEncoder, C.uint8_t(typ), C.uint_t(vertexStart), C.uint_t(vertexCount))
|
||||
rce.commandEncoder.Send(sel_drawPrimitives_vertexStart_vertexCount, uintptr(typ), vertexStart, vertexCount)
|
||||
}
|
||||
|
||||
// DrawIndexedPrimitives encodes a command to render one instance of primitives using an index list specified in a buffer.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515542-drawindexedprimitives
|
||||
func (rce RenderCommandEncoder) DrawIndexedPrimitives(typ PrimitiveType, indexCount int, indexType IndexType, indexBuffer Buffer, indexBufferOffset int) {
|
||||
C.RenderCommandEncoder_DrawIndexedPrimitives(rce.commandEncoder, C.uint8_t(typ), C.uint_t(indexCount), C.uint8_t(indexType), indexBuffer.buffer, C.uint_t(indexBufferOffset))
|
||||
rce.commandEncoder.Send(
|
||||
sel_drawIndexedPrimitives_indexCount_indexType_indexBuffer_indexBufferOffset,
|
||||
uintptr(typ), indexCount, uintptr(indexType), indexBuffer.buffer, indexBufferOffset)
|
||||
}
|
||||
|
||||
// BlitCommandEncoder is an encoder that specifies resource copy
|
||||
@ -814,33 +941,52 @@ type BlitCommandEncoder struct {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400775-synchronize.
|
||||
func (bce BlitCommandEncoder) Synchronize(resource Resource) {
|
||||
C.BlitCommandEncoder_Synchronize(bce.commandEncoder, resource.resource())
|
||||
if cocoa.IsIOS {
|
||||
return
|
||||
}
|
||||
bce.commandEncoder.Send(sel_synchronizeResource, resource.resource())
|
||||
}
|
||||
|
||||
func (bce BlitCommandEncoder) SynchronizeTexture(texture Texture, slice int, level int) {
|
||||
C.BlitCommandEncoder_SynchronizeTexture(bce.commandEncoder, texture.texture, C.uint_t(slice), C.uint_t(level))
|
||||
if cocoa.IsIOS {
|
||||
return
|
||||
}
|
||||
bce.commandEncoder.Send(sel_synchronizeTexture_slice_level, texture.texture, slice, level)
|
||||
}
|
||||
|
||||
func (bce BlitCommandEncoder) CopyFromTexture(sourceTexture Texture, sourceSlice int, sourceLevel int, sourceOrigin Origin, sourceSize Size, destinationTexture Texture, destinationSlice int, destinationLevel int, destinationOrigin Origin) {
|
||||
C.BlitCommandEncoder_CopyFromTexture(bce.commandEncoder, sourceTexture.texture, C.uint_t(sourceSlice), C.uint_t(sourceLevel), sourceOrigin.c(), sourceSize.c(), destinationTexture.texture, C.uint_t(destinationSlice), C.uint_t(destinationLevel), destinationOrigin.c())
|
||||
inv := cocoa.NSInvocation_invocationWithMethodSignature(cocoa.NSMethodSignature_signatureWithObjCTypes("v@:@QQ{MTLOrigin=qqq}{MTLSize=qqq}@QQ{MTLOrigin=qqq}"))
|
||||
inv.SetTarget(bce.commandEncoder)
|
||||
inv.SetSelector(sel_copyFromTexture_sourceSlice_sourceLevel_sourceOrigin_sourceSize_toTexture_destinationSlice_destinationLevel_destinationOrigin)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&sourceTexture), 2)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&sourceSlice), 3)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&sourceLevel), 4)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&sourceOrigin), 5)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&sourceSize), 6)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&destinationTexture), 7)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&destinationSlice), 8)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&destinationLevel), 9)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&destinationOrigin), 10)
|
||||
inv.Invoke()
|
||||
}
|
||||
|
||||
// Library is a collection of compiled graphics or compute functions.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtllibrary.
|
||||
type Library struct {
|
||||
library unsafe.Pointer
|
||||
library objc.ID
|
||||
}
|
||||
|
||||
// MakeFunction returns a pre-compiled, non-specialized function.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtllibrary/1515524-makefunction.
|
||||
func (l Library) MakeFunction(name string) (Function, error) {
|
||||
f := C.Library_MakeFunction(l.library, C.CString(name))
|
||||
if f == nil {
|
||||
f := l.library.Send(sel_newFunctionWithName,
|
||||
cocoa.NSString_alloc().InitWithUTF8String(name).ID,
|
||||
)
|
||||
if f == 0 {
|
||||
return Function{}, fmt.Errorf("function %q not found", name)
|
||||
}
|
||||
|
||||
return Function{f}, nil
|
||||
}
|
||||
|
||||
@ -849,19 +995,19 @@ func (l Library) MakeFunction(name string) (Function, error) {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtltexture.
|
||||
type Texture struct {
|
||||
texture unsafe.Pointer
|
||||
texture objc.ID
|
||||
}
|
||||
|
||||
// NewTexture returns a Texture that wraps an existing id<MTLTexture> pointer.
|
||||
func NewTexture(texture unsafe.Pointer) Texture {
|
||||
func NewTexture(texture objc.ID) Texture {
|
||||
return Texture{texture: texture}
|
||||
}
|
||||
|
||||
// resource implements the Resource interface.
|
||||
func (t Texture) resource() unsafe.Pointer { return t.texture }
|
||||
func (t Texture) resource() unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&t.texture)) }
|
||||
|
||||
func (t Texture) Release() {
|
||||
C.Texture_Release(t.texture)
|
||||
t.texture.Send(sel_release)
|
||||
}
|
||||
|
||||
// GetBytes copies a block of pixels from the storage allocation of texture
|
||||
@ -869,30 +1015,42 @@ func (t Texture) Release() {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtltexture/1515751-getbytes.
|
||||
func (t Texture) GetBytes(pixelBytes *byte, bytesPerRow uintptr, region Region, level int) {
|
||||
r := region.c()
|
||||
C.Texture_GetBytes(t.texture, unsafe.Pointer(pixelBytes), C.size_t(bytesPerRow), r, C.uint_t(level))
|
||||
inv := cocoa.NSInvocation_invocationWithMethodSignature(cocoa.NSMethodSignature_signatureWithObjCTypes("v@:^vQ{MTLRegion={MTLOrigin=qqq}{MTLSize=qqq}}Q"))
|
||||
inv.SetTarget(t.texture)
|
||||
inv.SetSelector(sel_getBytes_bytesPerRow_fromRegion_mipmapLevel)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&pixelBytes), 2)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&bytesPerRow), 3)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(®ion), 4)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&level), 5)
|
||||
inv.Invoke()
|
||||
}
|
||||
|
||||
// ReplaceRegion copies a block of pixels from the caller's pointer into the storage allocation for slice 0 of a texture.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtltexture/1515464-replaceregion
|
||||
func (t Texture) ReplaceRegion(region Region, level int, pixelBytes unsafe.Pointer, bytesPerRow int) {
|
||||
r := region.c()
|
||||
C.Texture_ReplaceRegion(t.texture, r, C.uint_t(level), pixelBytes, C.uint_t(bytesPerRow))
|
||||
inv := cocoa.NSInvocation_invocationWithMethodSignature(cocoa.NSMethodSignature_signatureWithObjCTypes("v@:{MTLRegion={MTLOrigin=qqq}{MTLSize=qqq}}Q^vQ"))
|
||||
inv.SetTarget(t.texture)
|
||||
inv.SetSelector(sel_replaceRegion_mipmapLevel_withBytes_bytesPerRow)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(®ion), 2)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&level), 3)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&pixelBytes), 4)
|
||||
inv.SetArgumentAtIndex(unsafe.Pointer(&bytesPerRow), 5)
|
||||
inv.Invoke()
|
||||
}
|
||||
|
||||
// Width is the width of the texture image for the base level mipmap, in pixels.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtltexture/1515339-width
|
||||
func (t Texture) Width() int {
|
||||
return int(C.Texture_Width(t.texture))
|
||||
return int(t.texture.Send(sel_width))
|
||||
}
|
||||
|
||||
// Height is the height of the texture image for the base level mipmap, in pixels.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtltexture/1515938-height
|
||||
func (t Texture) Height() int {
|
||||
return int(C.Texture_Height(t.texture))
|
||||
return int(t.texture.Send(sel_height))
|
||||
}
|
||||
|
||||
// Buffer is a memory allocation for storing unformatted data
|
||||
@ -900,40 +1058,55 @@ func (t Texture) Height() int {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlbuffer.
|
||||
type Buffer struct {
|
||||
buffer unsafe.Pointer
|
||||
buffer objc.ID
|
||||
}
|
||||
|
||||
func (b Buffer) resource() unsafe.Pointer { return b.buffer }
|
||||
func (b Buffer) resource() unsafe.Pointer { return *(*unsafe.Pointer)(unsafe.Pointer(&b.buffer)) }
|
||||
|
||||
func (b Buffer) Length() uintptr {
|
||||
return uintptr(C.Buffer_Length(b.buffer))
|
||||
return uintptr(b.buffer.Send(sel_length))
|
||||
}
|
||||
|
||||
func (b Buffer) CopyToContents(data unsafe.Pointer, lengthInBytes uintptr) {
|
||||
C.Buffer_CopyToContents(b.buffer, data, C.size_t(lengthInBytes))
|
||||
contents := b.buffer.Send(sel_contents)
|
||||
// use unsafe.Slice when ebitengine reaches 1.17
|
||||
var contentSlice []byte
|
||||
contentHeader := (*reflect.SliceHeader)(unsafe.Pointer(&contentSlice))
|
||||
contentHeader.Data = uintptr(contents)
|
||||
contentHeader.Len = int(lengthInBytes)
|
||||
contentHeader.Cap = int(lengthInBytes)
|
||||
var dataSlice []byte
|
||||
dataHeader := (*reflect.SliceHeader)(unsafe.Pointer(&dataSlice))
|
||||
dataHeader.Data = uintptr(data)
|
||||
dataHeader.Len = int(lengthInBytes)
|
||||
dataHeader.Cap = int(lengthInBytes)
|
||||
copy(contentSlice, dataSlice)
|
||||
if !cocoa.IsIOS {
|
||||
b.buffer.Send(sel_didModifyRange, 0, lengthInBytes)
|
||||
}
|
||||
}
|
||||
|
||||
func (b Buffer) Retain() {
|
||||
C.Buffer_Retain(b.buffer)
|
||||
b.buffer.Send(sel_retain)
|
||||
}
|
||||
|
||||
func (b Buffer) Release() {
|
||||
C.Buffer_Release(b.buffer)
|
||||
b.buffer.Send(sel_release)
|
||||
}
|
||||
|
||||
func (b Buffer) Native() unsafe.Pointer {
|
||||
return b.buffer
|
||||
return *(*unsafe.Pointer)(unsafe.Pointer(&b.buffer))
|
||||
}
|
||||
|
||||
// Function represents a programmable graphics or compute function executed by the GPU.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlfunction.
|
||||
type Function struct {
|
||||
function unsafe.Pointer
|
||||
function objc.ID
|
||||
}
|
||||
|
||||
func (f Function) Release() {
|
||||
C.Function_Release(f.function)
|
||||
f.function.Send(sel_release)
|
||||
}
|
||||
|
||||
// RenderPipelineState contains the graphics functions
|
||||
@ -941,11 +1114,11 @@ func (f Function) Release() {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlrenderpipelinestate.
|
||||
type RenderPipelineState struct {
|
||||
renderPipelineState unsafe.Pointer
|
||||
renderPipelineState objc.ID
|
||||
}
|
||||
|
||||
func (r RenderPipelineState) Release() {
|
||||
C.RenderPipelineState_Release(r.renderPipelineState)
|
||||
r.renderPipelineState.Send(sel_release)
|
||||
}
|
||||
|
||||
// Region is a rectangular block of pixels in an image or texture,
|
||||
@ -957,41 +1130,18 @@ type Region struct {
|
||||
Size Size // The size of the block.
|
||||
}
|
||||
|
||||
func (r *Region) c() C.struct_Region {
|
||||
return C.struct_Region{
|
||||
Origin: r.Origin.c(),
|
||||
Size: r.Size.c(),
|
||||
}
|
||||
}
|
||||
|
||||
// Origin represents the location of a pixel in an image or texture relative
|
||||
// to the upper-left corner, whose coordinates are (0, 0).
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlorigin.
|
||||
type Origin struct{ X, Y, Z int }
|
||||
|
||||
func (o *Origin) c() C.struct_Origin {
|
||||
return C.struct_Origin{
|
||||
X: C.uint_t(o.X),
|
||||
Y: C.uint_t(o.Y),
|
||||
Z: C.uint_t(o.Z),
|
||||
}
|
||||
}
|
||||
|
||||
// Size represents the set of dimensions that declare the size of an object,
|
||||
// such as an image, texture, threadgroup, or grid.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlsize.
|
||||
type Size struct{ Width, Height, Depth int }
|
||||
|
||||
func (s *Size) c() C.struct_Size {
|
||||
return C.struct_Size{
|
||||
Width: C.uint_t(s.Width),
|
||||
Height: C.uint_t(s.Height),
|
||||
Depth: C.uint_t(s.Depth),
|
||||
}
|
||||
}
|
||||
|
||||
// RegionMake2D returns a 2D, rectangular region for image or texture data.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/1515675-mtlregionmake2d.
|
||||
@ -1011,17 +1161,6 @@ type Viewport struct {
|
||||
ZFar float64
|
||||
}
|
||||
|
||||
func (v *Viewport) c() C.struct_Viewport {
|
||||
return C.struct_Viewport{
|
||||
OriginX: C.double(v.OriginX),
|
||||
OriginY: C.double(v.OriginY),
|
||||
Width: C.double(v.Width),
|
||||
Height: C.double(v.Height),
|
||||
ZNear: C.double(v.ZNear),
|
||||
ZFar: C.double(v.ZFar),
|
||||
}
|
||||
}
|
||||
|
||||
// ScissorRect represents a rectangle for the scissor fragment test.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtlscissorrect
|
||||
@ -1032,24 +1171,15 @@ type ScissorRect struct {
|
||||
Height int
|
||||
}
|
||||
|
||||
func (s *ScissorRect) c() C.struct_ScissorRect {
|
||||
return C.struct_ScissorRect{
|
||||
X: C.uint_t(s.X),
|
||||
Y: C.uint_t(s.Y),
|
||||
Width: C.uint_t(s.Width),
|
||||
Height: C.uint_t(s.Height),
|
||||
}
|
||||
}
|
||||
|
||||
// DepthStencilState is a depth and stencil state object that specifies the depth and stencil configuration and operations used in a render pass.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/metal/mtldepthstencilstate
|
||||
type DepthStencilState struct {
|
||||
depthStencilState unsafe.Pointer
|
||||
depthStencilState objc.ID
|
||||
}
|
||||
|
||||
func (d DepthStencilState) Release() {
|
||||
C.DepthStencilState_Release(d.depthStencilState)
|
||||
d.depthStencilState.Send(sel_release)
|
||||
}
|
||||
|
||||
// DepthStencilDescriptor is an object that configures new MTLDepthStencilState objects.
|
||||
|
@ -1,218 +0,0 @@
|
||||
// Copyright 2018 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned long uint_t;
|
||||
|
||||
struct Device {
|
||||
void *Device;
|
||||
uint8_t Headless;
|
||||
uint8_t LowPower;
|
||||
uint8_t Removable;
|
||||
uint64_t RegistryID;
|
||||
const char *Name;
|
||||
};
|
||||
|
||||
struct Devices {
|
||||
struct Device *Devices;
|
||||
int Length;
|
||||
};
|
||||
|
||||
struct Library {
|
||||
void *Library;
|
||||
const char *Error;
|
||||
};
|
||||
|
||||
struct RenderPipelineDescriptor {
|
||||
void *VertexFunction;
|
||||
void *FragmentFunction;
|
||||
uint16_t ColorAttachment0PixelFormat;
|
||||
uint8_t ColorAttachment0BlendingEnabled;
|
||||
uint8_t ColorAttachment0DestinationAlphaBlendFactor;
|
||||
uint8_t ColorAttachment0DestinationRGBBlendFactor;
|
||||
uint8_t ColorAttachment0SourceAlphaBlendFactor;
|
||||
uint8_t ColorAttachment0SourceRGBBlendFactor;
|
||||
uint8_t ColorAttachment0WriteMask;
|
||||
uint8_t StencilAttachmentPixelFormat;
|
||||
};
|
||||
|
||||
struct RenderPipelineState {
|
||||
void *RenderPipelineState;
|
||||
const char *Error;
|
||||
};
|
||||
|
||||
struct ClearColor {
|
||||
double Red;
|
||||
double Green;
|
||||
double Blue;
|
||||
double Alpha;
|
||||
};
|
||||
|
||||
struct RenderPassDescriptor {
|
||||
uint8_t ColorAttachment0LoadAction;
|
||||
uint8_t ColorAttachment0StoreAction;
|
||||
struct ClearColor ColorAttachment0ClearColor;
|
||||
void *ColorAttachment0Texture;
|
||||
uint8_t StencilAttachmentLoadAction;
|
||||
uint8_t StencilAttachmentStoreAction;
|
||||
void *StencilAttachmentTexture;
|
||||
};
|
||||
|
||||
struct TextureDescriptor {
|
||||
uint16_t TextureType;
|
||||
uint16_t PixelFormat;
|
||||
uint_t Width;
|
||||
uint_t Height;
|
||||
uint8_t StorageMode;
|
||||
uint8_t Usage;
|
||||
};
|
||||
|
||||
struct Origin {
|
||||
uint_t X;
|
||||
uint_t Y;
|
||||
uint_t Z;
|
||||
};
|
||||
|
||||
struct Size {
|
||||
uint_t Width;
|
||||
uint_t Height;
|
||||
uint_t Depth;
|
||||
};
|
||||
|
||||
struct Region {
|
||||
struct Origin Origin;
|
||||
struct Size Size;
|
||||
};
|
||||
|
||||
struct Viewport {
|
||||
double OriginX;
|
||||
double OriginY;
|
||||
double Width;
|
||||
double Height;
|
||||
double ZNear;
|
||||
double ZFar;
|
||||
};
|
||||
|
||||
struct ScissorRect {
|
||||
uint_t X;
|
||||
uint_t Y;
|
||||
uint_t Width;
|
||||
uint_t Height;
|
||||
};
|
||||
|
||||
struct DepthStencilDescriptor {
|
||||
uint8_t BackFaceStencilStencilFailureOperation;
|
||||
uint8_t BackFaceStencilDepthFailureOperation;
|
||||
uint8_t BackFaceStencilDepthStencilPassOperation;
|
||||
uint8_t BackFaceStencilStencilCompareFunction;
|
||||
uint8_t FrontFaceStencilStencilFailureOperation;
|
||||
uint8_t FrontFaceStencilDepthFailureOperation;
|
||||
uint8_t FrontFaceStencilDepthStencilPassOperation;
|
||||
uint8_t FrontFaceStencilStencilCompareFunction;
|
||||
};
|
||||
|
||||
struct Device CreateSystemDefaultDevice();
|
||||
struct Devices CopyAllDevices();
|
||||
|
||||
uint8_t Device_SupportsFeatureSet(void *device, uint16_t featureSet);
|
||||
void *Device_MakeCommandQueue(void *device);
|
||||
struct Library Device_MakeLibrary(void *device, const char *source,
|
||||
size_t sourceLength);
|
||||
struct RenderPipelineState
|
||||
Device_MakeRenderPipelineState(void *device,
|
||||
struct RenderPipelineDescriptor descriptor);
|
||||
void *Device_MakeBufferWithBytes(void *device, const void *bytes, size_t length,
|
||||
uint16_t options);
|
||||
void *Device_MakeBufferWithLength(void *device, size_t length,
|
||||
uint16_t options);
|
||||
void *Device_MakeTexture(void *device, struct TextureDescriptor descriptor);
|
||||
void *Device_MakeDepthStencilState(void *device,
|
||||
struct DepthStencilDescriptor descriptor);
|
||||
|
||||
void CommandQueue_Release(void *commandQueue);
|
||||
void *CommandQueue_MakeCommandBuffer(void *commandQueue);
|
||||
|
||||
void CommandBuffer_Retain(void *commandBuffer);
|
||||
void CommandBuffer_Release(void *commandBuffer);
|
||||
uint8_t CommandBuffer_Status(void *commandBuffer);
|
||||
void CommandBuffer_PresentDrawable(void *commandBuffer, void *drawable);
|
||||
void CommandBuffer_Commit(void *commandBuffer);
|
||||
void CommandBuffer_WaitUntilCompleted(void *commandBuffer);
|
||||
void CommandBuffer_WaitUntilScheduled(void *commandBuffer);
|
||||
void *
|
||||
CommandBuffer_MakeRenderCommandEncoder(void *commandBuffer,
|
||||
struct RenderPassDescriptor descriptor);
|
||||
void *CommandBuffer_MakeBlitCommandEncoder(void *commandBuffer);
|
||||
|
||||
void CommandEncoder_EndEncoding(void *commandEncoder);
|
||||
|
||||
void RenderCommandEncoder_Release(void *renderCommandEncoder);
|
||||
void RenderCommandEncoder_SetRenderPipelineState(void *renderCommandEncoder,
|
||||
void *renderPipelineState);
|
||||
void RenderCommandEncoder_SetViewport(void *renderCommandEncoder,
|
||||
struct Viewport viewport);
|
||||
void RenderCommandEncoder_SetScissorRect(void *renderCommandEncoder,
|
||||
struct ScissorRect scissorRect);
|
||||
void RenderCommandEncoder_SetVertexBuffer(void *renderCommandEncoder,
|
||||
void *buffer, uint_t offset,
|
||||
uint_t index);
|
||||
void RenderCommandEncoder_SetVertexBytes(void *renderCommandEncoder,
|
||||
const void *bytes, size_t length,
|
||||
uint_t index);
|
||||
void RenderCommandEncoder_SetFragmentBytes(void *renderCommandEncoder,
|
||||
const void *bytes, size_t length,
|
||||
uint_t index);
|
||||
void RenderCommandEncoder_SetBlendColor(void *renderCommandEncoder, float red,
|
||||
float green, float blue, float alpha);
|
||||
void RenderCommandEncoder_SetFragmentTexture(void *renderCommandEncoder,
|
||||
void *texture, uint_t index);
|
||||
void RenderCommandEncoder_SetDepthStencilState(void *renderCommandEncoder,
|
||||
void *depthStencilState);
|
||||
void RenderCommandEncoder_DrawPrimitives(void *renderCommandEncoder,
|
||||
uint8_t primitiveType,
|
||||
uint_t vertexStart,
|
||||
uint_t vertexCount);
|
||||
void RenderCommandEncoder_DrawIndexedPrimitives(
|
||||
void *renderCommandEncoder, uint8_t primitiveType, uint_t indexCount,
|
||||
uint8_t indexType, void *indexBuffer, uint_t indexBufferOffset);
|
||||
|
||||
void BlitCommandEncoder_Synchronize(void *blitCommandEncoder, void *resource);
|
||||
void BlitCommandEncoder_SynchronizeTexture(void *blitCommandEncoder,
|
||||
void *texture, uint_t slice,
|
||||
uint_t level);
|
||||
void BlitCommandEncoder_CopyFromTexture(
|
||||
void *blitCommandEncoder, void *sourceTexture, uint_t sourceSlice,
|
||||
uint_t sourceLevel, struct Origin sourceOrigin, struct Size sourceSize,
|
||||
void *destinationTexture, uint_t destinationSlice, uint_t destinationLevel,
|
||||
struct Origin destinationOrigin);
|
||||
|
||||
void *Library_MakeFunction(void *library, const char *name);
|
||||
|
||||
void Texture_Release(void *texture);
|
||||
void Texture_GetBytes(void *texture, void *pixelBytes, size_t bytesPerRow,
|
||||
struct Region region, uint_t level);
|
||||
void Texture_ReplaceRegion(void *texture, struct Region region, uint_t level,
|
||||
void *pixelBytes, uint_t bytesPerRow);
|
||||
int Texture_Width(void *texture);
|
||||
int Texture_Height(void *texture);
|
||||
|
||||
size_t Buffer_Length(void *buffer);
|
||||
void Buffer_CopyToContents(void *buffer, void *data, size_t lengthInBytes);
|
||||
void Buffer_Retain(void *buffer);
|
||||
void Buffer_Release(void *buffer);
|
||||
void Function_Release(void *function);
|
||||
void RenderPipelineState_Release(void *renderPipelineState);
|
||||
void DepthStencilState_Release(void *depthStencilState);
|
@ -1,439 +0,0 @@
|
||||
// Copyright 2018 The Ebiten Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "mtl_darwin.h"
|
||||
#import <Metal/Metal.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct Device CreateSystemDefaultDevice() {
|
||||
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
|
||||
if (!device) {
|
||||
struct Device d;
|
||||
d.Device = NULL;
|
||||
return d;
|
||||
}
|
||||
|
||||
struct Device d;
|
||||
d.Device = device;
|
||||
#if !TARGET_OS_IPHONE
|
||||
d.Headless = device.headless;
|
||||
d.LowPower = device.lowPower;
|
||||
#else
|
||||
d.Headless = 0;
|
||||
d.LowPower = 0;
|
||||
#endif
|
||||
d.Name = device.name.UTF8String;
|
||||
return d;
|
||||
}
|
||||
|
||||
uint8_t Device_SupportsFeatureSet(void *device, uint16_t featureSet) {
|
||||
return [(id<MTLDevice>)device supportsFeatureSet:featureSet];
|
||||
}
|
||||
|
||||
void *Device_MakeCommandQueue(void *device) {
|
||||
return [(id<MTLDevice>)device newCommandQueue];
|
||||
}
|
||||
|
||||
struct Library Device_MakeLibrary(void *device, const char *source,
|
||||
size_t sourceLength) {
|
||||
NSError *error;
|
||||
id<MTLLibrary> library = [(id<MTLDevice>)device
|
||||
newLibraryWithSource:[[NSString alloc] initWithBytes:source
|
||||
length:sourceLength
|
||||
encoding:NSUTF8StringEncoding]
|
||||
options:NULL
|
||||
error:&error];
|
||||
|
||||
struct Library l;
|
||||
l.Library = library;
|
||||
if (!library) {
|
||||
l.Error = error.localizedDescription.UTF8String;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
struct RenderPipelineState
|
||||
Device_MakeRenderPipelineState(void *device,
|
||||
struct RenderPipelineDescriptor descriptor) {
|
||||
MTLRenderPipelineDescriptor *renderPipelineDescriptor =
|
||||
[[MTLRenderPipelineDescriptor alloc] init];
|
||||
renderPipelineDescriptor.vertexFunction = descriptor.VertexFunction;
|
||||
renderPipelineDescriptor.fragmentFunction = descriptor.FragmentFunction;
|
||||
renderPipelineDescriptor.colorAttachments[0].pixelFormat =
|
||||
descriptor.ColorAttachment0PixelFormat;
|
||||
renderPipelineDescriptor.colorAttachments[0].blendingEnabled =
|
||||
descriptor.ColorAttachment0BlendingEnabled;
|
||||
renderPipelineDescriptor.colorAttachments[0].destinationAlphaBlendFactor =
|
||||
descriptor.ColorAttachment0DestinationAlphaBlendFactor;
|
||||
renderPipelineDescriptor.colorAttachments[0].destinationRGBBlendFactor =
|
||||
descriptor.ColorAttachment0DestinationRGBBlendFactor;
|
||||
renderPipelineDescriptor.colorAttachments[0].sourceAlphaBlendFactor =
|
||||
descriptor.ColorAttachment0SourceAlphaBlendFactor;
|
||||
renderPipelineDescriptor.colorAttachments[0].sourceRGBBlendFactor =
|
||||
descriptor.ColorAttachment0SourceRGBBlendFactor;
|
||||
renderPipelineDescriptor.colorAttachments[0].writeMask =
|
||||
descriptor.ColorAttachment0WriteMask;
|
||||
renderPipelineDescriptor.stencilAttachmentPixelFormat =
|
||||
descriptor.StencilAttachmentPixelFormat;
|
||||
NSError *error;
|
||||
id<MTLRenderPipelineState> renderPipelineState = [(id<MTLDevice>)device
|
||||
newRenderPipelineStateWithDescriptor:renderPipelineDescriptor
|
||||
error:&error];
|
||||
[renderPipelineDescriptor release];
|
||||
struct RenderPipelineState rps;
|
||||
rps.RenderPipelineState = renderPipelineState;
|
||||
if (!renderPipelineState) {
|
||||
rps.Error = error.localizedDescription.UTF8String;
|
||||
}
|
||||
return rps;
|
||||
}
|
||||
|
||||
void *Device_MakeBufferWithBytes(void *device, const void *bytes, size_t length,
|
||||
uint16_t options) {
|
||||
return [(id<MTLDevice>)device newBufferWithBytes:(const void *)bytes
|
||||
length:(NSUInteger)length
|
||||
options:(MTLResourceOptions)options];
|
||||
}
|
||||
|
||||
void *Device_MakeBufferWithLength(void *device, size_t length,
|
||||
uint16_t options) {
|
||||
return
|
||||
[(id<MTLDevice>)device newBufferWithLength:(NSUInteger)length
|
||||
options:(MTLResourceOptions)options];
|
||||
}
|
||||
|
||||
void *Device_MakeTexture(void *device, struct TextureDescriptor descriptor) {
|
||||
MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init];
|
||||
textureDescriptor.textureType = descriptor.TextureType;
|
||||
textureDescriptor.pixelFormat = descriptor.PixelFormat;
|
||||
textureDescriptor.width = descriptor.Width;
|
||||
textureDescriptor.height = descriptor.Height;
|
||||
textureDescriptor.storageMode = descriptor.StorageMode;
|
||||
textureDescriptor.usage = descriptor.Usage;
|
||||
id<MTLTexture> texture =
|
||||
[(id<MTLDevice>)device newTextureWithDescriptor:textureDescriptor];
|
||||
[textureDescriptor release];
|
||||
return texture;
|
||||
}
|
||||
|
||||
void *Device_MakeDepthStencilState(void *device,
|
||||
struct DepthStencilDescriptor descriptor) {
|
||||
MTLDepthStencilDescriptor *depthStencilDescriptor =
|
||||
[[MTLDepthStencilDescriptor alloc] init];
|
||||
depthStencilDescriptor.backFaceStencil.stencilFailureOperation =
|
||||
descriptor.BackFaceStencilStencilFailureOperation;
|
||||
depthStencilDescriptor.backFaceStencil.depthFailureOperation =
|
||||
descriptor.BackFaceStencilDepthFailureOperation;
|
||||
depthStencilDescriptor.backFaceStencil.depthStencilPassOperation =
|
||||
descriptor.BackFaceStencilDepthStencilPassOperation;
|
||||
depthStencilDescriptor.backFaceStencil.stencilCompareFunction =
|
||||
descriptor.BackFaceStencilStencilCompareFunction;
|
||||
depthStencilDescriptor.frontFaceStencil.stencilFailureOperation =
|
||||
descriptor.FrontFaceStencilStencilFailureOperation;
|
||||
depthStencilDescriptor.frontFaceStencil.depthFailureOperation =
|
||||
descriptor.FrontFaceStencilDepthFailureOperation;
|
||||
depthStencilDescriptor.frontFaceStencil.depthStencilPassOperation =
|
||||
descriptor.FrontFaceStencilDepthStencilPassOperation;
|
||||
depthStencilDescriptor.frontFaceStencil.stencilCompareFunction =
|
||||
descriptor.FrontFaceStencilStencilCompareFunction;
|
||||
id<MTLDepthStencilState> depthStencilState = [(id<MTLDevice>)device
|
||||
newDepthStencilStateWithDescriptor:depthStencilDescriptor];
|
||||
[depthStencilDescriptor release];
|
||||
return depthStencilState;
|
||||
}
|
||||
|
||||
void CommandQueue_Release(void *commandQueue) {
|
||||
[(id<MTLCommandQueue>)commandQueue release];
|
||||
}
|
||||
|
||||
void *CommandQueue_MakeCommandBuffer(void *commandQueue) {
|
||||
return [(id<MTLCommandQueue>)commandQueue commandBuffer];
|
||||
}
|
||||
|
||||
void CommandBuffer_Retain(void *commandBuffer) {
|
||||
[(id<MTLCommandBuffer>)commandBuffer retain];
|
||||
}
|
||||
|
||||
void CommandBuffer_Release(void *commandBuffer) {
|
||||
[(id<MTLCommandBuffer>)commandBuffer release];
|
||||
}
|
||||
|
||||
uint8_t CommandBuffer_Status(void *commandBuffer) {
|
||||
return [(id<MTLCommandBuffer>)commandBuffer status];
|
||||
}
|
||||
|
||||
void CommandBuffer_PresentDrawable(void *commandBuffer, void *drawable) {
|
||||
[(id<MTLCommandBuffer>)commandBuffer
|
||||
presentDrawable:(id<MTLDrawable>)drawable];
|
||||
}
|
||||
|
||||
void CommandBuffer_Commit(void *commandBuffer) {
|
||||
[(id<MTLCommandBuffer>)commandBuffer commit];
|
||||
}
|
||||
|
||||
void CommandBuffer_WaitUntilCompleted(void *commandBuffer) {
|
||||
[(id<MTLCommandBuffer>)commandBuffer waitUntilCompleted];
|
||||
}
|
||||
|
||||
void CommandBuffer_WaitUntilScheduled(void *commandBuffer) {
|
||||
[(id<MTLCommandBuffer>)commandBuffer waitUntilScheduled];
|
||||
}
|
||||
|
||||
void *
|
||||
CommandBuffer_MakeRenderCommandEncoder(void *commandBuffer,
|
||||
struct RenderPassDescriptor descriptor) {
|
||||
MTLRenderPassDescriptor *renderPassDescriptor =
|
||||
[[MTLRenderPassDescriptor alloc] init];
|
||||
renderPassDescriptor.colorAttachments[0].loadAction =
|
||||
descriptor.ColorAttachment0LoadAction;
|
||||
renderPassDescriptor.colorAttachments[0].storeAction =
|
||||
descriptor.ColorAttachment0StoreAction;
|
||||
renderPassDescriptor.colorAttachments[0].clearColor =
|
||||
MTLClearColorMake(descriptor.ColorAttachment0ClearColor.Red,
|
||||
descriptor.ColorAttachment0ClearColor.Green,
|
||||
descriptor.ColorAttachment0ClearColor.Blue,
|
||||
descriptor.ColorAttachment0ClearColor.Alpha);
|
||||
renderPassDescriptor.colorAttachments[0].texture =
|
||||
(id<MTLTexture>)descriptor.ColorAttachment0Texture;
|
||||
renderPassDescriptor.stencilAttachment.loadAction =
|
||||
descriptor.StencilAttachmentLoadAction;
|
||||
renderPassDescriptor.stencilAttachment.storeAction =
|
||||
descriptor.StencilAttachmentStoreAction;
|
||||
renderPassDescriptor.stencilAttachment.texture =
|
||||
(id<MTLTexture>)descriptor.StencilAttachmentTexture;
|
||||
id<MTLRenderCommandEncoder> rce = [(id<MTLCommandBuffer>)commandBuffer
|
||||
renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||
[renderPassDescriptor release];
|
||||
return rce;
|
||||
}
|
||||
|
||||
void *CommandBuffer_MakeBlitCommandEncoder(void *commandBuffer) {
|
||||
return [(id<MTLCommandBuffer>)commandBuffer blitCommandEncoder];
|
||||
}
|
||||
|
||||
void CommandEncoder_EndEncoding(void *commandEncoder) {
|
||||
[(id<MTLCommandEncoder>)commandEncoder endEncoding];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_Release(void *renderCommandEncoder) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder release];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetRenderPipelineState(void *renderCommandEncoder,
|
||||
void *renderPipelineState) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
setRenderPipelineState:(id<MTLRenderPipelineState>)renderPipelineState];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetViewport(void *renderCommandEncoder,
|
||||
struct Viewport viewport) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
setViewport:(MTLViewport){
|
||||
.originX = viewport.OriginX,
|
||||
.originY = viewport.OriginY,
|
||||
.width = viewport.Width,
|
||||
.height = viewport.Height,
|
||||
.znear = viewport.ZNear,
|
||||
.zfar = viewport.ZFar,
|
||||
}];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetScissorRect(void *renderCommandEncoder,
|
||||
struct ScissorRect scissorRect) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
setScissorRect:(MTLScissorRect){
|
||||
.x = scissorRect.X,
|
||||
.y = scissorRect.Y,
|
||||
.width = scissorRect.Width,
|
||||
.height = scissorRect.Height,
|
||||
}];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetVertexBuffer(void *renderCommandEncoder,
|
||||
void *buffer, uint_t offset,
|
||||
uint_t index) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
setVertexBuffer:(id<MTLBuffer>)buffer
|
||||
offset:(NSUInteger)offset
|
||||
atIndex:(NSUInteger)index];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetVertexBytes(void *renderCommandEncoder,
|
||||
const void *bytes, size_t length,
|
||||
uint_t index) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
setVertexBytes:bytes
|
||||
length:(NSUInteger)length
|
||||
atIndex:(NSUInteger)index];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetFragmentBytes(void *renderCommandEncoder,
|
||||
const void *bytes, size_t length,
|
||||
uint_t index) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
setFragmentBytes:bytes
|
||||
length:(NSUInteger)length
|
||||
atIndex:(NSUInteger)index];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetFragmentTexture(void *renderCommandEncoder,
|
||||
void *texture, uint_t index) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
setFragmentTexture:(id<MTLTexture>)texture
|
||||
atIndex:(NSUInteger)index];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetBlendColor(void *renderCommandEncoder, float red,
|
||||
float green, float blue, float alpha) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder setBlendColorRed:red
|
||||
green:green
|
||||
blue:blue
|
||||
alpha:alpha];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_SetDepthStencilState(void *renderCommandEncoder,
|
||||
void *depthStencilState) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
setDepthStencilState:(id<MTLDepthStencilState>)depthStencilState];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_DrawPrimitives(void *renderCommandEncoder,
|
||||
uint8_t primitiveType,
|
||||
uint_t vertexStart,
|
||||
uint_t vertexCount) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
drawPrimitives:(MTLPrimitiveType)primitiveType
|
||||
vertexStart:(NSUInteger)vertexStart
|
||||
vertexCount:(NSUInteger)vertexCount];
|
||||
}
|
||||
|
||||
void RenderCommandEncoder_DrawIndexedPrimitives(
|
||||
void *renderCommandEncoder, uint8_t primitiveType, uint_t indexCount,
|
||||
uint8_t indexType, void *indexBuffer, uint_t indexBufferOffset) {
|
||||
[(id<MTLRenderCommandEncoder>)renderCommandEncoder
|
||||
drawIndexedPrimitives:(MTLPrimitiveType)primitiveType
|
||||
indexCount:(NSUInteger)indexCount
|
||||
indexType:(MTLIndexType)indexType
|
||||
indexBuffer:(id<MTLBuffer>)indexBuffer
|
||||
indexBufferOffset:(NSUInteger)indexBufferOffset];
|
||||
}
|
||||
|
||||
void BlitCommandEncoder_Synchronize(void *blitCommandEncoder, void *resource) {
|
||||
#if !TARGET_OS_IPHONE
|
||||
[(id<MTLBlitCommandEncoder>)blitCommandEncoder
|
||||
synchronizeResource:(id<MTLResource>)resource];
|
||||
#endif
|
||||
}
|
||||
|
||||
void BlitCommandEncoder_SynchronizeTexture(void *blitCommandEncoder,
|
||||
void *texture, uint_t slice,
|
||||
uint_t level) {
|
||||
#if !TARGET_OS_IPHONE
|
||||
[(id<MTLBlitCommandEncoder>)blitCommandEncoder
|
||||
synchronizeTexture:(id<MTLTexture>)texture
|
||||
slice:(NSUInteger)slice
|
||||
level:(NSUInteger)level];
|
||||
#endif
|
||||
}
|
||||
|
||||
void BlitCommandEncoder_CopyFromTexture(
|
||||
void *blitCommandEncoder, void *sourceTexture, uint_t sourceSlice,
|
||||
uint_t sourceLevel, struct Origin sourceOrigin, struct Size sourceSize,
|
||||
void *destinationTexture, uint_t destinationSlice, uint_t destinationLevel,
|
||||
struct Origin destinationOrigin) {
|
||||
[(id<MTLBlitCommandEncoder>)blitCommandEncoder
|
||||
copyFromTexture:(id<MTLTexture>)sourceTexture
|
||||
sourceSlice:(NSUInteger)sourceSlice
|
||||
sourceLevel:(NSUInteger)sourceLevel
|
||||
sourceOrigin:(MTLOrigin){.x = sourceOrigin.X,
|
||||
.y = sourceOrigin.Y,
|
||||
.z = sourceOrigin.Z}
|
||||
sourceSize:(MTLSize){.width = sourceSize.Width,
|
||||
.height = sourceSize.Height,
|
||||
.depth = sourceSize.Depth}
|
||||
toTexture:(id<MTLTexture>)destinationTexture
|
||||
destinationSlice:(NSUInteger)destinationSlice
|
||||
destinationLevel:(NSUInteger)destinationLevel
|
||||
destinationOrigin:(MTLOrigin){.x = destinationOrigin.X,
|
||||
.y = destinationOrigin.Y,
|
||||
.z = destinationOrigin.Z}];
|
||||
}
|
||||
|
||||
void *Library_MakeFunction(void *library, const char *name) {
|
||||
return [(id<MTLLibrary>)library
|
||||
newFunctionWithName:[NSString stringWithUTF8String:name]];
|
||||
}
|
||||
|
||||
void Texture_Release(void *texture) { [(id<MTLTexture>)texture release]; }
|
||||
|
||||
void Texture_GetBytes(void *texture, void *pixelBytes, size_t bytesPerRow,
|
||||
struct Region region, uint_t level) {
|
||||
[(id<MTLTexture>)texture getBytes:(void *)pixelBytes
|
||||
bytesPerRow:(NSUInteger)bytesPerRow
|
||||
fromRegion:(MTLRegion) {
|
||||
.origin = {.x = region.Origin.X,
|
||||
.y = region.Origin.Y,
|
||||
.z = region.Origin.Z},
|
||||
.size = {
|
||||
.width = region.Size.Width,
|
||||
.height = region.Size.Height,
|
||||
.depth = region.Size.Depth
|
||||
}
|
||||
}
|
||||
mipmapLevel:(NSUInteger)level];
|
||||
}
|
||||
|
||||
void Texture_ReplaceRegion(void *texture, struct Region region, uint_t level,
|
||||
void *bytes, uint_t bytesPerRow) {
|
||||
[(id<MTLTexture>)texture replaceRegion:(MTLRegion) {
|
||||
.origin = {.x = region.Origin.X,
|
||||
.y = region.Origin.Y,
|
||||
.z = region.Origin.Z},
|
||||
.size = {
|
||||
.width = region.Size.Width,
|
||||
.height = region.Size.Height,
|
||||
.depth = region.Size.Depth
|
||||
}
|
||||
}
|
||||
mipmapLevel:(NSUInteger)level
|
||||
withBytes:bytes
|
||||
bytesPerRow:(NSUInteger)bytesPerRow];
|
||||
}
|
||||
|
||||
int Texture_Width(void *texture) { return [(id<MTLTexture>)texture width]; }
|
||||
|
||||
int Texture_Height(void *texture) { return [(id<MTLTexture>)texture height]; }
|
||||
|
||||
size_t Buffer_Length(void *buffer) { return [(id<MTLBuffer>)buffer length]; }
|
||||
|
||||
void Buffer_CopyToContents(void *buffer, void *data, size_t lengthInBytes) {
|
||||
memcpy(((id<MTLBuffer>)buffer).contents, data, lengthInBytes);
|
||||
#if !TARGET_OS_IPHONE
|
||||
[(id<MTLBuffer>)buffer didModifyRange:NSMakeRange(0, lengthInBytes)];
|
||||
#endif
|
||||
}
|
||||
|
||||
void Buffer_Retain(void *buffer) { [(id<MTLBuffer>)buffer retain]; }
|
||||
|
||||
void Buffer_Release(void *buffer) { [(id<MTLBuffer>)buffer release]; }
|
||||
|
||||
void Function_Release(void *function) { [(id<MTLFunction>)function release]; }
|
||||
|
||||
void RenderPipelineState_Release(void *renderPipelineState) {
|
||||
[(id<MTLRenderPipelineState>)renderPipelineState release];
|
||||
}
|
||||
|
||||
void DepthStencilState_Release(void *depthStencilState) {
|
||||
[(id<MTLDepthStencilState>)depthStencilState release];
|
||||
}
|
@ -20,16 +20,10 @@
|
||||
package ns
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/ebitengine/purego/objc"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/ca"
|
||||
)
|
||||
|
||||
// #cgo !ios CFLAGS: -mmacosx-version-min=10.12
|
||||
//
|
||||
// #include "ns_darwin.h"
|
||||
import "C"
|
||||
|
||||
// Window is a window that an app displays on the screen.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/appkit/nswindow.
|
||||
@ -47,37 +41,33 @@ func NewWindow(window uintptr) Window {
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/appkit/nswindow/1419160-contentview.
|
||||
func (w Window) ContentView() View {
|
||||
return View{C.Window_ContentView(C.uintptr_t(w.window))}
|
||||
return View{objc.ID(w.window).Send(objc.RegisterName("contentView"))}
|
||||
}
|
||||
|
||||
// View is the infrastructure for drawing, printing, and handling events in an app.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/appkit/nsview.
|
||||
type View struct {
|
||||
view unsafe.Pointer
|
||||
view objc.ID
|
||||
}
|
||||
|
||||
// SetLayer sets v.layer to l.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/appkit/nsview/1483298-layer.
|
||||
func (v View) SetLayer(l ca.Layer) {
|
||||
C.View_SetLayer(v.view, l.Layer())
|
||||
v.view.Send(objc.RegisterName("setLayer:"), uintptr(l.Layer()))
|
||||
}
|
||||
|
||||
// SetWantsLayer sets v.wantsLayer to wantsLayer.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/appkit/nsview/1483695-wantslayer.
|
||||
func (v View) SetWantsLayer(wantsLayer bool) {
|
||||
if wantsLayer {
|
||||
C.View_SetWantsLayer(v.view, 1)
|
||||
} else {
|
||||
C.View_SetWantsLayer(v.view, 0)
|
||||
}
|
||||
v.view.Send(objc.RegisterName("setWantsLayer:"), wantsLayer)
|
||||
}
|
||||
|
||||
// IsInFullScreenMode returns a boolean value indicating whether the view is in full screen mode.
|
||||
//
|
||||
// Reference: https://developer.apple.com/documentation/appkit/nsview/1483337-infullscreenmode.
|
||||
func (v View) IsInFullScreenMode() bool {
|
||||
return C.View_IsInFullScreenMode(v.view) != 0
|
||||
return v.view.Send(objc.RegisterName("isInFullScreenMode")) != 0
|
||||
}
|
||||
|
@ -17,8 +17,11 @@
|
||||
|
||||
package metal
|
||||
|
||||
// #cgo CFLAGS: -x objective-c
|
||||
// #cgo LDFLAGS: -framework UIKit
|
||||
// Suppress the warnings about availability guard with -Wno-unguarded-availability-new.
|
||||
// It is because old Xcode (8 or older?) does not accept @available syntax.
|
||||
|
||||
// #cgo CFLAGS: -Wno-unguarded-availability-new -x objective-c
|
||||
// #cgo LDFLAGS: -framework UIKit -framework QuartzCore -framework Foundation -framework CoreGraphics
|
||||
//
|
||||
// #import <UIKit/UIKit.h>
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user