summaryrefslogtreecommitdiffstats
path: root/Common/NativeApp
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2019-03-30 18:52:35 +0000
committerEgor Yusov <egor.yusov@gmail.com>2019-03-30 18:52:35 +0000
commit2992642a3ca94bf52b066eed18bcc1df631ec67e (patch)
tree6bdc4fd27c0d83245a3b43d9086cc1d1d9bd7be2 /Common/NativeApp
parentUpdated core & native app cmake (diff)
downloadDiligentEngine-2992642a3ca94bf52b066eed18bcc1df631ec67e.tar.gz
DiligentEngine-2992642a3ca94bf52b066eed18bcc1df631ec67e.zip
Enabled Vulkan mode on iOS (close https://github.com/DiligentGraphics/DiligentCore/issues/46)
Diffstat (limited to 'Common/NativeApp')
-rw-r--r--Common/NativeApp/Apple/Data/iOS/Base.lproj/LaunchScreen.xib21
-rw-r--r--Common/NativeApp/Apple/Data/iOS/Base.lproj/Main.storyboard79
-rwxr-xr-xCommon/NativeApp/Apple/Data/iOS/Images.xcassets/opengles-logo.pngbin0 -> 39013 bytes
-rw-r--r--Common/NativeApp/Apple/Data/iOS/Images.xcassets/vulkan-logo.pngbin0 -> 35692 bytes
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.h3
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/AppDelegate.m27
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/AppViewBase.h16
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/AppViewBase.m166
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/BaseView.h12
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/BaseView.m21
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.h11
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/EAGLView.m157
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/MetalView.h7
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/MetalView.m39
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/ModeSelectionViewController.h29
-rw-r--r--Common/NativeApp/Apple/Source/Classes/iOS/ModeSelectionViewController.mm64
-rw-r--r--Common/NativeApp/CMakeLists.txt26
-rw-r--r--Common/NativeApp/include/IOS/IOSAppBase.h2
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
new file mode 100755
index 0000000..88b6983
--- /dev/null
+++ b/Common/NativeApp/Apple/Data/iOS/Images.xcassets/opengles-logo.png
Binary files differ
diff --git a/Common/NativeApp/Apple/Data/iOS/Images.xcassets/vulkan-logo.png b/Common/NativeApp/Apple/Data/iOS/Images.xcassets/vulkan-logo.png
new file mode 100644
index 0000000..8a15b9e
--- /dev/null
+++ b/Common/NativeApp/Apple/Data/iOS/Images.xcassets/vulkan-logo.png
Binary files differ
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){}