This has been bugging me recently. It is quite straightforward to put together an OpenGL ES app that supports both portrait and landscape.
But during autorotation, the system seems to just forcibly stretch the render buffer to the new dimensions once, autorotate, and then call the usual -layoutSubviews
-> -resizeFromLayer:
etc. so the drawables can be adjusted to the new viewport dimensions.
Most apps I've seen that support both portrait and landscape seem to settle for this easy approach. But I wonder if I can do better...
Perhaps I should intercept the autorotation before it happens (using UIViewController
's usual methods), "expand" once the render buffer to a perfect square of the longest screen size (e.g., 1136px x 1136px on an iPhone 5) - so that it 'bleeds' off screen, perform the autorrotation (no renderbuffer size change and hence no stretching, just as when you switch between e.g. two landscape orientations), and finally adjust the framebuffer again to dispose the invisible, "wasted" margins off screen? (of course I could have a square framebuffer all along, but that would be inefficient fillrate-wise)
Any suggestions? Any better way to accomplish this that I haven't thought about?
EDIT
I modified my -resizeFromLayer:
code as follows:
CGRect bounds = [layer bounds];
// Enlarge layer to square of the longest side:
if (bounds.size.width < bounds.size.height) {
bounds.size.width = bounds.size.height;
}
else{
bounds.size.height = bounds.size.width;
}
[layer setBounds:bounds];
// Adjust size to match view's layer:
[_mainContext renderbufferStorage:GL_RENDERBUFFER
fromDrawable:(CAEAGLLayer*) [_view layer]];
// Query the new size:
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
// (etc., you know the drill...)
...And it works! As it stands right now, I have a wasteful, off-screen-bleeding square renderbuffer all along, but this is just a proof of concept. On production code, I would perform said resizing-to-square just before autorotation, and resize back to screen dimensions afterwards.