diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2019-03-30 18:52:35 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2019-03-30 18:52:35 +0000 |
| commit | 2992642a3ca94bf52b066eed18bcc1df631ec67e (patch) | |
| tree | 6bdc4fd27c0d83245a3b43d9086cc1d1d9bd7be2 /Common/NativeApp | |
| parent | Updated core & native app cmake (diff) | |
| download | DiligentEngine-2992642a3ca94bf52b066eed18bcc1df631ec67e.tar.gz DiligentEngine-2992642a3ca94bf52b066eed18bcc1df631ec67e.zip | |
Enabled Vulkan mode on iOS (close https://github.com/DiligentGraphics/DiligentCore/issues/46)
Diffstat (limited to 'Common/NativeApp')
18 files changed, 485 insertions, 195 deletions
diff --git a/Common/NativeApp/Apple/Data/iOS/Base.lproj/LaunchScreen.xib b/Common/NativeApp/Apple/Data/iOS/Base.lproj/LaunchScreen.xib index 5569812..42589b0 100644 --- a/Common/NativeApp/Apple/Data/iOS/Base.lproj/LaunchScreen.xib +++ b/Common/NativeApp/Apple/Data/iOS/Base.lproj/LaunchScreen.xib @@ -1,9 +1,12 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8121.20" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES"> +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES"> + <device id="retina5_9" orientation="portrait"> + <adaptation id="fullscreen"/> + </device> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8101.16"/> - <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <objects> <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/> @@ -12,20 +15,20 @@ <rect key="frame" x="0.0" y="0.0" width="480" height="480"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright © 2015-2019 Diligent Graphics." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye"> + <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text=" Copyright © 2015-2019 Diligent Graphics." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye"> <rect key="frame" x="20" y="439" width="441" height="21"/> <fontDescription key="fontDescription" type="system" pointSize="17"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> - <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Diligent Engine" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX"> + <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Diligent Engine" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX"> <rect key="frame" x="20" y="140" width="441" height="43"/> <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/> - <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <nil key="highlightedColor"/> </label> </subviews> - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <constraints> <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/> <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/> diff --git a/Common/NativeApp/Apple/Data/iOS/Base.lproj/Main.storyboard b/Common/NativeApp/Apple/Data/iOS/Base.lproj/Main.storyboard index 0dc87c1..026129a 100644 --- a/Common/NativeApp/Apple/Data/iOS/Base.lproj/Main.storyboard +++ b/Common/NativeApp/Apple/Data/iOS/Base.lproj/Main.storyboard @@ -1,26 +1,89 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8121.20" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r"> +<?xml version="1.0" encoding="UTF-8"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="XIi-06-RrN"> + <device id="retina5_9" orientation="portrait"> + <adaptation id="fullscreen"/> + </device> <dependencies> <deployment identifier="iOS"/> - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8101.16"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> </dependencies> <scenes> - <!--View Controller--> + <!--Mode Selection View Controller--> + <scene sceneID="zOR-Fi-Gze"> + <objects> + <viewController id="XIi-06-RrN" customClass="ModeSelectionViewController" sceneMemberID="viewController"> + <layoutGuides> + <viewControllerLayoutGuide type="top" id="xws-yS-Cpz"/> + <viewControllerLayoutGuide type="bottom" id="eBA-xl-v26"/> + </layoutGuides> + <view key="view" contentMode="scaleToFill" id="bQn-Ig-dl7" customClass="BaseView"> + <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="CtC-44-7bh" userLabel="OpenGLES"> + <rect key="frame" x="43" y="270" width="289" height="119"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <state key="normal" title="Button" image="opengles-logo.png"/> + <connections> + <action selector="goOpenGLES:" destination="XIi-06-RrN" eventType="touchUpInside" id="Mad-GE-H0I"/> + </connections> + </button> + <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Exn-mx-E3B" userLabel="Vulkan"> + <rect key="frame" x="36" y="425" width="302" height="120"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <state key="normal" title="Button" image="vulkan-logo.png"/> + <connections> + <action selector="goVulkan:" destination="XIi-06-RrN" eventType="touchUpInside" id="jsv-Uc-EF5"/> + </connections> + </button> + </subviews> + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="voS-RJ-rQF" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="-1458.4000000000001" y="73.891625615763544"/> + </scene> + <!--Metal View Controller--> + <scene sceneID="sxp-To-dZO"> + <objects> + <viewController storyboardIdentifier="MetalViewControllerID" id="2n5-tG-bFt" userLabel="Metal View Controller" sceneMemberID="viewController"> + <layoutGuides> + <viewControllerLayoutGuide type="top" id="X8x-0E-yac"/> + <viewControllerLayoutGuide type="bottom" id="6Gz-x2-Owi"/> + </layoutGuides> + <view key="view" contentMode="scaleToFill" id="fUr-Le-qAJ" customClass="MetalView"> + <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> + </view> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="xSS-Vf-fsO" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="-570" y="74"/> + </scene> + <!--EAGL View Controller--> <scene sceneID="tne-QT-ifu"> <objects> - <viewController id="BYZ-38-t0r" sceneMemberID="viewController"> + <viewController storyboardIdentifier="EAGLViewControllerID" title="EAGL View Controller" id="BYZ-38-t0r" sceneMemberID="viewController"> <layoutGuides> <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> </layoutGuides> - <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC" customClass="EAGLView"> - <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> + <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC" userLabel="EAGL View" customClass="EAGLView"> + <rect key="frame" x="0.0" y="0.0" width="375" height="812"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> </view> </viewController> <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> </objects> + <point key="canvasLocation" x="214" y="74"/> </scene> </scenes> + <resources> + <image name="opengles-logo.png" width="1500" height="500"/> + <image name="vulkan-logo.png" width="1300" height="500"/> + </resources> </document> diff --git a/Common/NativeApp/Apple/Data/iOS/Images.xcassets/opengles-logo.png b/Common/NativeApp/Apple/Data/iOS/Images.xcassets/opengles-logo.png Binary files differnew file mode 100755 index 0000000..88b6983 --- /dev/null +++ b/Common/NativeApp/Apple/Data/iOS/Images.xcassets/opengles-logo.png diff --git a/Common/NativeApp/Apple/Data/iOS/Images.xcassets/vulkan-logo.png b/Common/NativeApp/Apple/Data/iOS/Images.xcassets/vulkan-logo.png Binary files differnew file mode 100644 index 0000000..8a15b9e --- /dev/null +++ b/Common/NativeApp/Apple/Data/iOS/Images.xcassets/vulkan-logo.png diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.h b/Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.h index bbb1f04..3839faa 100644 --- a/Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.h +++ b/Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.h @@ -9,9 +9,6 @@ #import <UIKit/UIKit.h> -@class EAGLView; -@class MainViewController; - @interface AppDelegate : NSObject <UIApplicationDelegate> { } diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.m b/Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.m index 6aa6648..5e1745c 100644 --- a/Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.m +++ b/Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.m @@ -7,7 +7,7 @@ */ #import "AppDelegate.h" -#import "EAGLView.h" +#import "BaseView.h" @implementation AppDelegate @@ -15,19 +15,12 @@ #pragma mark Application lifecycle - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ +{ // Override point for customization after application launch. - + [self.window makeKeyAndVisible]; - - NSString *error = [(EAGLView*)self.window.rootViewController.view getError]; - if(error != nil) - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failed to start the application" message:error delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Whatever", nil]; - [alert show]; - } - [(EAGLView*)self.window.rootViewController.view startAnimation]; + [(BaseView*)self.window.rootViewController.view startAnimation]; return YES; } @@ -40,7 +33,7 @@ Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. */ - [(EAGLView*)self.window.rootViewController.view stopAnimation]; + [(BaseView*)self.window.rootViewController.view stopAnimation]; } @@ -50,7 +43,7 @@ If your application supports background execution, called instead of applicationWillTerminate: when the user quits. */ - [(EAGLView*)self.window.rootViewController.view stopAnimation]; + [(BaseView*)self.window.rootViewController.view stopAnimation]; } @@ -59,7 +52,7 @@ Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. */ - [(EAGLView*)self.window.rootViewController.view startAnimation]; + [(BaseView*)self.window.rootViewController.view startAnimation]; } @@ -69,7 +62,7 @@ Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. */ - [(EAGLView*)self.window.rootViewController.view startAnimation]; + [(BaseView*)self.window.rootViewController.view startAnimation]; } @@ -79,8 +72,8 @@ See also applicationDidEnterBackground:. */ - [(EAGLView*)self.window.rootViewController.view stopAnimation]; - [(EAGLView*)self.window.rootViewController.view terminate]; + [(BaseView*)self.window.rootViewController.view stopAnimation]; + [(BaseView*)self.window.rootViewController.view terminate]; } diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/AppViewBase.h b/Common/NativeApp/Apple/Source/Classes/iOS/AppViewBase.h new file mode 100644 index 0000000..e6273e9 --- /dev/null +++ b/Common/NativeApp/Apple/Source/Classes/iOS/AppViewBase.h @@ -0,0 +1,16 @@ + +#import <UIKit/UIKit.h> +#import "BaseView.h" + +@interface AppViewBase : BaseView + +@property (nonatomic) NSInteger animationFrameInterval; + +- (void) initApp:(int)deviceType; +- (void) startAnimation; +- (void) stopAnimation; +- (void) terminate; +- (void) render; +- (NSString*)getError; + +@end diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/AppViewBase.m b/Common/NativeApp/Apple/Source/Classes/iOS/AppViewBase.m new file mode 100644 index 0000000..e7d4c57 --- /dev/null +++ b/Common/NativeApp/Apple/Source/Classes/iOS/AppViewBase.m @@ -0,0 +1,166 @@ + +#import "AppViewBase.h" + +#include "NativeAppBase.h" +#include <memory> +#include <string> + +@interface AppViewBase () +{ + std::unique_ptr<Diligent::NativeAppBase> _theApp; + NSInteger _animationFrameInterval; + CADisplayLink* _displayLink; + std::string _error; +} +@end + +@implementation AppViewBase + +- (void) initApp:(int)deviceType; +{ + try + { + _theApp.reset(Diligent::CreateApplication()); + // Init our renderer. + _theApp->Initialize(deviceType, (__bridge void*)self.layer); + } + catch(std::runtime_error &err) + { + _error = err.what(); + _theApp.reset(); + } + + [super stopAnimation]; + _animationFrameInterval = 1; + _displayLink = nil; +} + +- (void) render +{ + if(_theApp) + { + _theApp->Update(); + _theApp->Render(); + _theApp->Present(); + } +} + +- (void) layoutSubviews +{ + auto bounds = [self.layer bounds]; + auto scale = [self.layer contentsScale]; + + if(_theApp) + { + _theApp->WindowResize(bounds.size.width * scale, bounds.size.height * scale); + } +} + +- (NSInteger) animationFrameInterval +{ + return _animationFrameInterval; +} + +- (void) setAnimationFrameInterval:(NSInteger)frameInterval +{ + // Frame interval defines how many display frames must pass between each time the + // display link fires. The display link will only fire 30 times a second when the + // frame internal is two on a display that refreshes 60 times a second. The default + // frame interval setting of one will fire 60 times a second when the display refreshes + // at 60 times a second. A frame interval setting of less than one results in undefined + // behavior. + if (frameInterval >= 1) + { + _animationFrameInterval = frameInterval; + + if (self.animating) + { + [self stopAnimation]; + [self startAnimation]; + } + } +} + +- (void) startAnimation +{ + if (!self.animating) + { + // Create the display link and set the callback to our drawView method + _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawView:)]; + + // Set it to our _animationFrameInterval + [_displayLink setFrameInterval:_animationFrameInterval]; + + // Have the display link run on the default runn loop (and the main thread) + [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + + [super startAnimation]; + } +} + +- (void)stopAnimation +{ + if (self.animating) + { + [_displayLink invalidate]; + _displayLink = nil; + [super stopAnimation]; + } +} + +- (void)terminate +{ + _theApp.reset(); + [super terminate]; +} + +- (NSString*)getError +{ + return _error.empty() ? nil : [NSString stringWithFormat:@"%s", _error.c_str()]; +} + +- (void)touchesBegan:(NSSet<UITouch *> *)touches + withEvent:(UIEvent *)event; +{ + UITouch *firstTouch = touches.allObjects[0]; + CGPoint location = [firstTouch locationInView:self]; + if(_theApp) + { + _theApp->OnTouchBegan(location.x, location.y); + } +} + +- (void)touchesMoved:(NSSet<UITouch *> *)touches + withEvent:(UIEvent *)event; +{ + UITouch *firstTouch = touches.allObjects[0]; + CGPoint location = [firstTouch locationInView:self]; + if(_theApp) + { + _theApp->OnTouchMoved(location.x, location.y); + } +} + +- (void)touchesEnded:(NSSet<UITouch *> *)touches + withEvent:(UIEvent *)event; +{ + UITouch *firstTouch = touches.allObjects[0]; + CGPoint location = [firstTouch locationInView:self]; + if(_theApp) + { + _theApp->OnTouchEnded(location.x, location.y); + } +} + +- (void)touchesCancelled:(NSSet<UITouch *> *)touches + withEvent:(UIEvent *)event; +{ + UITouch *firstTouch = touches.allObjects[0]; + CGPoint location = [firstTouch locationInView:self]; + if(_theApp) + { + _theApp->OnTouchEnded(location.x, location.y); + } +} + +@end diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/BaseView.h b/Common/NativeApp/Apple/Source/Classes/iOS/BaseView.h new file mode 100644 index 0000000..9e8b99e --- /dev/null +++ b/Common/NativeApp/Apple/Source/Classes/iOS/BaseView.h @@ -0,0 +1,12 @@ + +#import <UIKit/UIKit.h> + +@interface BaseView : UIView + +@property (readonly, nonatomic, getter=isAnimating) BOOL animating; + +- (void) startAnimation; +- (void) stopAnimation; +- (void) terminate; + +@end diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/BaseView.m b/Common/NativeApp/Apple/Source/Classes/iOS/BaseView.m new file mode 100644 index 0000000..c87e5cd --- /dev/null +++ b/Common/NativeApp/Apple/Source/Classes/iOS/BaseView.m @@ -0,0 +1,21 @@ + +#import "BaseView.h" + +@implementation BaseView + +- (void) startAnimation +{ + _animating = TRUE; +} + +- (void)stopAnimation +{ + _animating = FALSE; +} + +- (void) terminate +{ + +} + +@end diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.h b/Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.h index fd6b9b9..e5ba68a 100644 --- a/Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.h +++ b/Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.h @@ -6,20 +6,13 @@ The EAGLView class is a UIView subclass that renders OpenGL scene. */ -#import <UIKit/UIKit.h> +#import "AppViewBase.h" // This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass. // The view content is basically an EAGL surface you render your OpenGL scene into. // Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel. -@interface EAGLView : UIView +@interface EAGLView : AppViewBase -@property (readonly, nonatomic, getter=isAnimating) BOOL animating; -@property (nonatomic) NSInteger animationFrameInterval; - -- (void) startAnimation; -- (void) stopAnimation; -- (void) terminate; - (void) drawView:(id)sender; -- (NSString*)getError; @end diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.m b/Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.m index 9120e99..ff02820 100644 --- a/Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.m +++ b/Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.m @@ -8,17 +8,11 @@ #import "EAGLView.h" -#include "NativeAppBase.h" -#include <memory> -#include <string> +#include "DeviceCaps.h" @interface EAGLView () { - std::unique_ptr<Diligent::NativeAppBase> _theApp; EAGLContext* _context; - NSInteger _animationFrameInterval; - CADisplayLink* _displayLink; - std::string _error; } @end @@ -32,166 +26,49 @@ // The GL view is stored in the storyboard file. When it's unarchived it's sent -initWithCoder: - (instancetype) initWithCoder:(NSCoder*)coder -{ +{ if ((self = [super initWithCoder:coder])) { // Get the layer CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; - + eaglLayer.opaque = TRUE; eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil]; - - + _context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; - + if (!_context || ![EAGLContext setCurrentContext:_context]) { return nil; } - - try - { - _theApp.reset(Diligent::CreateApplication()); - // Init our renderer. - _theApp->OnGLContextCreated((__bridge void*)self.layer); - } - catch(std::runtime_error &err) - { - _error = err.what(); - _theApp.reset(); - } - - _animating = FALSE; - _animationFrameInterval = 1; - _displayLink = nil; + + [self initApp:(int)Diligent::DeviceType::OpenGLES]; } - + return self; } - (void) drawView:(id)sender -{ - [EAGLContext setCurrentContext:_context]; - if(_theApp) +{ + [EAGLContext setCurrentContext:_context]; + + // There is no autorelease pool when this method is called + // because it will be called from a background thread. + // It's important to create one or app can leak objects. + @autoreleasepool { - _theApp->Update(); - _theApp->Render(); - _theApp->Present(); + [self render]; } } -- (void) layoutSubviews -{ - if(_theApp) - _theApp->WindowResize(0, 0); - [self drawView:nil]; -} - -- (NSInteger) animationFrameInterval -{ - return _animationFrameInterval; -} - -- (void) setAnimationFrameInterval:(NSInteger)frameInterval -{ - // Frame interval defines how many display frames must pass between each time the - // display link fires. The display link will only fire 30 times a second when the - // frame internal is two on a display that refreshes 60 times a second. The default - // frame interval setting of one will fire 60 times a second when the display refreshes - // at 60 times a second. A frame interval setting of less than one results in undefined - // behavior. - if (frameInterval >= 1) - { - _animationFrameInterval = frameInterval; - - if (_animating) - { - [self stopAnimation]; - [self startAnimation]; - } - } -} - -- (void) startAnimation -{ - if (!_animating) - { - // Create the display link and set the callback to our drawView method - _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawView:)]; - - // Set it to our _animationFrameInterval - [_displayLink setFrameInterval:_animationFrameInterval]; - - // Have the display link run on the default runn loop (and the main thread) - [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - - _animating = TRUE; - } -} - -- (void)stopAnimation -{ - if (_animating) - { - [_displayLink invalidate]; - _displayLink = nil; - _animating = FALSE; - } -} - -- (void)terminate -{ - _theApp.reset(); -} - - (void) dealloc { [self terminate]; // tear down context - if ([EAGLContext currentContext] == _context) + if ([EAGLContext currentContext] == _context) [EAGLContext setCurrentContext:nil]; } -- (NSString*)getError -{ - return _error.empty() ? nil : [NSString stringWithFormat:@"%s", _error.c_str()]; -} - -- (void)touchesBegan:(NSSet<UITouch *> *)touches - withEvent:(UIEvent *)event; -{ - UITouch *firstTouch = touches.allObjects[0]; - CGPoint location = [firstTouch locationInView:self]; - if(_theApp) - _theApp->OnTouchBegan(location.x, location.y); -} - -- (void)touchesMoved:(NSSet<UITouch *> *)touches - withEvent:(UIEvent *)event; -{ - UITouch *firstTouch = touches.allObjects[0]; - CGPoint location = [firstTouch locationInView:self]; - if(_theApp) - _theApp->OnTouchMoved(location.x, location.y); -} - -- (void)touchesEnded:(NSSet<UITouch *> *)touches - withEvent:(UIEvent *)event; -{ - UITouch *firstTouch = touches.allObjects[0]; - CGPoint location = [firstTouch locationInView:self]; - if(_theApp) - _theApp->OnTouchEnded(location.x, location.y);} - -- (void)touchesCancelled:(NSSet<UITouch *> *)touches - withEvent:(UIEvent *)event; -{ - UITouch *firstTouch = touches.allObjects[0]; - CGPoint location = [firstTouch locationInView:self]; - if(_theApp) - _theApp->OnTouchEnded(location.x, location.y); -} - @end diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/MetalView.h b/Common/NativeApp/Apple/Source/Classes/iOS/MetalView.h new file mode 100644 index 0000000..a485b27 --- /dev/null +++ b/Common/NativeApp/Apple/Source/Classes/iOS/MetalView.h @@ -0,0 +1,7 @@ +#import "AppViewBase.h" + +@interface MetalView : AppViewBase + +- (void) drawView:(id)sender; + +@end diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/MetalView.m b/Common/NativeApp/Apple/Source/Classes/iOS/MetalView.m new file mode 100644 index 0000000..3c8b198 --- /dev/null +++ b/Common/NativeApp/Apple/Source/Classes/iOS/MetalView.m @@ -0,0 +1,39 @@ +#import "MetalView.h" +#import <QuartzCore/CAMetalLayer.h> + +#include "DeviceCaps.h" + +@implementation MetalView + ++ (Class) layerClass +{ + return [CAMetalLayer class]; +} + +- (instancetype) initWithCoder:(NSCoder*)coder +{ + if ((self = [super initWithCoder:coder])) + { + [self initApp:(int)Diligent::DeviceType::Vulkan]; + } + + return self; +} + +- (void) drawView:(id)sender +{ + // There is no autorelease pool when this method is called + // because it will be called from a background thread. + // It's important to create one or app can leak objects. + @autoreleasepool + { + [self render]; + } +} + +- (void) dealloc +{ + [self terminate]; +} + +@end diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/ModeSelectionViewController.h b/Common/NativeApp/Apple/Source/Classes/iOS/ModeSelectionViewController.h new file mode 100644 index 0000000..4a08d7d --- /dev/null +++ b/Common/NativeApp/Apple/Source/Classes/iOS/ModeSelectionViewController.h @@ -0,0 +1,29 @@ +/* Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#import <UIKit/UIKit.h> + +@interface ModeSelectionViewController : UIViewController +{ +} +@end diff --git a/Common/NativeApp/Apple/Source/Classes/iOS/ModeSelectionViewController.mm b/Common/NativeApp/Apple/Source/Classes/iOS/ModeSelectionViewController.mm new file mode 100644 index 0000000..8958c10 --- /dev/null +++ b/Common/NativeApp/Apple/Source/Classes/iOS/ModeSelectionViewController.mm @@ -0,0 +1,64 @@ +/* Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#import "ModeSelectionViewController.h" +#import "BaseView.h" +#import "AppViewBase.h" + +@implementation ModeSelectionViewController +{ +} + +-(void)selectViewController:(NSString*)controllerID +{ + auto animating = ((BaseView*)self.view).animating; + + UIViewController* viewController = [self.storyboard instantiateViewControllerWithIdentifier:controllerID]; + self.view.window.rootViewController = viewController; + + NSString *error = [(AppViewBase*)viewController.view getError]; + if(error != nil) + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failed to start the application" message:error delegate:self cancelButtonTitle:@"OK" otherButtonTitles:@"Whatever", nil]; + [alert show]; + } + + if(animating) + { + [(BaseView*)viewController.view startAnimation]; + } +} + +- (IBAction)goOpenGLES:(id)sender +{ + [self selectViewController:@"EAGLViewControllerID"]; +} + +- (IBAction)goVulkan:(id)sender +{ +#if VULKAN_SUPPORTED + [self selectViewController:@"MetalViewControllerID"]; +#endif +} + +@end diff --git a/Common/NativeApp/CMakeLists.txt b/Common/NativeApp/CMakeLists.txt index b01877c..6fa1db4 100644 --- a/Common/NativeApp/CMakeLists.txt +++ b/Common/NativeApp/CMakeLists.txt @@ -13,7 +13,7 @@ if(PLATFORM_WIN32) function(add_win32_app TARGET_NAME SOURCE INCLUDE ASSETS) add_executable(${TARGET_NAME} WIN32 ${SOURCE} ${INCLUDE} ${ASSETS}) - + if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") # libmingw32 must be included BEFORE NativeAppBase that contains the definition of WinMain. # otherwise WinMain will be stripped out of NativeAppBase and will be unresolved. @@ -192,7 +192,6 @@ elseif(PLATFORM_MACOS) if (NOT CORE_VIDEO) message(FATAL_ERROR "CoreVideo is not found") endif() - target_link_libraries(${TARGET_NAME} PRIVATE ) find_library(METAL_FRAMEWORK Metal) if (NOT METAL_FRAMEWORK) @@ -227,21 +226,32 @@ elseif(PLATFORM_IOS) set(APPLE_SOURCE ${NATIVE_APP_SOURCE_DIR}/Apple/Source/main.m ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/AppDelegate.m + ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/BaseView.m ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/EAGLView.m + ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/AppViewBase.m + ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/ModeSelectionViewController.mm + ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/MetalView.m ) + set_source_files_properties(${APPLE_SOURCE} PROPERTIES COMPILE_FLAGS "-x objective-c++" ) set(APPLE_INCLUDE ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/AppDelegate.h + ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/BaseView.h ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/EAGLView.h + ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/AppViewBase.h + ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/ModeSelectionViewController.h + ${NATIVE_APP_SOURCE_DIR}/Apple/Source/Classes/iOS/MetalView.h ) set(APPLE_RESOURCES ${NATIVE_APP_SOURCE_DIR}/Apple/Data/iOS/Base.lproj/Main.storyboard ${NATIVE_APP_SOURCE_DIR}/Apple/Data/iOS/Base.lproj/LaunchScreen.xib ${NATIVE_APP_SOURCE_DIR}/Apple/Data/iOS/Images.xcassets/AppIcon.appiconset/dg-icon.png + ${NATIVE_APP_SOURCE_DIR}/Apple/Data/iOS/Images.xcassets/opengles-logo.png + ${NATIVE_APP_SOURCE_DIR}/Apple/Data/iOS/Images.xcassets/vulkan-logo.png ) set(APPLE_INFO_PLIST @@ -267,13 +277,13 @@ elseif(PLATFORM_IOS) target_include_directories(${TARGET_NAME} PRIVATE ${APPLE_INCLUDE_DIRS}) find_library(OPENGLES OpenGLES) - if (NOT OPENGLES) - message(FATAL_ERROR "OpenGLES is not found") - endif() + if (NOT OPENGLES) + message(FATAL_ERROR "OpenGLES is not found") + endif() find_library(UIKIT UIKit) if (NOT UIKIT) - message(FATAL_ERROR "UIKIT is not found") + message(FATAL_ERROR "UIKIT is not found") endif() find_library(CORE_ANIMATION QuartzCore) @@ -309,7 +319,7 @@ PUBLIC if(MSVC) target_compile_options(NativeAppBase PRIVATE -DUNICODE) - + if(PLATFORM_UNIVERSAL_WINDOWS) # Disable w4189: local variable is initialized but not referenced # Disable w4063: case is not a valid value for switch of enum @@ -332,7 +342,7 @@ if(PLATFORM_WIN32) ) elseif(PLATFORM_UNIVERSAL_WINDOWS) - + target_include_directories(NativeAppBase PUBLIC include/UWP diff --git a/Common/NativeApp/include/IOS/IOSAppBase.h b/Common/NativeApp/include/IOS/IOSAppBase.h index 2efe4ab..847052a 100644 --- a/Common/NativeApp/include/IOS/IOSAppBase.h +++ b/Common/NativeApp/include/IOS/IOSAppBase.h @@ -34,7 +34,7 @@ class IOSAppBase : public AppBase public: using AppBase::Update; void Update(); - virtual void OnGLContextCreated(void* eaglLayer) = 0; + virtual void Initialize(int deviceType, void* layer) = 0; virtual void OnTouchBegan(float x, float y){} virtual void OnTouchMoved(float x, float y){} virtual void OnTouchEnded(float x, float y){} |
