Synchronize rendering between native OpenGL and WebGL in WKWebview (iOS) - ios

For an iOS app we are developing, I am trying to tightly synchronize the rendering of a 3D scene happening in a WKWebView (using three.js/WebGL) and the OpenGL rendering happening on a separate UIView in the native side of the app (Objective-C). Each time the rendering loop of the native side prepares and presents a frame, a call to a JS function is done via the WKWebView evaluateJavaScript method to render one frame using three.js. The result is that, even though both rendering calls are frame synchronous, visually there's a tiny lag between the display of both scenes that doesn't work for our purposes. This is likely due to the fact that both renderings are happening in separate threads (OpenGL contexts?).
My question is: is it possible to completely synchronize the display of both a WKWebView/WebGL and a UIView (UIGLViewProtocol)?

Related

Excessive pending callback while loading video in Webview in React Native

I have the functionality Where I am loading the Wistia Video in Webview.
This is what I am doing in React Native.
The functionality works well when the video is loaded in portrait but when the video is moved to the landscape mode via native controller and when closed the UI gets distorts and causes the exception as below.
excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code: {"17417":{},"17418":{},"17419":{},"17420":{"module":"UIManager","method":"measureLayout"},"17421":{"module":"UIManager","method":"measureLayout"},"17422":{},"17423":{},"17424":{},"17425":{},"17426":{},"17427":{},"17430":{},"17431":{},"17432":{},"17433":{},"17434":{},"17435":{},"17436":{},"17437":{},"17438":{},"17439":{},"17440":{},"17441":{},"17442":{"module":"UIManager","method":"measureLayout"},"17443":{"module":"UIManager","method":"measureLayout"},"17444":{},"17445":{},"17446":{},"17447":{},"17448":{},"17449":{},"17450":{},"17451":{},"17454":{},"17455":{},"17456":{},"17457":{},"17458":{"module":"UIManager","method":"measureLayout"},"17459":{"module":"UIManager","method":"measureLayout"},"17460":{},"17461":{},"17462":{},"17463":{},"17464":{},"17465":{},"17466":{},"17467":{},"17468":{},"17469":{},"17470":{},"...(truncated keys)...":451}
The solutions to this suggests that there can be multiple async calls etc. which is not the case here.
The simple flow is as below
FlatList> WebView>Wistia link> turning to landscape mode> closing the video> Exception thrown.

Screen frame render finished / presented callback

I'd like to know the exact moment when screen frame finishes rendering and gets displayed, so I can capture specific window images with quartz api. There is CVDisplayLink / CADisplayLink that allows application to synchronise its drawing to the refresh rate of the display.
As I understand, those methods are very similar to what I need, but invoked when screen frame needs to be rendered, not when it finished and presented, meaning that if I capture the current screen image at that time I'd only see the previous render. Is this correct thinking?
If yes, is there a way to do get notified when the frame has actually finished rendered and was presented? Maybe there's private api for that? Ideally I need an answer for macOS, but if you happen to know how to do this in iOS, please let know.
P.S. I'm aware of CGDisplayStream, it's a great solution for capturing the whole screen, not specific windows – it uses run loops and dispatch queues, meaning that callbacks are not invoked in realtime like with display links.

UIWebView HTML 5 game Canvas drawing slowness in iOS 9, or WebGL crashing in iOS 8.0 and above

