Search code examples
opengl-esuikitcore-animation

How to synchronize OpenGL drawing with UIKit updates


In our app we have UIScrollView above CAEAGLLayer. UIScrollView contains some UIViews (red rectangles). In CAEAGLLayer we draw white rectangles. Centers of white rectangles are the same as the centers of red rectangles. When UIScrollView scrolls, we update positions of white rectangles in CAEAGLLayer and render them.

We are getting the expected result: centers of white rectangles are always the same as centers of red rectangles.

But we can't synchronize updates of the CAEAGLLayer with the movement of the views inside UIScrollView. We have some kind of mistiming – red rectangles lag behind white rectangles.

Speaking roughly, we really want to make CAEAGLLayer lag together with the UIScollView.

We have prepared sample code. Run it on the device and scroll, and you will see that white rectangles (drawn by OpenGL) are moving faster than red ones (regular UIViews). OpenGL is being updated within scrollViewDidScroll: delegate call.

https://www.dropbox.com/s/kzybsyu10825ikw/ios-opengl-scrollview-test.zip

It behaves the same even in iOS Simulator, just take a look at the video: http://www.youtube.com/watch?v=1T9hsAVrEXw

Red = UIKit, White = OpenGL

Code is:

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView {
    // reuses red squares that are gone outside thw bounds
    [overlayView updateVisibleRect:CGRectMake(...)];
    // draws white squares using OpenGL under the red squares
    [openGlView updateVisibleRect:CGRectMake(...)];
}

Edit:

The same issue can easily be demonstrated in a much simplified sample. The working xcodeproj can be find at:

https://www.dropbox.com/s/vznzccibhlf8bon/simple_sample.zip

The sample project basically draws and animates a set of WHITE squares in OpenGL and does the same for a RED set of UIViews. The lagging can easily be seen between the red and white squares.


Solution

  • In fact, you can't synchronize them using current APIs. MobileMaps.app and Apple Map Kit use private property on CAEAGLLayer asynchronous to workaround this issue.

    Here is related radar: http://openradar.appspot.com/radar?id=3118401