Post

Replies

Boosts

Views

Activity

Reply to Core Image drawing corruption
@FrankSchlegel wow thank you, I added the ROI callback (simply returning the images full extent) and the top image doesn't look corrupted anymore. I'm so confused as to why the default behavior is any different when an ROI callback is not specified, wow. Still not the end of the story though, when drawing large with interpolation disabled (NSImageInterpolationNone and kCAFilterNearest), the top image is doing something odd, new video here -> http://tclementdev.com/coreimage_metal_test2.mov
Jul ’23
Reply to Core Image drawing corruption
I've done some further experiments: if I set the CGImage (obtained from the CIImage) directly onto the contents property of the layer of my view, then it works and display fine. But if I implement drawRect() and draw the CGImage into the CGContext using CGContextDrawImage() then it appears corrupted. How weird is that?
Jul ’23
Reply to NWConnection send buffer and when to send more data
Using a method like this to handle input is roughly the same as calling connection.receive(minimumIncompleteLength: 1, maximumLength: 1000), is there a reason you are not parsing out the length of your frame from the packet header? Hi Matt, in my app I do parse the length from the packet header. This is a reduced sample code, the simplest possible that demonstrates the problem. I added a protocol framer that basically does nothing (just passing the data along), and it changed the behavior of the writer, which seems wrong to me. About your code, you need to remove these three lines: if error == nil { startReceive(on: connection) } Because the whole point is to see what happens when the other side does not read (or rather does not read fast enough). If you remove these three lines, you will see that the sender keeps enqueuing indefinitely into memory explosion.
Sep ’21
Reply to NWConnection send buffer and when to send more data
Ok Quinn. I made further testing and the problem seems related to me using a protocol framer. Give it a try and let me know what you think. import Foundation import Network class MyProtocol: NWProtocolFramerImplementation { // Create a global definition of your game protocol to add to connections. static let definition = NWProtocolFramer.Definition(implementation: MyProtocol.self) // Set a name for your protocol for use in debugging. static var label: String { return "MyProtocol" } // Set the default behavior for most framing protocol functions. required init(framer: NWProtocolFramer.Instance) { } func start(framer: NWProtocolFramer.Instance) -> NWProtocolFramer.StartResult { return .ready } func wakeup(framer: NWProtocolFramer.Instance) { } func stop(framer: NWProtocolFramer.Instance) -> Bool { return true } func cleanup(framer: NWProtocolFramer.Instance) { } // Whenever the application sends a message, add your protocol header and forward the bytes. func handleOutput(framer: NWProtocolFramer.Instance, message: NWProtocolFramer.Message, messageLength: Int, isComplete: Bool) { try? framer.writeOutputNoCopy(length: messageLength) } // Whenever new bytes are available to read, try to parse out your message format. func handleInput(framer: NWProtocolFramer.Instance) -> Int { let message = NWProtocolFramer.Message(definition: MyProtocol.definition) _ = framer.deliverInputNoCopy(length: 1000, message: message, isComplete: true) return 0 } } var listenerRef: NWListener? = nil var receiveConnectionRef: NWConnection? = nil func startListener() { let options = NWProtocolFramer.Options(definition: MyProtocol.definition) let parameters = NWParameters.tcp parameters.defaultProtocolStack.applicationProtocols.insert(options, at: 0) let listener = try! NWListener(using: parameters, on: 12345) listenerRef = listener listener.stateUpdateHandler = { state in print("listener: state did change, new: \(state)") } listener.newConnectionHandler = { conn in if let old = receiveConnectionRef { print("listener: will cancel old connection") old.cancel() receiveConnectionRef = nil } receiveConnectionRef = conn startReceive(on: conn) conn.start(queue: .main) } listener.start(queue: .main) } func startReceive(on connection: NWConnection) { connection.receiveMessage { dataQ, _, isComplete, errorQ in if let data = dataQ { print("receiver: did received, count: \(data.count)") } if let error = errorQ { print("receiver: did fail, error: \(error)") return } // if isComplete { // print("receiver: is complete") // return // } print("receiver: will not start new receive to force back pressure") } } var sendConnectionRef: NWConnection? = nil var totalSent = 0 func sendRandomData(to connection: NWConnection) { var bytes = [UInt8](repeating: 0, count: 1000) let err = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes) assert(err == errSecSuccess) let message = NWProtocolFramer.Message(definition: MyProtocol.definition) let context = NWConnection.ContentContext(identifier: "Data", metadata: [message]) connection.send(content: Data(bytes), contentContext: context, completion: .contentProcessed({ errorQ in if let error = errorQ { print("sender: send failed, error: \(error)") return } totalSent += bytes.count print("sender: did send, total: \(totalSent)") sendRandomData(to: connection) })) } func startSender() { let options = NWProtocolFramer.Options(definition: MyProtocol.definition) let parameters = NWParameters.tcp parameters.defaultProtocolStack.applicationProtocols.insert(options, at: 0) let connection = NWConnection(host: "localhost", port: 12345, using: parameters) sendConnectionRef = connection // Guarantees a long-lived referenced. connection.stateUpdateHandler = { state in print("sender: state did change, new: \(state)") } sendRandomData(to: connection) connection.start(queue: .main) } func main() { startListener() startSender() dispatchMain() } main() exit(EXIT_SUCCESS)
Sep ’21