| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 | 
							- #include "UnityAppController+Rendering.h"
 
- #include "UnityAppController+ViewHandling.h"
 
- #include "Unity/InternalProfiler.h"
 
- #include "Unity/UnityMetalSupport.h"
 
- #include "Unity/DisplayManager.h"
 
- #include "UI/UnityView.h"
 
- #include <dlfcn.h>
 
- // On some devices presenting render buffer may sporadically take long time to complete even with very simple scenes.
 
- // In these cases display link still fires at steady frame rate but input processing becomes stuttering.
 
- // As a workaround this switch disables display link during rendering a frame.
 
- // If you are running a GPU bound scene and experience frame drop you may want to disable this switch.
 
- #define ENABLE_DISPLAY_LINK_PAUSING 1
 
- #define ENABLE_RUNLOOP_ACCEPT_INPUT 1
 
- // _glesContextCreated was renamed to _renderingInited
 
- extern bool _renderingInited;
 
- extern bool _unityAppReady;
 
- extern bool _skipPresent;
 
- extern bool _didResignActive;
 
- static int _renderingAPI = 0;
 
- static int SelectRenderingAPIImpl();
 
- static bool _enableRunLoopAcceptInput = false;
 
- @implementation UnityAppController (Rendering)
 
- - (void)createDisplayLink
 
- {
 
-     _displayLink = [CADisplayLink displayLinkWithTarget: self selector: @selector(repaintDisplayLink)];
 
-     [self callbackFramerateChange: -1];
 
-     [_displayLink addToRunLoop: [NSRunLoop currentRunLoop] forMode: NSRunLoopCommonModes];
 
- }
 
- - (void)destroyDisplayLink
 
- {
 
-     [_displayLink invalidate];
 
-     _displayLink = nil;
 
- }
 
- - (void)processTouchEvents
 
- {
 
-     // On multicore devices running at 60 FPS some touch event delivery isn't properly interleaved with graphical frames.
 
-     // Running additional run loop here improves event handling in those cases.
 
-     // Passing here an NSDate from the past invokes run loop only once.
 
- #if ENABLE_RUNLOOP_ACCEPT_INPUT
 
-     // We get "NSInternalInconsistencyException: unexpected start state" exception if there are events queued and app is
 
-     // going to background at the same time. This happens when we render additional frame after receiving
 
-     // applicationWillResignActive. So check if we are supposed to ignore input.
 
-     bool ignoreInput = [[UIApplication sharedApplication] isIgnoringInteractionEvents];
 
-     if (!ignoreInput && _enableRunLoopAcceptInput)
 
-     {
 
-         static NSDate* past = [NSDate dateWithTimeIntervalSince1970: 0]; // the oldest date we can get
 
-         [[NSRunLoop currentRunLoop] acceptInputForMode: NSDefaultRunLoopMode beforeDate: past];
 
-     }
 
- #endif
 
- }
 
- - (void)repaintDisplayLink
 
- {
 
- #if ENABLE_DISPLAY_LINK_PAUSING
 
-     _displayLink.paused = YES;
 
- #endif
 
-     if (!_didResignActive)
 
-     {
 
-         UnityDisplayLinkCallback(_displayLink.timestamp);
 
-         [self repaint];
 
-         [self processTouchEvents];
 
-     }
 
- #if ENABLE_DISPLAY_LINK_PAUSING
 
-     _displayLink.paused = NO;
 
- #endif
 
- }
 
- - (void)repaint
 
- {
 
- #if UNITY_SUPPORT_ROTATION
 
-     [self checkOrientationRequest];
 
- #endif
 
-     [_unityView recreateRenderingSurfaceIfNeeded];
 
-     [_unityView processKeyboard];
 
-     UnityDeliverUIEvents();
 
-     if (!UnityIsPaused())
 
-         UnityRepaint();
 
- }
 
- - (void)callbackGfxInited
 
- {
 
-     InitRendering();
 
-     _renderingInited = true;
 
-     [self shouldAttachRenderDelegate];
 
-     [_unityView recreateRenderingSurface];
 
-     [_renderDelegate mainDisplayInited: _mainDisplay.surface];
 
-     _mainDisplay.surface->allowScreenshot = 1;
 
- }
 
- - (void)callbackPresent:(const UnityFrameStats*)frameStats
 
- {
 
-     if (_skipPresent || _didResignActive)
 
-         return;
 
-     // metal needs special processing, because in case of airplay we need extra command buffers to present non-main screen drawables
 
-     if (UnitySelectedRenderingAPI() == apiMetal)
 
-     {
 
-     #if UNITY_CAN_USE_METAL
 
-         [[DisplayManager Instance].mainDisplay present];
 
-         [[DisplayManager Instance] enumerateNonMainDisplaysWithBlock:^(DisplayConnection* conn) {
 
-             PreparePresentNonMainScreenMTL((UnityDisplaySurfaceMTL*)conn.surface);
 
-         }];
 
-     #endif
 
-     }
 
-     else
 
-     {
 
-         [[DisplayManager Instance] present];
 
-     }
 
-     Profiler_FramePresent(frameStats);
 
- }
 
