diff --git a/shell/mac/AppDelegate.mm b/shell/mac/AppDelegate.mm index e1eeb81ccf..ac59a3a7e1 100644 --- a/shell/mac/AppDelegate.mm +++ b/shell/mac/AppDelegate.mm @@ -13,6 +13,9 @@ #import "ViewController.h" #import +#include +#include +#include namespace { @@ -63,7 +66,11 @@ @interface AppDelegate () @property (weak) IBOutlet NSWindow* window; @property NSTabViewController* tabViewController; +@property std::shared_ptr factory; +- (void)addTab:(igl::shell::RenderSessionWindowConfig)windowConfig + sessionConfig:(igl::shell::RenderSessionConfig)sessionConfig + frame:(CGRect)frame; @end @implementation AppDelegate @@ -76,75 +83,136 @@ - (void)applicationDidFinishLaunching:(NSNotification*)aNotification { - (void)setupViewController { self.tabViewController = [[NSTabViewController alloc] init]; - auto frame = [self.window frame]; - (void)frame; - ViewController* viewController = nullptr; - + self.factory = igl::shell::createDefaultRenderSessionFactory(); + + igl::shell::RenderSessionWindowConfig suggestedWindowConfig = { + .width = 1024, + .height = 768, + .windowMode = igl::shell::WindowMode::Window, + }; + std::vector suggestedSessionConfigs = { #if IGL_BACKEND_HEADLESS - // Headless tab - NSTabViewItem* tinyHeadlessTabViewItem = [[NSTabViewItem alloc] initWithIdentifier:nil]; - viewController = [[ViewController alloc] initWithFrame:frame - backendVersion:{igl::BackendFlavor::Invalid, 0, 0}]; - - tinyHeadlessTabViewItem.viewController = viewController; - tinyHeadlessTabViewItem.label = @"Headless"; - [self.tabViewController addTabViewItem:tinyHeadlessTabViewItem]; + { + .displayName = "Headless", + .backendVersion = {.flavor = igl::BackendFlavor::Invalid, + .majorVersion = 0, + .minorVersion = 0}, + .colorFramebufferFormat = igl::TextureFormat::RGBA_SRGB, + }, #endif - #if IGL_BACKEND_METAL - // Metal tab - NSTabViewItem* tinyMetalTabViewItem = [[NSTabViewItem alloc] initWithIdentifier:nil]; - viewController = [[ViewController alloc] initWithFrame:frame - backendVersion:{igl::BackendFlavor::Metal, 3, 0}]; - tinyMetalTabViewItem.viewController = viewController; - - tinyMetalTabViewItem.label = @"Metal"; - [self.tabViewController addTabViewItem:tinyMetalTabViewItem]; + { + .displayName = "Metal", + .backendVersion = {.flavor = igl::BackendFlavor::Metal, + .majorVersion = 3, + .minorVersion = 0}, + .colorFramebufferFormat = igl::TextureFormat::BGRA_SRGB, + }, #endif - #if IGL_BACKEND_OPENGL - // OpenGL tab - NSTabViewItem* tinyOGL4TabViewItem = [[NSTabViewItem alloc] initWithIdentifier:nil]; - viewController = [[ViewController alloc] initWithFrame:frame - backendVersion:{igl::BackendFlavor::OpenGL, 4, 1}]; - tinyOGL4TabViewItem.viewController = viewController; - - tinyOGL4TabViewItem.label = @"OGL 4.1"; - [self.tabViewController addTabViewItem:tinyOGL4TabViewItem]; - // @fb-only - // @fb-only - // @fb-only + { + .displayName = "OGL 4.1", + .backendVersion = {.flavor = igl::BackendFlavor::OpenGL, + .majorVersion = 4, + .minorVersion = 1}, + .colorFramebufferFormat = igl::TextureFormat::BGRA_SRGB, + }, + // clang-format off // @fb-only + // clang-format on + // @fb-only + // @fb-only // @fb-only - // @fb-only - // @fb-only - - NSColorSpace* metalColorSpace = colorSpaceToNSColorSpace(viewController.colorSpace); - [self.window setColorSpace:metalColorSpace]; + // @fb-only + // @fb-only + // @fb-only #endif - // @fb-only - // @fb-only - // @fb-only - // @fb-only + // clang-format off // @fb-only + // clang-format on + // @fb-only + // @fb-only // @fb-only - // @fb-only + // @fb-only + // @fb-only + // @fb-only +// @fb-only +#if IGL_BACKEND_VULKAN + { + .displayName = "Vulkan", + .backendVersion = {.flavor = igl::BackendFlavor::Vulkan, + .majorVersion = 1, + .minorVersion = 1}, + .colorFramebufferFormat = igl::TextureFormat::BGRA_SRGB, + }, +#endif + }; + + const auto requestedWindowConfig = self.factory->requestedWindowConfig(suggestedWindowConfig); + IGL_ASSERT(requestedWindowConfig.windowMode == igl::shell::WindowMode::Window || + requestedWindowConfig.windowMode == igl::shell::WindowMode::MaximizedWindow); + + CGRect frame = requestedWindowConfig.windowMode == igl::shell::WindowMode::Window + ? [self.window frame] + : [[NSScreen mainScreen] frame]; + if (requestedWindowConfig.windowMode == igl::shell::WindowMode::Window) { + frame.size = CGSizeMake(requestedWindowConfig.width, requestedWindowConfig.height); + } + + const auto requestedSessionConfigs = + self.factory->requestedSessionConfigs(std::move(suggestedSessionConfigs)); + for (const auto& sessionConfig : requestedSessionConfigs) { + [self addTab:requestedWindowConfig sessionConfig:sessionConfig frame:frame]; + } +} + +- (void)addTab:(igl::shell::RenderSessionWindowConfig)windowConfig + sessionConfig:(igl::shell::RenderSessionConfig)sessionConfig + frame:(CGRect)frame { + ViewController* viewController = nullptr; + bool supported = false; +#if IGL_BACKEND_HEADLESS + if (sessionConfig.backendVersion.flavor == igl::BackendFlavor::Invalid) { + supported = true; + } +#endif +#if IGL_BACKEND_METAL + if (sessionConfig.backendVersion.flavor == igl::BackendFlavor::Metal) { + supported = true; + } +#endif +#if IGL_BACKEND_OPENGL + if (sessionConfig.backendVersion.flavor == igl::BackendFlavor::OpenGL) { + supported = true; + NSColorSpace* metalColorSpace = colorSpaceToNSColorSpace(viewController.colorSpace); + [self.window setColorSpace:metalColorSpace]; + } +#endif +// @fb-only // @fb-only + // @fb-only // @fb-only // @fb-only - #if IGL_BACKEND_VULKAN - // Vulkan tab - NSTabViewItem* tinyVulkanTabViewItem = [[NSTabViewItem alloc] initWithIdentifier:nil]; + if (sessionConfig.backendVersion.flavor == igl::BackendFlavor::Vulkan) { + supported = true; + } +#endif + if (!IGL_VERIFY(supported)) { + return; + } + + NSTabViewItem* tabViewItem = [[NSTabViewItem alloc] initWithIdentifier:nil]; + viewController = [[ViewController alloc] initWithFrame:frame - backendVersion:{igl::BackendFlavor::Vulkan, 1, 3}]; + factory:*self.factory + config:sessionConfig]; - tinyVulkanTabViewItem.viewController = viewController; - tinyVulkanTabViewItem.label = @"Vulkan"; - [self.tabViewController addTabViewItem:tinyVulkanTabViewItem]; -#endif + tabViewItem.viewController = viewController; + tabViewItem.label = [NSString stringWithUTF8String:sessionConfig.displayName.c_str()]; + [self.tabViewController addTabViewItem:tabViewItem]; self.window.contentViewController = self.tabViewController; [self.window setFrame:viewController.frame display:YES animate:false]; diff --git a/shell/mac/ViewController.h b/shell/mac/ViewController.h index 1123b259a2..314e0617c5 100644 --- a/shell/mac/ViewController.h +++ b/shell/mac/ViewController.h @@ -9,6 +9,7 @@ #import #import #import +#import NS_ASSUME_NONNULL_BEGIN @interface ViewController : NSViewController @@ -16,7 +17,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) NSView* iglView; - (instancetype)initWithFrame:(CGRect)frame - backendVersion:(igl::BackendVersion)backendType NS_DESIGNATED_INITIALIZER; + factory:(igl::shell::IRenderSessionFactory&)factory + config:(igl::shell::RenderSessionConfig)config; // Explicitly disable superclass' designated initializers - (instancetype)initWithNibName:(nullable NSNibName)nibNameOrNil diff --git a/shell/mac/ViewController.mm b/shell/mac/ViewController.mm index 1cc3795894..aa57cc4d5b 100644 --- a/shell/mac/ViewController.mm +++ b/shell/mac/ViewController.mm @@ -31,6 +31,7 @@ #include #include #include +#include #include // @fb-only // @fb-only @@ -48,7 +49,8 @@ using namespace igl; @interface ViewController () { - igl::BackendVersion backendVersion_; + igl::shell::IRenderSessionFactory* factory_; + igl::shell::RenderSessionConfig config_; igl::shell::ShellParams shellParams_; CGRect frame_; CVDisplayLinkRef displayLink_; // For OpenGL only @@ -66,16 +68,19 @@ @implementation ViewController /// MARK: - Init ///-------------------------------------- -- (instancetype)initWithFrame:(CGRect)frame backendVersion:(igl::BackendVersion)backendVersion { +- (instancetype)initWithFrame:(CGRect)frame + factory:(igl::shell::IRenderSessionFactory&)factory + config:(igl::shell::RenderSessionConfig)config { self = [super initWithNibName:nil bundle:nil]; if (!self) { return self; } - backendVersion_ = backendVersion; + config_ = std::move(config); + factory_ = &factory; shellParams_ = igl::shell::ShellParams(); - frame.size.width = shellParams_.viewportSize.x; - frame.size.height = shellParams_.viewportSize.y; + shellParams_.viewportSize.x = frame.size.width; + shellParams_.viewportSize.y = frame.size.height; frame_ = frame; kMouseSpeed_ = 0.05f; currentDrawable_ = nil; @@ -109,7 +114,7 @@ - (void)render { shellPlatform_->getInputDispatcher().processEvents(); igl::SurfaceTextures surfaceTextures; - if (backendVersion_.flavor != igl::BackendFlavor::Invalid && + if (config_.backendVersion.flavor != igl::BackendFlavor::Invalid && shellPlatform_->getDevicePtr() != nullptr) { // @fb-only // @fb-only @@ -150,7 +155,7 @@ - (void)loadView { // return something that works HWDeviceQueryDesc queryDesc(HWDeviceType::Unknown); - switch (backendVersion_.flavor) { + switch (config_.backendVersion.flavor) { case igl::BackendFlavor::Invalid: { auto headlessView = [[HeadlessView alloc] initWithFrame:frame_]; self.view = headlessView; @@ -178,7 +183,7 @@ - (void)loadView { metalView.delegate = self; metalView.colorPixelFormat = - metal::Texture::textureFormatToMTLPixelFormat(shellParams_.defaultColorFramebufferFormat); + metal::Texture::textureFormatToMTLPixelFormat(config_.colorFramebufferFormat); metalView.colorspace = metal::colorSpaceToCGColorSpace(shellParams_.swapchainColorSpace); metalView.framebufferOnly = NO; @@ -192,7 +197,7 @@ - (void)loadView { #if IGL_BACKEND_OPENGL case igl::BackendFlavor::OpenGL: { NSOpenGLPixelFormat* pixelFormat; - if (backendVersion_.majorVersion == 4 && backendVersion_.minorVersion == 1) { + if (config_.backendVersion.majorVersion == 4 && config_.backendVersion.minorVersion == 1) { static NSOpenGLPixelFormatAttribute attributes[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAAllowOfflineRenderers, @@ -212,7 +217,8 @@ - (void)loadView { }; pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; IGL_ASSERT_MSG(pixelFormat, "Requested attributes not supported"); - } else if (backendVersion_.majorVersion == 3 && backendVersion_.minorVersion == 2) { + } else if (config_.backendVersion.majorVersion == 3 && + config_.backendVersion.minorVersion == 2) { static NSOpenGLPixelFormatAttribute attributes[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAAllowOfflineRenderers, @@ -231,7 +237,8 @@ - (void)loadView { 0, }; pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - } else if (backendVersion_.majorVersion == 2 && backendVersion_.minorVersion == 1) { + } else if (config_.backendVersion.majorVersion == 2 && + config_.backendVersion.minorVersion == 1) { static NSOpenGLPixelFormatAttribute attributes[] = { NSOpenGLPFADoubleBuffer, NSOpenGLPFAAllowOfflineRenderers, @@ -253,8 +260,8 @@ - (void)loadView { } else { IGL_ASSERT_MSG(false, "Unsupported OpenGL version: %u.%u\n", - backendVersion_.majorVersion, - backendVersion_.minorVersion); + config_.backendVersion.majorVersion, + config_.backendVersion.minorVersion); } auto openGLView = [[GLView alloc] initWithFrame:frame_ pixelFormat:pixelFormat]; igl::Result result; @@ -282,8 +289,7 @@ - (void)loadView { vulkanContextConfig.enableBufferDeviceAddress = true; vulkanContextConfig.swapChainColorSpace = shellParams_.swapchainColorSpace; - vulkanContextConfig.requestedSwapChainTextureFormat = - shellParams_.defaultColorFramebufferFormat; + vulkanContextConfig.requestedSwapChainTextureFormat = config_.colorFramebufferFormat; auto context = igl::vulkan::HWDevice::createContext(vulkanContextConfig, (__bridge void*)vulkanView); @@ -330,7 +336,7 @@ - (void)loadView { } } - session_ = igl::shell::createDefaultRenderSession(shellPlatform_); + session_ = factory_->createRenderSession(shellPlatform_); IGL_ASSERT_MSG(session_, "createDefaultRenderSession() must return a valid session"); // Get initial native surface dimensions shellParams_.nativeSurfaceDimensions = glm::ivec2(2048, 1536); @@ -374,7 +380,7 @@ - (void)mtkView:(nonnull MTKView*)view drawableSizeDidChange:(CGSize)size { } - (std::shared_ptr)createTextureFromNativeDrawable { - switch (backendVersion_.flavor) { + switch (config_.backendVersion.flavor) { #if IGL_BACKEND_METAL case igl::BackendFlavor::Metal: { auto& device = shellPlatform_->getDevice(); @@ -424,7 +430,7 @@ - (void)mtkView:(nonnull MTKView*)view drawableSizeDidChange:(CGSize)size { } - (std::shared_ptr)createTextureFromNativeDepth { - switch (backendVersion_.flavor) { + switch (config_.backendVersion.flavor) { #if IGL_BACKEND_METAL case igl::BackendFlavor::Metal: { auto& device = shellPlatform_->getDevice();