Bug 18003 - [OpenTK] iPhoneOSGameView causes errors on iOS 7 when the parent view controller is transitioned off screen by a UINavigationController
Summary: [OpenTK] iPhoneOSGameView causes errors on iOS 7 when the parent view control...
Status: CONFIRMED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll (show other bugs)
Version: 7.0.7
Hardware: PC Mac OS
: Normal normal
Target Milestone: Untriaged
Assignee: Radek Doulik
URL:
Depends on:
Blocks:
 
Reported: 2014-02-25 16:15 UTC by Brendan Zagaeski (Xamarin Team, assistant)
Modified: 2014-05-08 07:04 UTC (History)
4 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test case (11.04 KB, application/zip)
2014-02-25 16:15 UTC, Brendan Zagaeski (Xamarin Team, assistant)
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report for Bug 18003 on Developer Community or GitHub if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: Developer Community HTML or GitHub Markdown
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:
Status:
CONFIRMED

Description Brendan Zagaeski (Xamarin Team, assistant) 2014-02-25 16:15:32 UTC
Created attachment 6149 [details]
Test case

`iPhoneOSGameView.WillMoveToWindow()` leads to "Operation requires a GraphicsContext" and "Can't change RenderingApi after GraphicsContext is constructed" errors on iOS 7 when the parent view controller is transitioned off screen with animation by a UINavigationController.


## Steps to reproduce
1. Run the attached project on iOS 6 or iOS 7 (either simulator or device is fine). This is a slightly modified version of the "OpenGL Application" template that places the `OpenGLViewController` within a `UINavigationController`.

2. Wait 5 seconds so that the bouncing square gets transitioned off screen by the navigation controller.

3. Push the "Back" navigation button.


## Results

### On iOS 6 simulator: SUCCEEDS

Console output:
> Called OpenGLViewController.ViewWillAppear()
> Called WillMoveToWindow() with window: <UIWindow: 0xd083a00; frame = (0 0; 320 480); layer = <UIWindowLayer: 0xd083650>>
> Called OpenGLViewController.ViewWillDisappear()
> Called WillMoveToWindow() with window: 
> Called OpenGLViewController.ViewWillAppear()
> Called WillMoveToWindow() with window: <UIWindow: 0xd083a00; frame = (0 0; 320 480); layer = <UIWindowLayer: 0xd083650>>

### On iOS 7 simulator: FAILS

Console output:
> Called OpenGLViewController.ViewWillAppear()
> Called WillMoveToWindow() with window: <UIWindow: 0x10264f30; frame = (0 0; 320 480); gestureRecognizers = <NSArray: 0x10265690>; layer = <UIWindowLayer: 0x102633a0>>
> Called OpenGLViewController.ViewWillDisappear()
> Called WillMoveToWindow() with window: 
> Called WillMoveToWindow() with window: <UIWindow: 0x10264f30; frame = (0 0; 320 480); gestureRecognizers = <NSArray: 0x10265690>; layer = <UIWindowLayer: 0x102633a0>>
> Error in DestroyFrameBuffer: System.InvalidOperationException: Operation requires a GraphicsContext, which hasn't been created yet.
>   at OpenTK.Platform.iPhoneOS.iPhoneOSGameView.AssertContext () [0x00011] in /Developer/MonoTouch/Source/monotouch/src/OpenGLES/OpenTK_1.0/Platform/iPhoneOS/iPhoneOSGameView.cs:246 
>   at OpenTK.Platform.iPhoneOS.iPhoneOSGameView.DestroyFrameBuffer () [0x00008] in /Developer/MonoTouch/Source/monotouch/src/OpenGLES/OpenTK_1.0/Platform/iPhoneOS/iPhoneOSGameView.cs:546 
>   at OpenGLTest2.EAGLView.DestroyFrameBuffer () [0x00003] in /Volumes/Cases/iOS_DestroyedOpenGL_View_RFicker_2014_02_24/OpenGLTest2/EAGLView.cs:63 
> Called WillMoveToWindow() with window: 
> Called OpenGLViewController.ViewWillAppear()
> 
> Unhandled Exception:
> System.NotSupportedException: Can't change RenderingApi after GraphicsContext is constructed.
>   at OpenTK.Platform.iPhoneOS.iPhoneOSGameView.set_ContextRenderingApi (EAGLRenderingAPI value)
(remainder of stack trace omitted for brevity)


