mlx_init.swift
1 2 import Cocoa 3 import Metal 4 import mlx_window 5 import mlx_image 6 7 8 func _mlx_bridge<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer? { 9 return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque()) 10 } 11 12 func _mlx_bridge<T : AnyObject>(ptr : UnsafeRawPointer) -> T { 13 return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue() 14 } 15 16 17 18 public class MlxMain { 19 20 public var winList = [MlxWin]() 21 public var imgList = [MlxImg]() 22 var myMlxApp:NSApplication? 23 public var device:MTLDevice! 24 var loopHook:UnsafeMutableRawPointer? 25 var loopParam:UnsafeMutableRawPointer 26 var loopHookTimer:CFRunLoopTimer? 27 public var inLoop = false 28 29 public init(_ flag:Int = 0) 30 { 31 /// make app with top menubar 32 myMlxApp = NSApplication.shared 33 if (flag == 1) 34 { 35 NSApp.setActivationPolicy(NSApplication.ActivationPolicy.prohibited) /// for non clickable win, no top menu 36 } 37 else 38 { 39 NSApp.setActivationPolicy(NSApplication.ActivationPolicy.regular) 40 } 41 42 device = MTLCreateSystemDefaultDevice()! 43 loopParam = UnsafeMutableRawPointer(bitPattern:1)! /// set to 1-1 44 loopParam -= 1 45 46 /// Add observer anyway to flush pixels every loop. If loop_hook exists, call it. 47 var ocontext = CFRunLoopObserverContext(version:0, info:_mlx_bridge(obj:self), retain:nil, release:nil, copyDescription:nil) 48 let observer = CFRunLoopObserverCreate(kCFAllocatorDefault, CFRunLoopActivity.beforeWaiting.rawValue, true, 0, createOCallback(), &ocontext) 49 CFRunLoopAddObserver(CFRunLoopGetMain(), observer, CFRunLoopMode.commonModes) 50 51 } 52 53 public func addWinToList(_ win:MlxWin) 54 { winList.append(win) } 55 public func addImgToList(_ img:MlxImg) 56 { imgList.append(img) } 57 58 59 func doCallLoopHook() 60 { 61 /// if (loopHook != nil) 62 /// { 63 _ = (unsafeBitCast(loopHook!,to:(@convention(c)(UnsafeRawPointer)->Void).self))(loopParam) 64 /// } 65 } 66 67 func createOCallback() -> CFRunLoopObserverCallBack 68 { 69 return { (cfRunloopObserver, cfrunloopactivity, info) -> Void in 70 let mlx:MlxMain = _mlx_bridge(ptr:info!) 71 mlx.winList.forEach { $0.flushImages() } 72 /// mlx.doCallLoopHook() 73 } 74 } 75 76 func createTCallback() -> CFRunLoopTimerCallBack 77 { 78 return { (cfRunloopTimer, info) -> Void in 79 let mlx:MlxMain = _mlx_bridge(ptr:info!) 80 mlx.doCallLoopHook() 81 } 82 } 83 84 public func addLoopHook(_ f:UnsafeMutableRawPointer?, _ p:UnsafeMutableRawPointer) 85 { 86 var tcontext = CFRunLoopTimerContext(version:0, info:_mlx_bridge(obj:self), retain:nil, release:nil, copyDescription:nil) 87 if (loopHook != nil) 88 { 89 CFRunLoopTimerInvalidate(loopHookTimer) 90 } 91 92 loopHook = f 93 loopParam = p 94 if (loopHook != nil) 95 { 96 loopHookTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, 0.0, 0.0001, 0, 0, createTCallback(), &tcontext) 97 CFRunLoopAddTimer(CFRunLoopGetMain(), loopHookTimer, CFRunLoopMode.commonModes) 98 } 99 } 100 101 }