As I've been writing the Mesa C++ wrappers I've come across some dificulties posed by the way the interfaces are exported. As I progressed I started to realize I was loosing too much time and effort trying to fight the system, and the system in this case - Mesa - needs not to be fought, but adapted to the new needs. Note that the changes I propose aren't just to facilitate the C++ wrappers, they would give a more consistent and efficient interface for C drivers, and are very well in sync with other ongoing efforts on DRI (namely Keith Whitwell's vtxfmt and Ian Romanick's texmem).
1. In the last IRC meeting (relevant part of the log attached) I already focused on one of the aspects in Mesa's driver interfaces which wasn't very convenient: the use of private structure pointers as a mechanism for data inheritance. My proposal is to use structure compositing instead of private pointers. This has the benefits of: - reduced memory allocation overhead and less referencing - more consistency between the base and inherited structures (no more things like driver private texture data having a seperate life from Mesa's texture. - in C++ we can describe inherited classes from mesa substrucutres as easily as subclassing. This means that: - For every overloadable structure in Mesa, there is a function which takes a pointer to such structure and initializes it. - the driver is always the one who allocates the memory (as it's the only one who knows the full base+inhrited structure size), and has to call Mesa to initialize the data strutruture. For many structures, Mesa already has one of the above things. The biggest exception (and biggest advantage) is the texture structure. This is also the way that Ian has organized the texture structure in texmem branch, so it will fit nicely there. 2. On user space, the current drivers are structured (with some exceptions not relevent now) as follows: Client application | | v v glapi GLX | | v v Mesa DRI | | v v DRI_Driver | v Hardware And the driver has to fill a Mesa callback function table. But, as Keith recently said here, there is interest in having the drivers to deal with the glapi dispatch table directly, in other words: Client application | | v v glapi GLX : | | : | v : | DRI : | | : v v : DRI_Driver : ^ | : | | v v v Mesa Hardware That is, instead of Mesa acting as the middle man, it should act more as a library. This specificaly means that, instead of (phony names): userapp.c: glEnable(GL_TEXTURE); mesa.c: _mesa_Enable(enum) { // Do its thing here if(ctx->Driver.Enable) ctx->Driver.Enable(ctx, enum); } driver.c: RadeonEnable(ctx, enum) { // Do its thing here } It would be: userapp.c: glEnable(GL_TEXTURE); driver.c: RadeonEnable(enum) { // Do its thing here _mesa_Enable(ctx, enum) // ... or here } mesa.c: _mesa_Enable(enum) { // Do its thing here } Note that, according to the specific case, RadeonEnable may not even xist, or don't call _mesa_Enable at all. And no time would be wasted on doing unnecessary stuff (such as tables lookups, or maintaining irrelevant state). And this may be controled on run-time via glapi. The drawback here is that usually mesa verifies if the state changed before notifying the driver, and this would be lost here - I really don't know how much relevant this is. 3. Make the glapi get the current ctx pointer and pass it to the functions. If I understood correcly, the drivers will have a per-context dispatch table, which is on thread local storage (TLS). If so, this means that the glapi already knows the current context pointer, so it can pass it to the gl API entries, therefore using one less lookup to the TLS. This would also make the C++ simpler, and the ctx could be seen as an abstract class, where the disptatch table were member functions. Of course that the C++ call conventions don't allow this be just like that, but from the C++ drivers point of view, it would be so. But this is not the more important. Finally I would like to discuss in which CVS repository the C++ framework and these ideas would go. My preference would be to do it on a branch based on the embbeded branch on Mesa CVS. (This was also briefly discusses in the last meeting). A side note: if/when these things hit the DRI/Mesa trunks, if nobody else wants to share it with, I take the resposability to update all existing Mesa/DRI drivers. In any case, the changes can be a little time consuming, but will be straightforward. José Fonseca
<jfonseca> keithw: Is there any reason for "inheritence" in Mesa being achieved in most cases via private pointers instead of putting the base struct as the first field of the derived struct, and hence sharing the same base pointer? <idr> jfonseca: I think that's so that the "base" can change in size without breaking things. <idr> jfonseca: Also, then each "class" only has to allocate a chunk of memory for its data. <keithw> jfonseca: No - it's just the way it is <jfonseca> keithw: The reason why I'm asking is that I'm considering "standardize" Mesa in the later approach for consistency and simplification. This will not only simplify the C++ bindings, but yield less allocations, as IDR noticed. <keithw> jfonseca: The base class thing does get to be a pain if you try & build deep inheritance that way. The Xt widget library springs to mind. <keithw> jfonseca: But for mesa, I don't think it would be a problem. <idr> keithw: I guess there are the same binary compat. issues that you have with sharing things between libGL.so and the client-driver or the X server and the X driver. <jfonseca> keithw: You mean for the allocation. <keithw> idr: Yes, but binary compatibility is a recent concept. <keithw> jose: Just generally Xt was a pain. <jfonseca> keithw: Becuase for using is actually simpler, as less references are needed. <keithw> jfonseca: It's probably true. <jfonseca> keithw: Anyway, I'm thinking in doing this while maintining source compatability, i.e., simply add the _mesa_init_* functions which don't exist already, and keep the private pointers. <idr> keithw: k. <keithw> jfonseca: Sounds good. I'm keen to see the results. <keithw> jfonseca: Brian may have more to say on the design choices... <jfonseca> keithw: I'm going to use the CreateTexture driver function again for this (which was dead so far), so that the driver is called for the allocation of the texture, and call mesa back to initialize the base struct. <keithw> jfonseca: Where is that going to be called from? <jfonseca> keithw: Sure. I'm going to send this to Mesa3d-dev. (Let me copy&paste now before the history gets lost...) <jfonseca> keithw: The texture structure. When mesa wants to create a texture, it must ask the driver to allocate the memory (only the driver knows the full size of the inherited struct), and to initialize the texture private data. Currently these two things (mesa & driver init) are completly seperate, code- and time-wise. <jfonseca> keithw: I think that by doing every thing this manner, things will be more consistent and efficient, bothe for C drivers and C++ bindings. <keithw> jfonseca: OK, so this is from texobj.c somewhere -- _mesa_GenTextures, _mesa_BindTexture? <jfonseca> keithw: That's right. <keithw> jfonseca: It's reasonable. There have been all sorts of bugs because those two structs lead separate lives... <idr> jfonseca: This sounds like what I do in the texmem code. <jfonseca> idr: Really? I didn't knew you've been changing mesa internals there. <idr> jfonseca: I don't. But each driver inherits from driTextureObject (in texmem.h) in a similar why to what you're talking about. <idr> jfonseca: With your changes we'd have mesaTextureObject -> driTextureObject -> r200TextureObject. <jfonseca> idr: Ah... Ok. But between mesa<->driver things still use private pointers. <jfonseca> idr: Ok. Nice. <idr> jfonseca: Yes. One of the fields of driTextureObject is a pointer to the gl_texture_object from Mesa. <jfonseca> Ok. This changes take to another related subject, which is where to host the CVS repository of the C++ framework to start making these changes. I'm inclined towards using a branch based on embedded-0-1-branch in Mesa CVS, becausse it's smaller, has everything needed, and already has doxygen documentation which connects nicely to the C++ framework docs. Any comments? <idr> jfonseca: I'd rather have it as a branch of the DRI tree. Is it a good idea to have a branch of a branch? :) <keithw> idr, jfonseca: I'm interested in the idea of moving driver development to a smaller repository in the future - with the embedded branch as an idea of what that repository might look like <keithw> . <jfonseca> idr: It's *much* simpler to work with the embedded branch - everything is just one directory level away. <idr> jfonseca: Fair enough. <idr> jfonseca: I'm not leaning to hard either way. :) <fxkuehl> jfonseca: At some point you're going to want to merge your Mesa changes to the Mesa trunk. I guess it'll be more work then. <jfonseca> keithw: That seems good - the DRI repository isn't a full one anyway. One issue which has to be considered is the integration back in the X CVS. <keithw> One thing to realize is that there are now two environments that I can build the drivers for -- XFree86/DRI and fbdev/miniglx. These are mesa drivers first & foremost and the integration with a given windowsystem is actually a secondary choice. <keithw> jfonseca: I would put the drivers in extras/Mesa. <jfonseca> fxkuehl: Not with the C++ framework, since it will be basically add a new subdirectory, and a few changes in Mesa source. I.e., the changes will be fairly well contained. But don't know about general development. <keithw> jfonseca: That would make it clear to XFree people that patches should be submitted to Mesa/DRI/wherever-the-new-tree-lives. <jfonseca> keithw: And what about changes in the DDX? There is no infrastructure for that in embedded-branch... <keithw> fxkuehl: The new tree would subsume *both* the dri and mesa trees <keithw> jfonseca: We'd have to keep the existing DRI tree for infrastructure work, or come up with a new mechanism. <keithw> jfonseca: Basically the proposal is: "Move the 3d drivers into extras/Mesa". Everything else follows from that. <jfonseca> keithw: Isn't there a paradox in your two previous lines? <keithw> jfonseca: I preanswered your question <keithw> jfonseca: Do you see what I mean? <jfonseca> keithw: not really... :/ The paradox is you saying to fxkuehl "The new tree would subsume *both* the dri and mesa trees", and then "We'd have to keep the existing DRI tree for infrastructure work"... <keithw> The new tree would subsume *both* the dri xc/lib/GL subtree and the mesa tree. <keithw> jfonseca: (trying to clarify) <fxkuehl> keithw, jfonseca: are you talking about starting a new DRI CVS repository, or just a new subdir in the current DRI CVS tree? <keithw> jfonseca: The new tree would be imported to XFree cvs in the extras/Mesa directory. So the drivers would get linked in along with the rest of mesa source. <jfonseca> keithw: I think I'm understanding, but I don't see how it would simplify things if you keep the current DRI CVS, as you'd have to merge things back everytime you wanted to change the DDX or the infrastructure... <keithw> fxkuehl: A new tree somewhere. <jfonseca> Ok. It'd be easy, since it would live under mesa. <keithw> jfonseca: OK. <jfonseca> I think Brian should do the Mesa directory reorganization he mentioned before. <fxkuehl> keithw: then the new tree would be the place for the client side driver development only. What about the kernel and X-server? <keithw> fxkuehl: The existing DRI tree would continue and be the place for server and probably kernel module development. <keithw> fxkuehl: Hmm. Actually there are good reasons to consider splitting the kernel module out -- as it is no longer used exclusively by XFree86 (ie miniglx drivers use it too, now). <idr> keithw: Shouldn't the kernel modules at least be in the same repository as the rest of the 3D driver? <keithw> idr: It makes sense, I think. <keithw> jfonseca: The mesa directory reorg would be a good time to make the transition.