Skip to content

Commit

Permalink
internal/cocoa: bring back NSInvocation for CopyFromTexture (#3136)
Browse files Browse the repository at this point in the history
This is a partial revert of c3ea539 but keeps the change for removal of NSInvocation in SetScissorRect, GetBytes,
and ReplaceRegion.

Closes #3135
  • Loading branch information
TotallyGamerJet authored Oct 19, 2024
1 parent 646f340 commit 6452cbc
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 27 deletions.
105 changes: 82 additions & 23 deletions internal/cocoa/api_cocoa_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,37 +21,50 @@ import (
)

var (
class_NSInvocation = objc.GetClass("NSInvocation")
class_NSMethodSignature = objc.GetClass("NSMethodSignature")
class_NSAutoreleasePool = objc.GetClass("NSAutoreleasePool")
class_NSString = objc.GetClass("NSString")
class_NSProcessInfo = objc.GetClass("NSProcessInfo")
class_NSColor = objc.GetClass("NSColor")
class_NSWindow = objc.GetClass("NSWindow")
class_NSView = objc.GetClass("NSView")
class_NSScreen = objc.GetClass("NSScreen")
)

var (
sel_alloc = objc.RegisterName("alloc")
sel_new = objc.RegisterName("new")
sel_release = objc.RegisterName("release")
sel_initWithUTF8String = objc.RegisterName("initWithUTF8String:")
sel_UTF8String = objc.RegisterName("UTF8String")
sel_length = objc.RegisterName("length")
sel_processInfo = objc.RegisterName("processInfo")
sel_frame = objc.RegisterName("frame")
sel_contentView = objc.RegisterName("contentView")
sel_setBackgroundColor = objc.RegisterName("setBackgroundColor:")
sel_colorWithSRGBRedGreenBlueAlpha = objc.RegisterName("colorWithSRGBRed:green:blue:alpha:")
sel_setFrameSize = objc.RegisterName("setFrameSize:")
sel_object = objc.RegisterName("object")
sel_styleMask = objc.RegisterName("styleMask")
sel_setStyleMask = objc.RegisterName("setStyleMask:")
sel_mainScreen = objc.RegisterName("mainScreen")
sel_screen = objc.RegisterName("screen")
sel_isVisible = objc.RegisterName("isVisible")
sel_deviceDescription = objc.RegisterName("deviceDescription")
sel_objectForKey = objc.RegisterName("objectForKey:")
sel_unsignedIntValue = objc.RegisterName("unsignedIntValue")
sel_setLayer = objc.RegisterName("setLayer:")
sel_setWantsLayer = objc.RegisterName("setWantsLayer:")
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_invokeWithTarget = objc.RegisterName("invokeWithTarget:")
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")
sel_processInfo = objc.RegisterName("processInfo")
sel_frame = objc.RegisterName("frame")
sel_contentView = objc.RegisterName("contentView")
sel_setBackgroundColor = objc.RegisterName("setBackgroundColor:")
sel_colorWithSRGBRedGreenBlueAlpha = objc.RegisterName("colorWithSRGBRed:green:blue:alpha:")
sel_setFrameSize = objc.RegisterName("setFrameSize:")
sel_object = objc.RegisterName("object")
sel_styleMask = objc.RegisterName("styleMask")
sel_setStyleMask = objc.RegisterName("setStyleMask:")
sel_mainScreen = objc.RegisterName("mainScreen")
sel_screen = objc.RegisterName("screen")
sel_isVisible = objc.RegisterName("isVisible")
sel_deviceDescription = objc.RegisterName("deviceDescription")
sel_objectForKey = objc.RegisterName("objectForKey:")
sel_unsignedIntValue = objc.RegisterName("unsignedIntValue")
sel_setLayer = objc.RegisterName("setLayer:")
sel_setWantsLayer = objc.RegisterName("setWantsLayer:")
)

const (
Expand Down Expand Up @@ -163,6 +176,52 @@ func (v NSView) SetWantsLayer(wantsLayer bool) {
v.Send(sel_setWantsLayer, wantsLayer)
}

// 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 (i NSInvocation) SetSelector(cmd objc.SEL) {
i.Send(sel_setSelector, cmd)
}

func (i NSInvocation) SetTarget(target objc.ID) {
i.Send(sel_setTarget, target)
}

func (i NSInvocation) SetArgumentAtIndex(arg unsafe.Pointer, idx int) {
i.Send(sel_setArgumentAtIndex, arg, idx)
}

func (i NSInvocation) GetReturnValue(ret unsafe.Pointer) {
i.Send(sel_getReturnValue, ret)
}

func (i NSInvocation) Invoke() {
i.Send(sel_invoke)
}

func (i NSInvocation) InvokeWithTarget(target objc.ID) {
i.Send(sel_invokeWithTarget, target)
}

type NSMethodSignature struct {
objc.ID
}

// 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
}
Expand Down
18 changes: 14 additions & 4 deletions internal/graphicsdriver/metal/mtl/mtl_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -1003,10 +1003,20 @@ func (bce BlitCommandEncoder) SynchronizeTexture(texture Texture, slice int, lev
//
// Reference: https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400754-copyfromtexture?language=objc.
func (bce BlitCommandEncoder) CopyFromTexture(sourceTexture Texture, sourceSlice int, sourceLevel int, sourceOrigin Origin, sourceSize Size, destinationTexture Texture, destinationSlice int, destinationLevel int, destinationOrigin Origin) {
sel := sel_copyFromTexture_sourceSlice_sourceLevel_sourceOrigin_sourceSize_toTexture_destinationSlice_destinationLevel_destinationOrigin
bce.commandEncoder.Send(sel,
sourceTexture.texture, sourceSlice, sourceLevel, sourceOrigin, sourceSize,
destinationTexture.texture, destinationSlice, destinationLevel, destinationOrigin)
// copyFromTexture requires so many arguments that Send doesn't work (#3135).
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.
Expand Down

0 comments on commit 6452cbc

Please sign in to comment.