I've having an issue with UIWebView and running HTML 5 games (that another developer is working on). We've tried two different options, and neither is optimal.
Option 1: He renders the HTML 5 game with "canvas drawing". When he does it this way, nothing crashes, however in iOS 9 when we go back into the app from the background, the Web View loads back up, but the game is moving much slower than normal (issue not on iOS 7.1 and above). By much slower I'm talking about the animations are not moving the same velocity that they were when we first load the game. The weird thing about this issue is that even if the user opens up a different HTML 5 game (we're adding multiple games) the animations are slower for that game as well. I've tried dismissing the Web View Controller when the UIApplicationWillResignActiveNotification gets posted. When I set the game up this way, the slowness only happens if the app is in the for 4 seconds (it's very strange).
Option 2: He renders the game with "WebGL". When he renders it this way, the app crashes when the app gets backgrounded on iOS 8.0 and above. My research into the crash is that iOS can't draw OpenGL ES in the background. I'm assuming that the WebGL commands are running similar commands as OpenGL ES would do, hence the crash. Dismissing the Web View Controller on UIApplicationWillResignActiveNotification still causes the crash to happen.
Has anyone else ever dealt with a situation like this?
I've not found a good solution to the problem, but I did find a work around.
When I get the App Will Resign Active message, I remove the UIWebView from the UIWebViewController's subview. When I get the Did Become Active message, I add the UIWebView to the UIWebViewController's subview.
This solution works for both cases.

Improving UIWebView initialization time

My company uses a UIWebView to display ads. The issue I'm having is that initializing a UIWebView appears to be expensive; profiling with Time Profiler shows [UIWebView alloc] initWithFrame:CGRectMake(0,0,500,500)] to take 31–40ms. This is enough to cause noticeable frame drops in games running at 60 FPS.
Is there a way to workaround this slow initialization time? My current ideas are to create a UIWebView when the app launches (but before gameplay has started), and reuse that (potentially creating a pool of them to reuse, like how UITableViewCell works) or to try and see if WKWebView has better performance.
Here are my findings:
WKWebView does not initialize any faster. Creating WKWebViews took a similar amount of time as creating UIWebViews (in the 1 test I did, it took 46ms to create two WKWebViews.
The very first web view created takes significantly longer to create than subsequent web views. The first one takes 31–42 ms; subsequent ones take ~11ms to create. The good news here is that creating the first web view when e.g. the app launches allows future webviews to be created more cheaply, avoiding a 40ms hit while the game is running.
Creating a pool of UIWebViews was a good solution for my use case. By creating the webviews at app launch and then reusing them, I avoid causing a frame drop while the game is running.
There is not much difference in the responsiveness between UIWebView and WKWebView because WKWebView has been introduced for a consistency matter between iOS and OSX. The underlying engine is Webkit in either way and it requires a lot of initialization.
The best solution I've found recent during years has been fading a WebView starting from a view with 0.1 alpha in which the url was loaded. Be careful to not start from 0.0 and do not have your webview detached from main view hierarchy because your url would not be loaded.
When didFinishLoading is called then you can fade it to 1.0 thus providing a better user experience.
Personally I don't like the UIWebView pool because I have experienced some memory troubles when maintaining it, especially on iOS 7 devices.

UIWebview slows down after a period of time

We have a complex app that uses a UIWebView to display some information at a certain point. We have an OpenGL layer that stops drawing while the UIWebview is displayed, and we're using about 128 Meg of ram (according to monitors). The page is about 10 screens worth of table, and is static content. Javascript is used on setup, but that's it.
We've noticed that the page loads and is responsive, and then after scrolling the view up and down a few times, the CPU hits about 18% - not in our code. This happens on DidReceiveMemory warning (though the device is not short of memory), so it feels like a garbage collector or something. The 18% then remains until the view is freed off. Returning to the view again and the newly created UIWebview will be responsive again, with the same behaviour of slowing down after a bit of brisk scrolling.
We clear the NSURLCache on didReceiveMemoryWarning (and give the OS back lots of ram). Does anyone have other suggestions, as the responsiveness drops off a cliff on older devices?
It turns out if you present the Renderbuffer from the OpenGL layer every frame while a UIWebView is visible, this slow down kicks in. The other instance we used a UIWebview we had paused the renderer, so it didn't matter
Ensuring that
glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
[m_pContext presentRenderbuffer:GL_RENDERBUFFER];
Does not run (or pausing the display link) fixed the problem for us. Hope it is useful to someone, as it has been puzzling us for days.

Resources