Smooth OpenGL animation possible, even if main thread blocks?
Smooth OpenGL animation possible, even if main thread blocks?
- Subject: Smooth OpenGL animation possible, even if main thread blocks?
- From: Markus Hanauska <email@hidden>
- Date: Fri, 25 Jun 2010 20:19:25 +0200
Let me shortly describe the current situation: We have a window and inside this window is a layer-hosting NSView. This view is supposed to permanently display a never ending OpenGL animation. Why did we use CALayers for that? For no specific reason, it just sounded like starting with 10.5 CALayers is the way to go and maybe one day we also want to make use of CALayer animation capabilities, so why not? So we did as Apple told us: Subclass CAOpenGLLayer and override the appropriate methods. To not overload the main thread, all calculations are performed on a background thread, that updates all necessary parameters of our CALayer, when done, it waits some time (to avoid the animation is running too fast) and finally updates the content of the CALayer by calling setNeedsDisplay on main thread (performSelectorOnMainThread). This works pretty well, we are quite happy with the results.
Now to our problem: If the main thread is blocking for a short while or temporarily not running its runloop, which can happen for various reasons, the animation starts to "stutter". It doesn't even have to block for a very long amount of time, it only needs to block longer than the time difference between two animation updates. This is by far not long enough to get a spinning mouse cursor for this application. We try to do everything asynchronously and never block the main thread for one millisecond longer than absolutely necessary, but nonetheless only reacting to all kind of user input can sometimes make the animation less smooth than we would like it to be. Of course that is expected, because without the main loop performing the CALayer update, no update will happen and when the next update is performed, any number of animation frames might have been skipped.
What we want is that this animation is always smooth, no matter how busy the main thread might be. Even if it blocks for a whole second it should be smooth, at least as long as the CPU has enough resources to keep the animation updating on time (otherwise there is no way to avoid that frames are skipped, but if the system is at its limits, that is absolutely okay). With normal NSViews, you can also perform updates from background threads, as far as I understand the documentation, by directly locking focus from the background thread (lockFocusIfCanDraw), directly drawing to the view and unlocking focus again. There seems no way to lock focus for a CALayer and no way to paint into and thus update the content of a CALayer from any other thread, but the main thread.
So what are we supposed to do? Is there something I'm overlooking here or should we maybe stop using CALayers and instead use NSOpenGLView or maybe even manage our own OpenGL Context, render into a background buffer (e.g. some kind of image) and then directly paint this image from within the background thread into the view whenever we want to? If so, what image is most effective for such a task? NSImage, CGImage, CIImage? Any advise is highly appreciated.
--
Markus Hanauska
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden