I'm currently creating a window system for XNA games from scratch. I'm developing primarily for Windows, but who knows what platforms I might support in the future. Feel free to answer if you know this for native Direct3D, since the performance semantics should be similar. If possible, consider what would change if the target platform was X-Box 360.
I'm making good progress, but now I am unsure on how to exactly render the windows. I came up with four approaches:
Just render all controls directly onto the screen. This is what I do now. Controls can be animated by blending between states as long as they are not semi-transparent. I did not find a good way to animate between an arbitrary number of states (suppose a button that is currently animating from button-up to button-down and from mouse-out to mouse-over, and then it is being disabled. It should smoothly blend from its last state to the new state. With this approach, this only works if one animation is played after the last one finished, or you'll have jumps in animation.
Render each top-level window and all controls into a render target, and then use that to render the top-level windows with semi-transparency onto the screen. This makes semi-transparency at top-level work and is easy to manage, but doesn't change the thing with the animations.
Render each control into a render target, which is only updated when the control becomes dirty (i.e. must animate or the text has been changed). This way, per-control semi-transparency would work.
Like the previous, but in addition to solve the animation problem have a second render target for each control. Whenever an animation starts, swap render targets, so we have the state when the animation starts, and blend it with the destination state into the other render target. This should not add overhead over the previous approach, we just had twice as many render targets, of which in any given frame only one would be rendered to (at maximum). But here comes the problem: For this to work, I would need to have the "old" render target preserve its contents. This should work with good performance on Windows, but appears to have a serious performance impact on X-Box 360. On the other hand, the "preserve" bit is only necessary while an animation is active.
And here come the actual questions. Anything that clarifies is welcome. With the performance questions, remember that this would just be the window system of a game - the game behind might use many render targets and suck up performance as well, and likely much more than the window system. Assume that we might have five top-level windows with 20-40 controls each on the screen in absolute worst-case.
- Which of these approaches, if any, would you recommend and why? Feel free, of course, to add another approach.
- Is there a performance impact when just having let's say 200 or 400 render targets available, provided that only maybe 20 of them are being rendered to each frame?
- Is the performance impact of PreserveContents really that bad on X-Box 360? How bad is it on Windows?
- The RenderTarget2D.RenderTargetUsage property can be written to. Is switching this at runtime a good idea, to enable PreserveContents only as needed?
- Would you (as a player) mind if control animations would jump in certain situations, like hovering over a button, moving the mouse out and then in again, so the "normal->hover" animation is played twice from the beginning because it is slower than you?