Sync EAGLView Presentation with Resize Frame on iPhone

I have an EAGLView that I modify in an animation, and the animation is controlled by NSTimer , which calls the draw function. When I resize an EAGLView , I need to adjust the projection for viewing in order to maintain the aspect ratio of the content. The draw function is as follows:

 gameView.frame = newFrame; [gameView setFramebuffer]; [self updateProjection]; /* Drawing to the EAGLView, gameView, here, then... */ [gameView presentFramebuffer]; 

To accomplish this, however, the contents of the EAGLView seem to be "stepped" down the animation. When I record it and look at it frame by frame, it clearly indicates that the projection is adjusted, and then the image will be changed a very short time later (less than one frame of animation).

I suspect the reason is that the change in the gameView frame gameView delayed, and in the meantime, the updated framebuffer breaks through to the screen. I tried using CATransactions to update the frame right away, but since I was as if expecting a UIView change, it did nothing. I suppose I can change the EAGLView and leave a full EAGLView frame, but I am worried that this may leave me with synchronization problems elsewhere (say, with updates for any overlaid CALayers).

Does this sound like a reasonable assessment of the problem? How can I prevent this β€” that is, how can I better make sure that the framebuffer view matches the change in the actual EAGLView frame (and other CA elements)?

Thanks!

+4
source share
1 answer

I ran into a similar problem with a custom EAGLView that I wrote. The problem was that when the orientation was changed, the image changed and the content was stretched, and only after the animation the scene with the correct proportions was displayed.

I think your problem is the same, and I don’t think that you can get CoreAnimation to wait for your view to be updated before rendering the animation frame because of how it works (CA does not know the drawing mechanism of the view or layer on which it works).

But you can easily work around the problem: open the xib file containing the view, switch to the attribute pointer on the right. Select EAGLView (the same applies to GLKView ), and under the "View" - attribute "Mode". If you create the view programmatically, set the contentMode property.

This value describes the management of the contents of the view during animation. Until the buffer is displayed, the old scene will be changed in accordance with this mode; perhaps you can find a mode that matches the animation you need to achieve.

  • If you are concerned about the proportions, the content center mode may work, but the part of the scene that has not yet been displayed will appear empty during the animation.

  • Unfortunately, the redraw mode does not have to update the EAGLView : the view is actually redrawn, but potentially with the old contents of the color buffer. This is the problem of getting a buffer full at the right time.

  • You can try resizing and previewing a frame large enough to cover the entire animation before starting it; or you can try to display the frame on a UIImage , replace the view on the fly, animate it, place the EAGLView back, but this can seriously affect performance.

  • The way I solved my problem simply made EAGLView big enough.

  • As for mixing other CALayer s, as far as I tried, I did not find a synchronization problem; EAGLView updates, when possible, other layers. Just set the correct CAEAGLLayer properties if you use an alpha channel, and remember that blending layers every time OpenGL updates your scene can be expensive in terms of performance.

+1
source

All Articles