tags:

views:

679

answers:

3

I took this WPF-VS2008 ScreenSaver template and started to make a new screen saver. I have some experience with winForms-platform (GDI+) screen savers, so i am little bit lost with WPF.

  1. Background-element for my screen saver is Canvas.
  2. A DispatcherTimer tick is set to 33 msec, which is ~ 30 FPS.
  3. Background-color is just one huge LinearGradientBrush.
  4. On the screen I have (per available screen, on my local computer i have 2) n-Ellipses drawn with randomly-calculated (Initialization) Background colors + Alpha channel. They are all in Canvas's Children collection.
  5. I'm moving those Ellipses around the screen with some logic (every DispatcherTimer tick). I make a move per-ellipse, and then just call Canvas.SetLeft(...) and Canvas.SetTop(...) for each Ellipse.
  6. If N (number of Ellipses) is higher > 70-80, i begin to notice graphics slow-downs.

Now, i wonder, if there is anything i could do to improve the graphic-smoothness when choosing higher N-values ? Can I "freeze" "something" before moving my Ellipses and "un-freeze" "something" when i'm finished ? Or is there any other trick i could do?

Not that i would be too picky about mentioned performance drop downs - becouse when N==50, everything works smooth as it should. Even if Ellipses are ALL in the SAME place (loads of transparency stuff), there are no problems at all.

A: 

It is not possible to unfreeze something once it has been frozen (although a copy of the object is unfozen by default). Double buffering is also enabled by default in WPF so you cannot gain here.

Once way to improve performance if not already done is to use geometry objects such as Ellipse Geometry rather than shapes if you do not need to the all of the events as these are lighter weight.

I also have found this MSDN Article Optimizing Performance: 2D Graphics and Imaging that suggests a CachingHint may help along with some other tips.

Finally ensure that you are using the latest service pack one as it has many performance improvements outlined here

John
Acutally what i meant with "Ellipses" - My Canvas childrens are EllipseGeometry-instances.I guess there are no-more GDI+ like-tricks (when you could play little bit with styles-doubleBuffering-etc.) in WPF?
I have updated my answer with a few more ideas that may help
John
A: 

You will improve performance if you call the Freeze method on objects that inherit from Freezable - brushes for example.

The reason is that Freezable supports extra change notifications that have to be handled by the graphics system, when you call Freeze the object can no longer change and so there are no more change notifications.

For an example of this notification system, if you create a brush, use it to paint a rectangle (for example) and then change the brush the on-screen rectangle will change color.

Nir
+3  A: 

Have you tried rendering in the CompositionTarget.Rendering event, rather than in a timer? I've gotten impressive performance in a 3D screen saver when using the Rendering event and doing my own double buffering. (See http://stuff.seans.com/2008/08/21/simple-water-animation-in-wpf/ , http://stuff.seans.com/2008/08/24/raindrop-animation-in-wpf/ , and http://stuff.seans.com/2008/09/01/writing-a-screen-saver-in-wpf/ )

Sean Sexton
Thx for info. Will read the articles and try to do it "your" way :).
Sean, i tried the "CompositionTarget.Rendering" method, but i didn't see any performance boost at all. Then i found another tip/trick. Setting IsHitTestVisible to FALSE for all the Shapes i am using (of course i don't need user-interaction with the screenSaver). That helped little bit!
Great, glad to hear that the hit test change helped!
Sean Sexton