State management in D3D... is currently kind of a mess.
Stefan D. posted a message about this some time ago, but I can't find it
right now...
- some states are applied immediately (via Set* calls)
- some are applied at draw time (like shaders, textures, transforms, ...)
- some are recorded into a stateblock structure, and applied when the
app says apply().
- the GL code is all over the place, tightly coupled to the d3d code.
===============================
There's a number of projects going on at the moment, from what I understand:
- Roderick is working on making wined3d -> wgl
- Stefan D. has expressed concern about multithreaded d3d (where the
D3D device state is shared, but not necessarily the GL one - or can GL
contexts be shared between multiple threads?)
- I'm trying to get FBOs to work, where the FBO needs to be bound once
both the render and stencil target have been assigned (that's 2 calls
from the app in any order) - i.e I need those states to be applied in a
delayed fashion, before draw
- Henri Verbeet wants multiple render target support added to that
(meaning the FBO needs to be bound once *all* render targets are
assigned in addition to the depth/stencil one).
================================
All of the above have a common theme - better state management is
needed, with more encapsulation, and better separation between D3D and GL.
So, let's come up with a plan, and try to implement it. How about we
redesign the stateblock object like this:
- remove deltas. I.E. if a SetLightEnable() command is sent, fetch the
light, enable it, then save the light back - store only state, and no
deltas.
This should make the recording stateblock (updateStateBlock) the same
as the initial device stateblock, which stores states
- provide a uniform internal interface for accessing states inside the
stateblock - like:
SetState(stateblock, ID_XYZ, (void*) state_data);
GetState(stateblock, ID_XYZ, (void**) state_data);
CaptureState(stateblock, ID_XYZ);
ApplyState(stateblock, ID_XYZ);
ID_XYZ could be an individual state, or a "trigger" keyword, which will
refer to a whole group of states.
Those would be private functions in addition to the standard interface.
- provide a fn pointer table inside the stateblock [ which can be
directed to OGL or WGL or AGL ],
which, for each ID_XYZ, maps a get and set function using the same
interface
- move all device.c GL code into those functions
- now all device.c Get* and Set* requests will do is:
- error checking
- recording into updateStateBlock
- or writing to stateBlock (which may be applied later, at our
discretion).
- apply() would just loop through all the IDs and call the corresponding
function pointer if the states are marked dirty (we'll keep the 'dirty'
field)
- capture() would do the same in the get* direction.
- new object can be instantiated per device, or per device per thread to
address multithreading.
It could have an associated glContext, and can be locked as necessary.
- it would use ideas from the d3d9 test framework for stateblock, except
of course more competently written, and cleaner :)