diff --git a/include/ios_driver.h b/include/ios_driver.h index 7f783970..85b3be2c 100644 --- a/include/ios_driver.h +++ b/include/ios_driver.h @@ -1,7 +1,9 @@ #pragma once #include #include +#include void iosCreateEmulator(); void iosLoadROM(NSString* pathNS); -void iosRunFrame(CAMetalLayer* layer); \ No newline at end of file +void iosRunFrame(CAMetalLayer* layer); +void iosSetOutputSize(uint32_t width, uint32_t height); \ No newline at end of file diff --git a/src/core/renderer_mtl/pica_to_mtl.cpp b/src/core/renderer_mtl/pica_to_mtl.cpp index 538e6d52..973ad1bf 100644 --- a/src/core/renderer_mtl/pica_to_mtl.cpp +++ b/src/core/renderer_mtl/pica_to_mtl.cpp @@ -40,7 +40,13 @@ namespace PICA { }; void checkForMTLPixelFormatSupport(MTL::Device* device) { - if (!device->supportsFamily(MTL::GPUFamilyApple1)) { +#ifndef PANDA3DS_IOS_SIMULATOR + const bool supportsApple1 = device->supportsFamily(MTL::GPUFamilyApple1); +#else + // iOS simulator claims to support Apple1, yet doesn't support a bunch of texture formats from it... + const bool supportsApple1 = false; +#endif + if (!supportsApple1) { mtlPixelFormatInfos[2] = {MTL::PixelFormatRGBA8Unorm, 4, decodeTexelA1BGR5ToRGBA8}; mtlPixelFormatInfos[3] = {MTL::PixelFormatRGBA8Unorm, 4, decodeTexelB5G6R5ToRGBA8}; mtlPixelFormatInfos[4] = {MTL::PixelFormatRGBA8Unorm, 4, decodeTexelABGR4ToRGBA8}; diff --git a/src/core/renderer_mtl/renderer_mtl.cpp b/src/core/renderer_mtl/renderer_mtl.cpp index 2b0f80c6..bbc8212a 100644 --- a/src/core/renderer_mtl/renderer_mtl.cpp +++ b/src/core/renderer_mtl/renderer_mtl.cpp @@ -130,7 +130,7 @@ void RendererMTL::display() { // Top screen if (topScreen) { renderCommandEncoder->setViewport( - MTL::Viewport{blitInfo.topScreenX, blitInfo.topScreenY + 240 * blitInfo.scale, 400 * blitInfo.scale, 240 * blitInfo.scale, 0.0f, 1.0f} + MTL::Viewport{blitInfo.topScreenX, blitInfo.topScreenY, 400 * blitInfo.scale, 240 * blitInfo.scale, 0.0f, 1.0f} ); renderCommandEncoder->setFragmentTexture(topScreen->get().texture, 0); renderCommandEncoder->drawPrimitives(MTL::PrimitiveTypeTriangleStrip, NS::UInteger(0), NS::UInteger(4)); diff --git a/src/host_shaders/metal_blit.metal b/src/host_shaders/metal_blit.metal index 31b94ec4..6709c82a 100644 --- a/src/host_shaders/metal_blit.metal +++ b/src/host_shaders/metal_blit.metal @@ -10,8 +10,8 @@ struct BasicVertexOut { }; struct NDCViewport { - float2 offset; - float2 scale; + float2 offset; + float2 scale; }; vertex BasicVertexOut vertexBlit(uint vid [[vertex_id]], constant NDCViewport& viewport [[buffer(0)]]) { diff --git a/src/ios_driver.mm b/src/ios_driver.mm index 8ec87436..cb98b269 100644 --- a/src/ios_driver.mm +++ b/src/ios_driver.mm @@ -33,6 +33,10 @@ IOS_EXPORT void iosRunFrame(CAMetalLayer* layer) { } IOS_EXPORT void iosLoadROM(NSString* pathNS) { - auto path = std::filesystem::path([pathNS UTF8String]); - emulator->loadROM(path); + auto path = std::filesystem::path([pathNS UTF8String]); + emulator->loadROM(path); +} + +IOS_EXPORT void iosSetOutputSize(uint32_t width, uint32_t height) { + emulator->setOutputSize(width, height); } \ No newline at end of file diff --git a/src/pandios/Alber/Headers/ios_driver.h b/src/pandios/Alber/Headers/ios_driver.h index 7f783970..85b3be2c 100644 --- a/src/pandios/Alber/Headers/ios_driver.h +++ b/src/pandios/Alber/Headers/ios_driver.h @@ -1,7 +1,9 @@ #pragma once #include #include +#include void iosCreateEmulator(); void iosLoadROM(NSString* pathNS); -void iosRunFrame(CAMetalLayer* layer); \ No newline at end of file +void iosRunFrame(CAMetalLayer* layer); +void iosSetOutputSize(uint32_t width, uint32_t height); \ No newline at end of file diff --git a/src/pandios/Pandios.xcodeproj/project.xcworkspace/xcuserdata/giorgos.xcuserdatad/UserInterfaceState.xcuserstate b/src/pandios/Pandios.xcodeproj/project.xcworkspace/xcuserdata/giorgos.xcuserdatad/UserInterfaceState.xcuserstate index 38cf2747..3009b72b 100644 Binary files a/src/pandios/Pandios.xcodeproj/project.xcworkspace/xcuserdata/giorgos.xcuserdatad/UserInterfaceState.xcuserstate and b/src/pandios/Pandios.xcodeproj/project.xcworkspace/xcuserdata/giorgos.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/src/pandios/Pandios/ContentView.swift b/src/pandios/Pandios/ContentView.swift index 16a64f7c..ebcc7190 100644 --- a/src/pandios/Pandios/ContentView.swift +++ b/src/pandios/Pandios/ContentView.swift @@ -3,32 +3,47 @@ import SwiftUI import MetalKit import Darwin +final class DrawableSize { + var width: UInt32 = 0 + var height: UInt32 = 0 + var sizeChanged = false +} + var emulatorLock = NSLock() +var drawableSize = DrawableSize() + +class ResizeAwareMTKView: MTKView { + var onResize: ((CGSize) -> Void)? + + override func layoutSubviews() { + super.layoutSubviews() + onResize?(self.drawableSize) + } +} class DocumentViewController: UIViewController, DocumentDelegate { var documentPicker: DocumentPicker! override func viewDidLoad() { super.viewDidLoad() - - /// set up the document picker documentPicker = DocumentPicker(presentationController: self, delegate: self) /// When the view loads (ie user opens the app) show the file picker show() } - /// callback from the document picker + /// Callback from the document picker func didPickDocument(document: Document?) { if let pickedDoc = document { let fileURL = pickedDoc.fileURL print("Loading ROM", fileURL) emulatorLock.lock() + print(fileURL.path(percentEncoded: false)) iosLoadROM(fileURL.path(percentEncoded: false)) emulatorLock.unlock() } } - + func show() { documentPicker.displayPicker() } @@ -36,25 +51,15 @@ class DocumentViewController: UIViewController, DocumentDelegate { struct DocumentView: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> DocumentViewController { - return DocumentViewController() - } - - func updateUIViewController(_ uiViewController: DocumentViewController, context: Context) { - // No update needed + DocumentViewController() } + + func updateUIViewController(_ uiViewController: DocumentViewController, context: Context) {} } struct ContentView: UIViewRepresentable { - @State var showFileImporter = true - - /* - func makeCoordinator() -> Renderer { - Renderer(self) - } - */ - - func makeUIView(context: UIViewRepresentableContext) -> MTKView { - let mtkView = MTKView() + func makeUIView(context: Context) -> ResizeAwareMTKView { + let mtkView = ResizeAwareMTKView() mtkView.preferredFramesPerSecond = 60 mtkView.enableSetNeedsDisplay = true mtkView.isPaused = true @@ -64,17 +69,34 @@ struct ContentView: UIViewRepresentable { } mtkView.framebufferOnly = false - mtkView.drawableSize = mtkView.frame.size + + mtkView.onResize = { newDrawableSize in + let newWidth = UInt32(newDrawableSize.width) + let newHeight = UInt32(newDrawableSize.height) + + emulatorLock.lock() + if drawableSize.width != newWidth || drawableSize.height != newHeight { + drawableSize.width = newWidth + drawableSize.height = newHeight + drawableSize.sizeChanged = true + } + emulatorLock.unlock() + } let dispatchQueue = DispatchQueue(label: "QueueIdentification", qos: .background) - let metalLayer = mtkView.layer as! CAMetalLayer; + let metalLayer = mtkView.layer as! CAMetalLayer - dispatchQueue.async{ + dispatchQueue.async { iosCreateEmulator() while (true) { emulatorLock.lock() - iosRunFrame(metalLayer); + if drawableSize.sizeChanged { + drawableSize.sizeChanged = false + iosSetOutputSize(drawableSize.width, drawableSize.height) + } + + iosRunFrame(metalLayer) emulatorLock.unlock() } } @@ -82,14 +104,13 @@ struct ContentView: UIViewRepresentable { return mtkView } - func updateUIView(_ uiView: MTKView, context: UIViewRepresentableContext) { - print("Updating MTKView"); - } + func updateUIView(_ uiView: ResizeAwareMTKView, context: Context) {} } struct ContentView_Previews: PreviewProvider { static var previews: some View { - DocumentView(); - ContentView(); + DocumentView() + ContentView() + .frame(maxWidth: .infinity, maxHeight: .infinity) } }