The problem is roughly that `WillMoveToWindow()` is called 3 times instead of just once between `OpenGLViewController.ViewWillDisappear()` and `OpenGLViewController.ViewWillAppear()`. It is called once with a `null` window, then once with a non-null window (causing an error), then again with a `null` window.


## Workarounds

### Workaround 1: don't animate the UINavigationController transition

In `AppDelegate.cs`, change:
> _nav.PushViewController(new UIViewController(), true)

... to:
> _nav.PushViewController(new UIViewController(), false)

Apparently iOS 7 does something different with how it calls `WillMoveToWindow()` when performing an animated navigation controller transition compared to a non-animated transition.


### Workaround 2: add some logic to ensure that the base `iPhoneOSGameView.WillMoveToWindow()` method is only called once for each call of `OpenGLViewController.ViewWillAppear()` or `OpenGLViewController.ViewWillAppear()`.

For example, in EAGLView.cs add:
> public bool HasMovedToWindow { get; set; }
> 
> public override void WillMoveToWindow(UIWindow window)
> {
>     Console.WriteLine ("Called WillMoveToWindow() with window: {0}", window);
>     if (!HasMovedToWindow) {
>         HasMovedToWindow = true;
>         base.WillMoveToWindow(window);
>     }
> }


Then in both `OpenGLViewController.ViewWillAppear()` and `OpenGLViewController.ViewWillAppear()` add:
> _eaglView.HasMovedToWindow = false;


## Version information
Tested on Xamarin.iOS 7.0.6.168 and 7.0.7.2
Comment 2 Sadik Ali 2014-02-26 05:32:45 UTC
I have checked this is issue on below environments:

Mac
XS 4.2.2 (build 2)
X iOS: 7.0.6.168

I debug application on iOS 6 and iOS 7, noticed that application is working is working on iOS 6 and for iOS 7 getting exception same as mentioned in bug description.

For exception refer screen cast: https://gist.github.com/anonymous/fdbd08b42873ff0d6650
Comment 3 Johannes Rudolph 2014-05-08 07:04:03 UTC
I can confirm this bug still exists with the current Xamarin Stable version, and in addition (depending on the state of the view) I get a slightly different exception:

`
System.InvalidOperationException: Operation requires a GraphicsContext, which hasn't been created yet.
  at OpenTK.Platform.iPhoneOS.iPhoneOSGameView.AssertContext () [0x00011] in /Developer/MonoTouch/Source/monotouch/src/OpenGLES/OpenTK_1.0/Platform/iPhoneOS/iPhoneOSGameView.cs:246 
  at OpenTK.Platform.iPhoneOS.iPhoneOSGameView.DestroyFrameBuffer () [0x00008] in /Developer/MonoTouch/Source/monotouch/src/OpenGLES/OpenTK_1.0/Platform/iPhoneOS/iPhoneOSGameView.cs:546 
  at OpenTK.Platform.iPhoneOS.iPhoneOSGameView.WillMoveToWindow (MonoTouch.UIKit.UIWindow window) [0x00078] in /Developer/MonoTouch/Source/monotouch/src/OpenGLES/OpenTK_1.0/Platform/iPhoneOS/iPhoneOSGameView.cs:802 
  at RowingInMotion.Mobile.BoatApp.iOS.EAGLView.WillMoveToWindow (MonoTouch.UIKit.UIWindow window) [0x00003] in /Users/jr/dev/rowinginmotion-cross/RowingInMotion.Mobile.BoatApp.iOS/Views/EAGLView.cs:80 
  at (wrapper managed-to-native) MonoTouch.UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
  at MonoTouch.UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0004c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/.pmcs-compat.UIApplication.cs:38 
  at RowingInMotion.Mobile.BoatApp.iOS.Application.Main (System.String[] args) [0x00008] in /Users/jr/dev/rowinginmotion-cross/RowingInMotion.Mobile.BoatApp.iOS/Setup/Main.cs:17 
`


Xamarin.iOS
Version: 7.2.2.2 (Business Edition)
Hash: db4427f
Branch: 
Build date: 2014-04-22 12:49:14-0400

Trying to see whether there's an easy workaround/patch.