The two things that are happening when you press the Home-button are
applicationDidEnterBackground: returns your process is not
allowed to touch the GPU any more.Those two facts are not contradictory, because SpringBoard does not
expect your code to render anything for it at that moment – it simply
asks Core Animation to rasterise the CALayer tree that already exists.
For a normal UIView that is fine, because the last thing it drew is
still sitting in the layer.
For a CAEAGLLayer that is only true as long as the renderbuffer you
presented last is still alive. If you have already destroyed that
renderbuffer (or never rendered into the “new” size that Core Animation
lays out while preparing the snapshot) the layer is empty and you get the
console message you have seen:
Snapshotting a view that has not been rendered results in an empty snapshot.
In short: the problem is not that you are forbidden to draw – the problem is that you tear the layer down too early.
They finish every pending GL command in
applicationWillResignActive: / UIApplicationWillResignActiveNotification
(often by calling glFinish()), so that the current frame is complete.
They keep their EAGLContext, framebuffer and
renderbuffer alive while in the background.
They just do not use them until the app becomes active again.
They do not do any GL calls once
applicationDidEnterBackground: has returned.
Keeping the presented render-buffer around is enough for Core Animation
to create a clean snapshot.
Because the render-buffer contains a full-resolution image, Core
Animation can down-scale it for the other orientation, for Slide-Over,
Split-View, etc., so you do not get the ugly pixel-doubled snapshot you
are seeing now.
Some games prefer to show their title screen or their launch artwork
instead of the last rendered frame.
You can still do that without breaking the “no GL in the background”
rule:
• While you are still active (e.g. in
applicationWillResignActive:) render whatever you want to be
captured, presentRenderbuffer, then immediately overlay the OpenGL
view with an ordinary UIKit view (usually a full-screen UIImageView)
that contains the same bitmap.
UIKit views are rendered by the CPU, so they are perfectly legal in
the background.
• Remove that overlay again in
applicationDidBecomeActive: / applicationWillEnterForeground:.
This is the trick used by a lot of titles you see in the store.
• Do not issue any GL commands after
applicationDidEnterBackground:; the system may kill your app for
that.
• Do not release your framebuffer / renderbuffer / EAGLContext while
you are in the background unless you really need the memory.
If you do, Core Animation no longer has anything to snapshot.
// App delegate -----------------------------------------------
- (void)applicationWillResignActive:(UIApplication *)application
{
// 1. Finish the current frame.
[EAGLContext setCurrentContext:self.glView.context];
glFinish();
// 2. (Optional) render a title screen here, *still active*.
// 3. Keep every GL object alive – just don’t use them until we are active again.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Absolutely no OpenGL calls in here!
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Everything is still alive, just continue rendering.
}
With nothing more than “do not destroy the render-buffer before you enter the background” your snapshots will immediately look the same in both orientations and in Slide-Over / Split-View, and you are 100 % within Apple’s multitasking rules.
Was this answer helpful?
version: o3-2025-04-16
Status: UQ Validated
Validated: 8 months ago
Status: Needs Human Verification
Loading model reviews...
Loading reviews...