Apple has been traditionally very good at introducing new features you initially didn’t know you would desire. The new iPad (aka iPad 3) with the Retina display is one of those examples. What does this mean for your Adobe AIR applications? The bad news upfront: without modifications, your existing applications will look worse than on the iPad 1/2 (scaled), and a purely CPU rendered UI won’t scale to such a high resolution without dropping frames – the good news: there are solutions.
How to enable Retina support with AIR 3.2
Applications build with the iOS 5.1 SDK will automatically switch to Retina mode once they start on the iPad 3. Unfortunately by default AIR packages with a captive SDK, therefore AIR applications won’t switch to Retina on the iPad 3. Thankfully it is possible to package with an external SDK. Here is a detailed guide to the command line parameters, e.g. for automated build scripts. In Flash Builder, it’s even easier – the native extensions dialog features an iOS SDK option to define the path to the desired SDK.
During my tests (keep in mind this is not the official guide, nor is Retina support an official feature yet), I had to add a native extension to switch to the new SDK when targeting the “fast mode”, while the release build target worked without specifying one. Once configured, your application will launch automatically in Retina mode.
How to make your application perform well
The iPad retina resolution is 2048×1536, which is equivalent to 3.145.728 pixels. In comparison, the iPad 2 only had 786.432 pixels to worry about. The key to maintain smooth performance is to use the GPU as much as possible, since CPU rendering will reach its limits.
Stage3D based applications
Stage3D is fully GPU accelerated, meaning the rendering is offloaded to the hardware. If your application is designed with Stage3D, the Retina display shouldn’t cause any issues.
Here is an example of an Retina up-converted AIR application with StageVideo, N2D2 for the 3D UI, and StageWebView to display HTML5 content.
The video can’t physically demonstrate the high quality Retina display, but it looks stunning. It’s interesting to note that the StageWebView content automatically upgrades to Retina resolution as well.
In addition, here is an UI framework scrolling example based on Starling:
Flex Mobile
Flex Mobile is a challenging case, since it doesn’t support Stage3D, and by default the older renderModes “cpu” and “direct” use the CPU to draw the components. The very basic GPU mode (not Stage3D, renderMode “gpu”) was not recommended in the past, since it didn’t improve the performance of Flex Mobile applications. This is appears to be different with Retina, the performance boost of renderMode “gpu” is significant.
Again, it’s hard to capture Retina on a lower resolution video, but it demonstrates the overall scroll performance. My example is very basic, and performance could be different with more complex UIs (please share your results in case you run your own tests).
The last challenge with Flex Mobile is the DPI. Even though Flex Mobile is DPI sensitive, AIR 3.2 currently reports the wrong DPI for iPad 3, therefore the UI appears very small.
Thankfully the Retina resolution is easy to detect, and it’s possible to return the correct DPI with a minor extension of the RuntimeDPIProvider. Here is an example from iBr3nt.
package ui { import flash.system.Capabilities; import mx.core.DPIClassification; import mx.core.RuntimeDPIProvider; public class iPad3RuntimeDPI extends RuntimeDPIProvider { public function iPad3RuntimeDPI() { super(); } override public function get runtimeDPI():Number { var os:String = Capabilities.os; if(os.indexOf("iPad") != -1) { if(Capabilities.screenResolutionX >; 2000 || Capabilities.screenResolutionY >; 2000) { return DPIClassification.DPI_320; } else { return DPIClassification.DPI_160; } } else { return Capabilities.screenDPI; } } } } |
The last step is to overwrite the default runtimeDPIProvider with the extended class – don’t forget to define the applicationDPI to enable the DPI based scaling.
ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" runtimeDPIProvider="iPad3RuntimeDPI" applicationDPI="240" |
Conclusion
Even though not an automatic and integrated option within the tools yet, it’s possible to create Retina resolution applications with the current AIR runtimes today. The key is GPU acceleration. Keeping that in mind, even though renderMode “gpu” improves the Flex Mobile performance on Retina, it’s very basic in its functionality and performance. Stage3D has much better performance potential. Hopefully the Apache Flex community is able to port the Flex framework to Stage3D to unleash more of its potential.
Great write-up Jens. I’m glad my DPI code worked for you.
iBrent
@iBrent Thanks, works great ;-). AIR for Android initially had this issue too on certain high density devices, I saw this workaround before.
For anybody who’s used this, I still had a crazy amount of trouble when positioning popups, specifically trying to center them effectively.
PopUpManager.centerPopup(this) failed in the majority of cases as it centers in the containing display item. Using stage width would return 2048 pixels but the coordinate system was still in 0-1023 for some reason, so the easiest method I’ve found is to do this upon CreationComplete:
this.width = parent.width * 0.8;
this.x = parent.width * 0.1;
and likewise for the height & y.
@laceysnr In case this is a Flex application, I believe when the DPI scaling kicks in, it translates the “interior” coordinates to Retina. E.g. if the app is designed for 1024×768, it would scale 2x on retina using the same coordinates, even though the Stage reports double the size. Everything that uses the Stage dimensions as reference will have issues as result (e.g. StageView, StageWebView positioning). I’m not a Flex expert, but that is what I found when working with Retina.
@Jens Loeffler Yep, that’s what I found too which meant I couldn’t use the stage etc. to size and position the popups. I would have just used 1024×768 but our app needs to run on android devices too with different resolutions so this method I’ve found seems to work the best for now.
Great post ! Thanks !
Just a little thing to maintain DPI well for iPhone4
:
…
} else {
//return Capabilities.screenDPI;
return super.runtimeDPI;
}
…
in iPadRuntimeDPI