pioneerspacesim/pioneer — pull request #1003 by robn (2012-02-22 10:51:18+00:00)
Title: Renderer state capture

Based on an idea in IRC today. Not for merge (yet). For use in cases where the current renderer state must be saved and restored (eg #1001).

Very simple. Each renderer provides a `PushState()` and `PopState()` that will somehow save and restore renderer state. For OpenGL its the normal matrix/attribute push/pop; for something else the renderer might have to carry its own stack. Whatever.

Client that needs to preserve state calls `renderer->CaptureState()`. It gets back an object representing the current state of the stack. When that object is destroyed, the state is restored. Constructing the object this way allows the following pattern:

```
{
ScopedPtr state(renderer->CaptureState());

renderer->SetViewport(...)
renderer->SetTransform(...)
renderer->DrawFoo(...)
}
```

When `state` goes out of scope, `ScopedPtr` deletes it and the state is restored.

The possible problem/quirk I see with this is that `State` does not really represent a renderer "state", but is really just a handle on a push/pop pair. Its not possible to "restore" the state, only pull it back from the stack. If two of these objects are retrieved and deleted out of order, state will not be restored to that of the last one. If there was a practical way to retrieve the entire GL state then this could be coded around (with something slightly different to `PushState()` and `PopState()` - probably `GetState()` and `SetState()`).

Really, this is probably just a problem of naming. I don't think that capturing the state and _not_ restoring it shortly after is something you'd want to do. I can't find a good name for the class that conveys the semantics in one or two words.

I'm not entirely sure what to do about clients leaking and/or storing a pointer to these returned state objects. But, to quote @johnbartholomew, "as long as the easiest way to use the thing is the right way then you've got a good start". Given we're the ones using this, and saving state for all renderers becomes as simple as copying that single `ScopedPtr...` line above, you've really got to go out of your way to screw things up.

Feedback please. Should I continue with this?