From: Keith W. <ke...@va...> - 2001-02-15 17:50:15
|
Gareth, Here's a braindump regarding runtime installation of the api of a tnl module into the libGL dispatch table. There are two tricks to this; efficiency and correctness... Correctness is complicated by the fact that it is anticipated that drivers may not know which tnl module they want to use until after a call to 'gl_update_state()' has completed. If we wait until we are inside the tnl code before triggering gl_update_state(), it becomes necessary to detect if the tnl function that called gl_update_state() is still attached to the dispatch table, and if not to invoke the new one. This is ugly, and actually quite complex to get right. All in all it would be preferable to ensure 'gl_update_state()' is called prior to entering the tnl code, and to ensure that the correct tnl module is always invoked. Efficiency concerns are that installing 20 or 30 function pointers on a potentially very frequent basis is likely to be a performance issue in itself. My basic idea was to perform the installation in a lazy fashion, as individual entrypoints are invoked by clients. A set of stub functions would be initially installed into dispatch, which: 1) determine whether it is necessary to call gl_update_state(), and if so, do so. 2) install the 'real' version of the function, eg _tnl_Begin(), into the dispatch table, and pass control to that function. Consider this invarient: When inside any tnl api function, ASSERT(ctx->NewState == 0). The question then is how/when to uninstall driver tnl functions and restore the stubs. It seems at least two triggers are required: - A directive from the driver to install a new tnl module. - Any statechange (!!) This seems like overkill -- there are a lot of statechanges. It may be necessary instead to require that drivers only swap tnl modules in statechange callbacks, rather than from ctx->Driver.UpdateState(). Then the calls to gl_update_state() can remain in things like _tnl_DrawElements(), but they will be guarenteed to never alter the dispatch tables, or require forwarding of the call back to dispatch. ... But ... As I said above, the driver may not know until gl_update_state() is called whether it is able to use an accelerated tnl module. Specifically it may need to reference one of the values computed in gl_update_state() to make it's choice. Thus drivers would have to swap to the neutral tnl module in response to any dangerous state change callbacks, and have the neutral vertex format specifically ask the driver to choose (validate) the installed tnl module, after calling gl_update_state(). An equivalent strategy would be to have the driver register a bitmask of 'dangerous' statechanges, and only swap to the neutral tnl module on those statechanges. However this seems to introduce unnecessary overhead into each core statechange operation. ====================================================================== So, a second attempt: - Forbid swapping tnl modules inside ctx->Driver.UpdateState(). - Keep calls to gl_update_state() inside tnl modules. - Add a new 'ctx->Driver.ValidateTnlModule()' callback. - Create a neutral tnl module which contains functions which: - check if gl_update_state() needs to be called. - check if ctx->Driver.ValidateTnlModule() needs to be called. - installs the appropriate driver tnl function into dispatch. - finally forwards the call to the newly installed driver function. - Experiment with bitmask vs. callback strategies for swapping back to the neutral tnl module. Then the mechanism of swapping back to the neutral tnl module needs to be explored. As I've outlined a lazy method for swapping the driver tnl module in, a function at a time, it should be possible to keep track of which dispatch entries have been modified (from the neutral baseline), and only swap back in the portions of the neutral tnl module which have been swapped out. This might typically amount to 5 entries or so. As you can see, there's a fair bit of experimentation left to get this right... There may be yet another approach which bypasses some of these issues. I haven't given much thought to it, but it may be possible to allow the driver to swap dispatch entries from gl_update_state(), even when called from inside a tnl module, providing that the lost data is somehow rescued later on, perhaps by calling a special 'fallback' routine. I guess DrawArrays etc would still need to forward... Keith |