This keeps coming up. There’s nothing wrong with Cocoa’s graphics toolbox, it uses CoreGraphics, which is what Carbon used also. Core Graphics is hardware accelerated and is blisteringly fast.
As point of reference, it possible to have full screen animations (in Retina, nearly 5mp per frame) run at 245 FPS, within Xojo.
The biggest slowdowns I’ve encountered are as follows:
#1 Overlapping controls, simply put, don’t do it! Cocoa’s smarter, but if you have EraseBackground checked, a simply refresh on one control will cause all controls overlapped to refresh.
#2 When drawing images, try to avoid drawing large images down, this takes precious time, instead cache them at the right size.
#3 When drawing text, if the text is to be drawn ‘trimmed’, consider trimming it before rather than during the drawing.
#4 Gradients, use CGGradient or NSGradient declares.
#5 Shadows, use the shadow property of the CGContext or NSShadow.
#6 Pay attention to the areas() property of the canvas, there’s no need to redraw everything if only a small portion is being updated.
#7 Consider using CGLayers (via declares) for caching as these as super fast and Retina ready.
#8 Retina is twice the resolution of a normal screen, which means that it can take 4 times as long to update each frame.
#9 Use invalidate( x, y, w, h, false ) if you only need to update a specific area, in combination with #6.
#10 actually time how long it takes to draw, work on doing as little as possible in the ‘Paint’ event. If your application spends too long in the paint event, you’ll be skipping frames.
#11 OS X uses coalescing to keep the refresh rate at 60 fps, the same as most displays, if you want higher fps, there’s a plist option for it.
#12 Understanding the difference between invalidate and refresh will make a difference. Invalidate, simply marks the NSView as dirty and needs drawing again. Most likely this will occur on the same event loop, but it may not. You can call invalidate as many times as you like in a method, it’ll only happen once. Refresh on the other hand, forces the view to update there and then, you call it ten times in a method and it’ll fire the Paint event ten times, however you’ll only see the update on the screen once, unless you also force the window to refresh.
Most of the time, use invalidate, but Refresh is useful when doing blocking animation (i.e. you want a control to animate, but don’t want the user to instigate an action while the animation is occurring).
#13 If you can, use the vector shapes drawRect, drawOval rather than images. Don’t forget you can use complex shapes also.
#14 Lastly if you have to draw a lot of images, loaded from disk, use NSImage (via MacOSLib, MBS or RetinaKIt). NSImage is highly cached and Retina ready.
For those comparing OS X graphics to Windows, it’s like Apple’s and Oranges… Apple use a form of PostScript for their display language (which is why every OS X application can output PDF), it’s double buffered, window and screen.
Windows, just erm… Lets any application do what ever it wants and AFAIK is still only Bitmap based. For gaming, it’s an advantage over a Mac.
