Search code examples
iphoneopengl-essplash-screenflickerdefault.png

iPhone OpenGL First Frame Black


My application is openGL based and supports ES 1.1 as well as ES 2.0.

My view controller has a view that is an instance of EAGLView (as per Apple's sample code), which in turn uses different "renderer" objects for either ES 1.1 or 2.0 (pretty much standard for anyone who has used the Xcode samples).

I use CADisplayLink to update the screen. I am targeting a minimum of iOS 4.0+ so there should be no problem.

On startup, the first frame after the startup image (Default.png) is shown, is rendered black. A one-frame, annoying black flicker in between.

If, before making the window Key and Visible I "fake" one round of my update/render cycle (so as to have the back buffer rendered to as well, and not empty), the flicker disappears but only when using ES 2.0.

I have kEAGLDrawablePropertyRetainedBacking set to YES, but neither value seems to make any difference.

When using ES 1.1, the flicker remains. The only difference is that, if I perform the "refresh" prior to making the window visible the screen flickers to the color I specify with glClearColor(). But if I don't pre-refresh, the flicker is invariably black.

I have seen discussions about this problem time and again on the Cocos2d forums, but even there the problem seems to always come back and bite you after every new hack the come up with.

Nevertheless I am using plain-OpenGL ES (NOT Cocos2d or any other library), and yet can't find anyone with a similar problem no matter how I search the web...

Any hints?


Solution

  • The cause of the problem is pretty much as you've diagnosed — when the relevant view controller is immediately finished loading (ie, when the Default.png image is removed), it doesn't have any content yet. CADisplayLink doesn't trigger until the end of that frame.

    I think the correct thing to do would be to do a full redraw and present in viewDidLoad:, since that's where you're meant to set up bits of the view that weren't in the NIB. That shouldn't introduce a frame of latency in either rendering path, assuming they're implemented as a single or double buffer.

    Supposing there is some other undiagnosable problem going on, in one case I had an app where it wasn't possible to draw a frame ahead of time due to the nature of code beyond my control (being a cross-platform port for which I was doing just the glue code). So what I did was add a fullscreen UIImageView containing Default.png on top of my first view controller. I then waited one frame and removed the UIImageView. That should work, whatever your render loop.