- - (void)callbackFramerateChange:(int)targetFPS
 
- {
 
-     int maxFPS = (int)[UIScreen mainScreen].maximumFramesPerSecond;
 
-     if (targetFPS <= 0)
 
-         targetFPS = UnityGetTargetFPS();
 
-     if (targetFPS > maxFPS)
 
-     {
 
-         targetFPS = maxFPS;
 
-         UnitySetTargetFPS(targetFPS);
 
-         return;
 
-     }
 
-     _enableRunLoopAcceptInput = (targetFPS == maxFPS && UnityDeviceCPUCount() > 1);
 
-     _displayLink.preferredFramesPerSecond = targetFPS;
 
- }
 
- - (void)selectRenderingAPI
 
- {
 
-     NSAssert(_renderingAPI == 0, @"[UnityAppController selectRenderingApi] called twice");
 
-     _renderingAPI = SelectRenderingAPIImpl();
 
- }
 
- - (UnityRenderingAPI)renderingAPI
 
- {
 
-     NSAssert(_renderingAPI != 0, @"[UnityAppController renderingAPI] called before [UnityAppController selectRenderingApi]");
 
-     return (UnityRenderingAPI)_renderingAPI;
 
- }
 
- @end
 
- extern "C" void UnityGfxInitedCallback()
 
- {
 
-     [GetAppController() callbackGfxInited];
 
- }
 
- extern "C" void UnityPresentContextCallback(struct UnityFrameStats const* unityFrameStats)
 
- {
 
-     [GetAppController() callbackPresent: unityFrameStats];
 
- }
 
- extern "C" void UnityFramerateChangeCallback(int targetFPS)
 
- {
 
-     [GetAppController() callbackFramerateChange: targetFPS];
 
- }
 
- extern "C" void UnityInitMainScreenRenderingCallback()
 
- {
 
-     [GetAppController().mainDisplay initRendering];
 
- }
 
- static NSBundle*        _MetalBundle    = nil;
 
- static id<MTLDevice>    _MetalDevice    = nil;
 
- static bool IsMetalSupported(int /*api*/)
 
- {
 
-     _MetalBundle = [NSBundle bundleWithPath: @"/System/Library/Frameworks/Metal.framework"];
 
-     if (_MetalBundle)
 
-     {
 
-         [_MetalBundle load];
 
-         _MetalDevice = ((MTLCreateSystemDefaultDeviceFunc)::dlsym(dlopen(0, RTLD_LOCAL | RTLD_LAZY), "MTLCreateSystemDefaultDevice"))();
 
-         if (_MetalDevice)
 
-             return true;
 
-     }
 
-     [_MetalBundle unload];
 
-     return false;
 
- }
 
- static int SelectRenderingAPIImpl()
 
- {
 
-     const int api = UnityGetRenderingAPI();
 
-     if (api == apiMetal && IsMetalSupported(0))
 
-         return api;
 
- #if TARGET_IPHONE_SIMULATOR || TARGET_TVOS_SIMULATOR
 
-     return apiNoGraphics;
 
- #else
 
-     assert(false);
 
-     return 0;
 
- #endif
 
- }
 
- extern "C" NSBundle*            UnityGetMetalBundle()
 
- {
 
-     return _MetalBundle;
 
- }
 
- extern "C" MTLDeviceRef         UnityGetMetalDevice()       { return _MetalDevice; }
 
- extern "C" MTLCommandQueueRef   UnityGetMetalCommandQueue() { return ((UnityDisplaySurfaceMTL*)GetMainDisplaySurface())->commandQueue; }
 
- extern "C" MTLCommandQueueRef   UnityGetMetalDrawableCommandQueue() { return ((UnityDisplaySurfaceMTL*)GetMainDisplaySurface())->drawableCommandQueue; }
 
- extern "C" int                  UnitySelectedRenderingAPI() { return _renderingAPI; }
 
- extern "C" UnityRenderBufferHandle  UnityBackbufferColor()      { return GetMainDisplaySurface()->unityColorBuffer; }
 
- extern "C" UnityRenderBufferHandle  UnityBackbufferDepth()      { return GetMainDisplaySurface()->unityDepthBuffer; }
 
- extern "C" void                 DisplayManagerEndFrameRendering() { [[DisplayManager Instance] endFrameRendering]; }
 
- extern "C" void                 UnityPrepareScreenshot()    { UnitySetRenderTarget(GetMainDisplaySurface()->unityColorBuffer, GetMainDisplaySurface()->unityDepthBuffer); }
 
- extern "C" void UnityRepaint()
 
- {
 
-     @autoreleasepool
 
-     {
 
-         Profiler_FrameStart();
 
-         UnityPlayerLoop();
 
-         Profiler_FrameEnd();
 
-     }
 
- }
 
 
  |