From: F. <j_r...@ya...> - 2003-03-21 19:57:34
Attachments:
irc.txt
|
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 |
From: Keith W. <ke...@tu...> - 2003-03-21 20:29:00
|
Jos=E9 Fonseca wrote: > 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 wel= l > in sync with other ongoing efforts on DRI (namely Keith Whitwell's > vtxfmt and Ian Romanick's texmem). >=20 >=20 > 1. In the last IRC meeting (relevant part of the log attached) I alread= y > 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 t= o > 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. >=20 >=20 > 2. On user space, the current drivers are structured (with some > exceptions not relevent now) as follows: >=20 > Client application > | | > v v > glapi GLX > | | > v v > Mesa DRI > | | > v v > DRI_Driver > | > v > Hardware > =20 > And the driver has to fill a Mesa callback function table. But, as Keit= h > recently said here, there is interest in having the drivers to deal > with the glapi dispatch table directly, in other words: >=20 > Client application > | | > v v > glapi GLX > : | | > : | v > : | DRI > : | | > : v v > : DRI_Driver > : ^ | > : | | > v v v > Mesa Hardware >=20 > That is, instead of Mesa acting as the middle man, it should act more a= s > a library. This specificaly means that, instead of (phony names): >=20 > userapp.c: glEnable(GL_TEXTURE); >=20 > mesa.c: _mesa_Enable(enum) { > // Do its thing here > if(ctx->Driver.Enable) > ctx->Driver.Enable(ctx, enum); > } >=20 > driver.c: RadeonEnable(ctx, enum) { > // Do its thing here > } >=20 > It would be: >=20 > userapp.c: glEnable(GL_TEXTURE); >=20 > driver.c: RadeonEnable(enum) { > // Do its thing here > _mesa_Enable(ctx, enum) > // ... or here > } >=20 > mesa.c: _mesa_Enable(enum) { > // Do its thing here > } >=20 This was the initial idea for the mesa 3.5 rework (which resulted in thin= gs=20 like the swrast,tnl,etc. modules). I didn't go this far as I felt the 3.= 5=20 structure was enough to bite off in a single chunk... Anyway, the slight trouble you get with this is error checking. Who does= it?=20 How does RadeonEnable check if _mesa_Enable succeeded? Also, error=20 checking is tied in with the general structure of the function a lot of t= he=20 time. Anyway, the code in api_validate.c is a fragment of my original=20 thoughts on this, but won't work so well where error checking can't be ea= sily=20 seperated from the rest of the functionality. Continuing with the Enable() example, it would be nice to duplicating avo= id=20 the 'switch' on the enum in both RadeonEnable and _mesa_Enable. Keith |
From: F. <jrf...@tu...> - 2003-03-21 22:09:36
|
On Fri, Mar 21, 2003 at 08:29:02PM +0000, Keith Whitwell wrote: > José Fonseca wrote: > >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 > > } > > > > This was the initial idea for the mesa 3.5 rework (which resulted in > things like the swrast,tnl,etc. modules). I didn't go this far as I felt > the 3.5 structure was enough to bite off in a single chunk... Were you thinking going the full way now for the vtxfmt rework? (Sorry for asking and not looking to the code myself, but I don't know exactly what's its state and where to start, and I'm also with my hands full now as you know) > Anyway, the slight trouble you get with this is error checking. Who does > it? That's a choice that RadeonEnable has: if it builds upon _mesa_Enable then _mesa_Enable can do that for him. If _mesa_Enable is never called then is its responsability to set the error. > How does RadeonEnable check if _mesa_Enable succeeded? In many cases you can simply check the error status. If ctx->ErrorValue hasn't enough (or updated) info about the error, we can extend it elsewhere (e.g., ctx->ReturnValue which would be set on zero on success). > Also, error checking is tied in with the general structure of the > function a lot of the time. Anyway, the code in api_validate.c is a > fragment of my original thoughts on this, but won't work so well where > error checking can't be easily seperated from the rest of the > functionality. I see. In some cases most of the code in a API is validation, and the solution you show in api_validate is the most apropriate, but others are which aren't that simple. > Continuing with the Enable() example, it would be nice to duplicating > avoid the 'switch' on the enum in both RadeonEnable and _mesa_Enable. NOTE: I'm thinking out loud in the next paragraphs, so you may want to skim quickly through them and read only the last code snippets. The only way I see to avoid the duplication of the switch is to break the glEnable in glEnableTexture, glEnableFoo, ... which is not a bad thing. We could have a function table (in the context or passed as and argument to a function _mesa_do_enable which would do the 'switch') whose the index would be 'enum', and there would only by one implementation of glEnable. RadeonEnableTexture would call _mesa_enable_texture, and so on... On other places this is way too much trouble for a small 'switch', and we could simply duplicate the code in Mesa's 'case' statements and eliminate the call to the Mesa API completly. Note that the state is stored in the context already is exported to the drivers, so everytime we change the state we need to check if the drivers aren't broken, but I confess that I'm still not very confortable doing this, since if we add derived state, things will silently be broken. Things would be easier if all these glEnableFoo were inlined and defined in a header, and _mesa_Enable and RadeonEnable would use them as suitable. There would be duplication of the switch statement in the code, but only one of them would be executed at run-time. Overall, if we consider that we need to support new OpenGL extensions everytime, and that we want to do that without having to modify each driver, then the only viable solutions are either in the line of api_validate.c or breaking glEnable in smaller functions. The others suck badily. Passing functions tables in C++ is a PITA if we want to model these functions as methods... so I think api_validate is the way to. Still, in many cases is enough just to check the error code and let Mesa do the validation by itself. That is: ----------- userapp.c: glEnable(GL_TEXTURE); driver.c: RadeonEnable(enum) { _mesa_Enable(ctx, enum) if ( !ctx->ReturnValue ) switch() { case GL_ONLY_A_SUBSET_OF_THE_POSSIBLE_ENUMS: // Do its thing here break; } } mesa.c: _mesa_Enable(ctx, enum) { // Do its thing here ctx->ReturnValue = error_condition ? 1 : 0; } ----------- Or when we need pre-validation: ----------- userapp.c: glEnable(GL_TEXTURE); driver.c: RadeonEnable(enum) { if ( !_mesa_validate_Enable(ctx, enum) ) { switch() { case GL_ONLY_A_SUBSET_OF_THE_POSSIBLE_ENUMS: // Do its thing here break; } _mesa_Enable_novalidate(ctx, enum) } } mesa.c: _mesa_Enable(ctx, enum) { if ( !_mesa_validate_Enable(ctx, enum) ) { // Do its thing here _mesa_Enable_novalidate(ctx, enum) } } _mesa_Enable_novalidate(ctx, enum) { // No need to validate here switch () { // Do its thing here } } ----------- José Fonseca |
From: Keith W. <ke...@tu...> - 2003-03-21 23:49:27
|
Jos=E9 Fonseca wrote: > On Fri, Mar 21, 2003 at 08:29:02PM +0000, Keith Whitwell wrote: >=20 >>Jos=E9 Fonseca wrote: >> >>>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 >>> } >>> >> >>This was the initial idea for the mesa 3.5 rework (which resulted in=20 >>things like the swrast,tnl,etc. modules). I didn't go this far as I fe= lt=20 >>the 3.5 structure was enough to bite off in a single chunk... >=20 >=20 > Were you thinking going the full way now for the vtxfmt rework? (Sorry > for asking and not looking to the code myself, but I don't know exactly > what's its state and where to start, and I'm also with my hands full no= w > as you know) No, it's primarily a rework of the tnl module & it's interfaces. Plus=20 removing some cruft. >=20 >>Anyway, the slight trouble you get with this is error checking. Who do= es=20 >>it?=20 >=20 >=20 > That's a choice that RadeonEnable has: if it builds upon _mesa_Enable > then _mesa_Enable can do that for him. If _mesa_Enable is never called > then is its responsability to set the error. >=20 >=20 >>How does RadeonEnable check if _mesa_Enable succeeded?=20 >=20 >=20 > In many cases you can simply check the error status. If ctx->ErrorValue > hasn't enough (or updated) info about the error, we can extend it > elsewhere (e.g., ctx->ReturnValue which would be set on zero on success= ). Yes - just pointing out one of the things that I'd come across on the sam= e path... >=20 >>Also, error checking is tied in with the general structure of the >>function a lot of the time. Anyway, the code in api_validate.c is a >>fragment of my original thoughts on this, but won't work so well where >>error checking can't be easily seperated from the rest of the >>functionality. >=20 >=20 > I see. In some cases most of the code in a API is validation, and the > solution you show in api_validate is the most apropriate, but others ar= e > which aren't that simple. Correct. >=20 >>Continuing with the Enable() example, it would be nice to duplicating=20 >>avoid the 'switch' on the enum in both RadeonEnable and _mesa_Enable. >=20 >=20 > NOTE: I'm thinking out loud in the next paragraphs, so you may want to > skim quickly through them and read only the last code snippets. Actually, I'm trying not to do that with your posts anymore... > The only way I see to avoid the duplication of the switch is to break > the glEnable in glEnableTexture, glEnableFoo, ... which is not a bad > thing. We could have a function table (in the context or passed as and > argument to a function _mesa_do_enable which would do the 'switch') > whose the index would be 'enum', and there would only by one > implementation of glEnable. RadeonEnableTexture would call > _mesa_enable_texture, and so on... I like this idea too. The ideal division for me would be along attribute= =20 group lines. Similarly you can split up glPushAttrib and glPopAttrib. T= hen=20 (with the init/update-state directions from recent embedded commits) attr= ibute=20 state management starts to look "modular"... > On other places this is way too much trouble for a small 'switch', and > we could simply duplicate the code in Mesa's 'case' statements and > eliminate the call to the Mesa API completly. =20 Wasn't the idea to reduce duplication? > Note that the state is > stored in the context already is exported to the drivers, so everytime > we change the state we need to check if the drivers aren't broken, but = I > confess that I'm still not very confortable doing this, since if we add > derived state, things will silently be broken. You mean if we add some new derived state, then the duplicated code in th= e=20 drivers won't know about it & so won't keep it uptodate? > Things would be easier if all these glEnableFoo were inlined and define= d > in a header, and _mesa_Enable and RadeonEnable would use them as > suitable. There would be duplication of the switch statement in the > code, but only one of them would be executed at run-time. Or if each enable enum were in a header. Or if we just eat the function = call. > Overall, if we consider that we need to support new OpenGL extensions > everytime, and that we want to do that without having to modify each > driver, then the only viable solutions are either in the line of > api_validate.c or breaking glEnable in smaller functions. The others > suck badily. Passing functions tables in C++ is a PITA if we want to > model these functions as methods... so I think api_validate is the way > to. Still, in many cases is enough just to check the error code and let > Mesa do the validation by itself. That is: I think you're seeing some of the reasons I didn't go all the way with th= is in=20 3.5... > ----------- > userapp.c: glEnable(GL_TEXTURE); >=20 > driver.c: RadeonEnable(enum) { > _mesa_Enable(ctx, enum) =20 > if ( !ctx->ReturnValue ) > switch() { > case GL_ONLY_A_SUBSET_OF_THE_POSSIBLE_ENUMS: > // Do its thing here > break; > } > } >=20 > mesa.c: _mesa_Enable(ctx, enum) { > // Do its thing here > ctx->ReturnValue =3D error_condition ? 1 : 0; > } > ----------- That's not really any better than the current system. I'd rather see (fo= r=20 enable) : _mesa_enable( enum ) { get_context(); fn =3D get_enable_fn_from_hash( enum ); if (fn) fn( enum, GL_TRUE ); else raise_error(); } Then: bool radeon_enable_texture( enum e, bool b ) { if (_mesa_enable_texture( e, b )) { RADEON_FIRE_VERTICES(); } } bool radeon_enable_polygon_stipple( e, b ) { ... } void init() { register_enable( GL_TEXTURE_1D, radeon_enable_texture ); register_enable( GL_TEXTURE_2D, radeon_enable_texture ); register_enable( GL_POLYGON_STIPPLE, radeon_enable_polygon_stipple ); } This also works nicely with extensions that may or may not be turned on. > Or when we need pre-validation: >=20 > ----------- > userapp.c: glEnable(GL_TEXTURE); >=20 > driver.c: RadeonEnable(enum) { > if ( !_mesa_validate_Enable(ctx, enum) ) { > switch() { > case GL_ONLY_A_SUBSET_OF_THE_POSSIBLE_ENUMS: > // Do its thing here > break; > } > _mesa_Enable_novalidate(ctx, enum) > } > } >=20 > mesa.c: _mesa_Enable(ctx, enum) { > if ( !_mesa_validate_Enable(ctx, enum) ) { > // Do its thing here > _mesa_Enable_novalidate(ctx, enum) > } > } >=20 > _mesa_Enable_novalidate(ctx, enum) { > // No need to validate here > switch () { > // Do its thing here > } > } >=20 I think this would turn into a pretty big mess over time... Keith |
From: F. <jrf...@tu...> - 2003-03-22 01:07:25
|
On Fri, Mar 21, 2003 at 11:49:35PM +0000, Keith Whitwell wrote: > José Fonseca wrote: > >Were you thinking going the full way now for the vtxfmt rework? (Sorry > >for asking and not looking to the code myself, but I don't know exactly > >what's its state and where to start, and I'm also with my hands full now > >as you know) > > No, it's primarily a rework of the tnl module & it's interfaces. Plus > removing some cruft. > > >In many cases you can simply check the error status. If ctx->ErrorValue > >hasn't enough (or updated) info about the error, we can extend it > >elsewhere (e.g., ctx->ReturnValue which would be set on zero on success). > > Yes - just pointing out one of the things that I'd come across on the > same path... > > >In some cases most of the code in a API is validation, and the > >solution you show in api_validate is the most apropriate, but others are > >which aren't that simple. > > Correct. > > >NOTE: I'm thinking out loud in the next paragraphs, so you may want to > >skim quickly through them and read only the last code snippets. > > Actually, I'm trying not to do that with your posts anymore... Well, thanks! :) > >The only way I see to avoid the duplication of the switch is to break > >the glEnable in glEnableTexture, glEnableFoo, ... which is not a bad > >thing. We could have a function table (in the context or passed as and > >argument to a function _mesa_do_enable which would do the 'switch') > >whose the index would be 'enum', and there would only by one > >implementation of glEnable. RadeonEnableTexture would call > >_mesa_enable_texture, and so on... > > I like this idea too. The ideal division for me would be along attribute > group lines. Similarly you can split up glPushAttrib and glPopAttrib. > Then (with the init/update-state directions from recent embedded commits) > attribute state management starts to look "modular"... I also like the division you made there - one can now make a change in a attribute group without having to change half places. > >On other places this is way too much trouble for a small 'switch', and > >we could simply duplicate the code in Mesa's 'case' statements and > >eliminate the call to the Mesa API completly. > > Wasn't the idea to reduce duplication? There is the source code duplication, and the run-time execution of duplicate code paths (which I thought was you main concern). This idea avoids later, but not the former. In other words, although the Mesa code is duplicated on the driver, only one of the instances is run on a single API call - [usually] the driver instance. > > Note that the state is > >stored in the context already is exported to the drivers, so everytime > >we change the state we need to check if the drivers aren't broken, but I > >confess that I'm still not very confortable doing this, since if we add > >derived state, things will silently be broken. > > You mean if we add some new derived state, then the duplicated code in > the drivers won't know about it & so won't keep it uptodate? Exactly. > >Things would be easier if all these glEnableFoo were inlined and defined > >in a header, and _mesa_Enable and RadeonEnable would use them as > >suitable. There would be duplication of the switch statement in the > >code, but only one of them would be executed at run-time. > > Or if each enable enum were in a header. Not very orthodox, but surely doable and effective. > Or if we just eat the function call. With a #define, for example. It seems OK for all circumstances I can think of. But as the problem is that the 'switch' code is in the drivers, so everytime you wanted to add a new 'case' to the 'switch' statement you had to add it to all drivers, so that they include a new header/#define/inline whatever... > I think you're seeing some of the reasons I didn't go all the way with > this in 3.5... Indeed. > > ... > > That's not really any better than the current system. I'd rather see > (for enable) : > > _mesa_enable( enum ) > { > get_context(); > fn = get_enable_fn_from_hash( enum ); > if (fn) fn( enum, GL_TRUE ); > else raise_error(); > } > > Then: > > bool radeon_enable_texture( enum e, bool b ) > { > if (_mesa_enable_texture( e, b )) { > RADEON_FIRE_VERTICES(); > } > } > > bool radeon_enable_polygon_stipple( e, b ) > { > ... > } > > void init() > { > register_enable( GL_TEXTURE_1D, radeon_enable_texture ); > register_enable( GL_TEXTURE_2D, radeon_enable_texture ); > register_enable( GL_POLYGON_STIPPLE, radeon_enable_polygon_stipple > ); > } > > This also works nicely with extensions that may or may not be turned on. I really liked your idea of the 'get_enable_fn_from_hash' function, because it allows for the C++ drivers to avoid using a C function table for the hash, it would replace that same function by another which would use internally a C++ method functions table, therefore avoiding having to write wrappers for each function in the hash. (PS: I know that we can always resort to using normal C functions in C++ but it would definetly be better if we use methods which can be inherited from other classes, as many of the things usually done in this sort of routines are done by all drivers thus can be shared). > >Or when we need pre-validation: > > > > ... > > I think this would turn into a pretty big mess over time... At least it's good we have some options. I don't think it's wise to suddenly change all APIs to one method or another, as it may show to be a bad choice after all. glEnable and glGet are clearly good candidates for experimenting with 'get_enable_fn_from_hash' thing. José Fonseca |
From: Brian P. <br...@tu...> - 2003-03-22 17:59:32
|
Keith Whitwell wrote: > Jos=E9 Fonseca wrote: >> 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 >> =20 >> And the driver has to fill a Mesa callback function table. But, as Kei= th >> 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 >> } >> >=20 > This was the initial idea for the mesa 3.5 rework (which resulted in=20 > things like the swrast,tnl,etc. modules). I didn't go this far as I=20 > felt the 3.5 structure was enough to bite off in a single chunk... >=20 > Anyway, the slight trouble you get with this is error checking. Who=20 > does it? How does RadeonEnable check if _mesa_Enable succeeded? Also= ,=20 > error checking is tied in with the general structure of the function a=20 > lot of the time. Anyway, the code in api_validate.c is a fragment of= =20 > my original thoughts on this, but won't work so well where error=20 > checking can't be easily seperated from the rest of the functionality. First, be aware that glEnable is one of the simplest functions in Mesa - = it=20 doesn't serve as a good representation of the big picture. Keith mentioned error checking. In the case of glEnable, all we have to = do is=20 check that we're not inside glBegin/glEnd and record an error if the enum= =20 parameter is invalid. Pretty simple. Other state-change functions are far more complicated. For example, the=20 gl[Copy]Tex[Sub]Image() functions require LOTS of error checking. The=20 texture_error_check() function alone is more than 270 lines long! The nice thing about the current system is that by time the driver's Enab= le or=20 TexParameter, or TexImage command is called we've already error-checked a= ll=20 the parameters and calling context. I'm pretty sure that we don't want t= o=20 deal with GL error checking in all the drivers. You might consider writing helper functions that just do error checking f= or=20 all the GL functions. But that would be a _lot_ of functions. And in so= me=20 instances it's difficult to isolate all the error checking at the beginni= ng of=20 a GL function (thus you may need error_check_foo_part1(),=20 error_check_foo_part2(), etc.) There'd be a lot of code duplication too. When testing for GL_INVALID_EN= UM,=20 for example, you'd effectively have to do the "switch (enumParam)" twice = -=20 once to error check, a second time to set state. > Continuing with the Enable() example, it would be nice to duplicating > avoid the 'switch' on the enum in both RadeonEnable and _mesa_Enable. The idea of implementing glEnable() with a hash table and having a bunch = of=20 little enum-specific enable/disable functions is interesting but I'm not = sure=20 it's the right solution. Would glEnable be the only function that used that mechanism? That would= make=20 it a bit of an odd-ball. I'd rather see a consistant interface for all=20 state-change functions. What we have now is pretty good in that regard. Consider _mesa_TexParameterfv() or similar functions if you persue this p= ath. Note: I'm not trying to discourage you. I think it's great that you're t= aking=20 a critical look at this stuff. -Brian |
From: Brian P. <br...@tu...> - 2003-03-22 17:43:03
|
OK, I'm getting caught up on email and have read through this thread.=20 Comments follow, and in subsequent messages... Jos=E9 Fonseca wrote: > 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 wel= l > in sync with other ongoing efforts on DRI (namely Keith Whitwell's > vtxfmt and Ian Romanick's texmem). >=20 >=20 > 1. In the last IRC meeting (relevant part of the log attached) I alread= y > 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 t= o > 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. I'm in favor of this. A while back I introduced code to do this with=20 GLcontext, GLframebuffer, and GLvisual. The OSMesa driver uses containme= nt to=20 "derive" struct osmesa_context from GLcontext. Extending this to texture objects and texture images would be a good foll= ow-on. In design pattern terms, the drivers will have to provide "factories" whi= ch=20 generate texture object and image instances. The factory functions will = have=20 to be registered with core Mesa since core Mesa often has to take the=20 initiative to allocate new objects. I may start working in this direction soon. > 2. On user space, the current drivers are structured (with some > exceptions not relevent now) as follows: >=20 > Client application > | | > v v > glapi GLX > | | > v v > Mesa DRI > | | > v v > DRI_Driver > | > v > Hardware > =20 > And the driver has to fill a Mesa callback function table. But, as Keit= h > recently said here, there is interest in having the drivers to deal > with the glapi dispatch table directly, in other words: >=20 > Client application > | | > v v > glapi GLX > : | | > : | v > : | DRI > : | | > : v v > : DRI_Driver > : ^ | > : | | > v v v > Mesa Hardware >=20 > That is, instead of Mesa acting as the middle man, it should act more a= s > a library. As Keith has said, this is the direction he started going back with Mesa = 3.5.=20 It kind of turns things inside-out conceptually, and people won't "get = it"=20 right away. The idea is that the hardware driver runs the whole show; the driver trea= ts=20 core Mesa as a collection of subsystems (state tracking, s/w rasterizatio= n,=20 s/w TCL, etc) which provide services to the driver. Going with this approach, it appears that the notion of the driver regist= ering=20 callback functions with Mesa (as seen in dd.h) is kind of backward. Unfortunately, we've currently got a bit of a mix of these different styl= es in=20 Mesa right now. We also have a system of dirty bits which track state ch= anges=20 and indicate when derived state must be recomputed or set. One could con= sider=20 taking that to the extreme and elimining most driver callbacks altogether. [The reality is this stuff is complicated and the perfect solution has ne= ver=20 been obvious. We just have to evolve things as best we can as we go alon= g.] > This specificaly means that, instead of (phony names): >=20 > userapp.c: glEnable(GL_TEXTURE); >=20 > mesa.c: _mesa_Enable(enum) { > // Do its thing here > if(ctx->Driver.Enable) > ctx->Driver.Enable(ctx, enum); > } >=20 > driver.c: RadeonEnable(ctx, enum) { > // Do its thing here > } >=20 > It would be: >=20 > userapp.c: glEnable(GL_TEXTURE); >=20 > driver.c: RadeonEnable(enum) { > // Do its thing here > _mesa_Enable(ctx, enum) > // ... or here > } >=20 > mesa.c: _mesa_Enable(enum) { > // Do its thing here > } >=20 > 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. I'll address this in another message. > 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-contex= t > 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. >=20 > 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. Unfortunately, we can't change this without breaking the current libGL /=20 driver ABI. I'm _really_ hesitant to go there. > 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). >=20 > 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 tim= e > consuming, but will be straightforward. You're welcome to create a new branch in the Mesa CVS tree to do your=20 experiments. Just clear it with me before you merge anything into the tr= unk! :-) -Brian |
From: Keith W. <ke...@tu...> - 2003-03-22 18:54:57
|
Brian Paul wrote: >=20 > OK, I'm getting caught up on email and have read through this thread.=20 > Comments follow, and in subsequent messages... >=20 > Jos=E9 Fonseca wrote: >=20 >> 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 we= ll >> 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 alrea= dy >> 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 (an= d >> 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. >=20 >=20 > I'm in favor of this. A while back I introduced code to do this with=20 > GLcontext, GLframebuffer, and GLvisual. The OSMesa driver uses=20 > containment to "derive" struct osmesa_context from GLcontext. >=20 > Extending this to texture objects and texture images would be a good=20 > follow-on. >=20 > In design pattern terms, the drivers will have to provide "factories"=20 > which generate texture object and image instances. The factory=20 > functions will have to be registered with core Mesa since core Mesa=20 > often has to take the initiative to allocate new objects. >=20 > I may start working in this direction soon. >=20 >=20 >> 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 >> =20 >> And the driver has to fill a Mesa callback function table. But, as Kei= th >> 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. >=20 >=20 > As Keith has said, this is the direction he started going back with Mes= a=20 > 3.5. It kind of turns things inside-out conceptually, and people won't= =20 > "get it" right away. >=20 > The idea is that the hardware driver runs the whole show; the driver=20 > treats core Mesa as a collection of subsystems (state tracking, s/w=20 > rasterization, s/w TCL, etc) which provide services to the driver. >=20 > Going with this approach, it appears that the notion of the driver=20 > registering callback functions with Mesa (as seen in dd.h) is kind of=20 > backward. >=20 > Unfortunately, we've currently got a bit of a mix of these different=20 > styles in Mesa right now. We also have a system of dirty bits which=20 > track state changes and indicate when derived state must be recomputed=20 > or set. One could consider taking that to the extreme and elimining=20 > most driver callbacks altogether. >=20 > [The reality is this stuff is complicated and the perfect solution has=20 > never been obvious. We just have to evolve things as best we can as we= =20 > go along.] >=20 >=20 >=20 >> 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 o= n >> doing unnecessary stuff (such as tables lookups, or maintaining >> irrelevant state). And this may be controled on run-time via glapi. Th= e >> drawback here is that usually mesa verifies if the state changed befor= e >> notifying the driver, and this would be lost here - I really don't kno= w >> how much relevant this is. >=20 >=20 > I'll address this in another message. >=20 >=20 >> 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-conte= xt >> 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 tha= t, >> but from the C++ drivers point of view, it would be so. But this is no= t >> the more important. >=20 >=20 > Unfortunately, we can't change this without breaking the current libGL = /=20 > driver ABI. I'm _really_ hesitant to go there. Oh wow, I missed this. (I've been sleeping really badly lately & everyth= ing's=20 kindof hazy) You really don't want to do this. The right solution is the one Gareth's= been=20 persuing for specialized fast TLS for GL, that brings the cost of these=20 lookups down to almost zero. In any case, this solution would be slower than our current one as it wou= ld=20 involve constructing a new stack frame for the dispatch call, or somehow=20 modifying the existing one. ... Hmm... I suppose you could stick the ctx = value=20 in a register instead of putting it on the stack. But the other point is -- the dispatch functions don't retrieve the conte= xt,=20 they retreive the active dispatch table, which is a completely different=20 variable, so the proposed savings don't really exist. There are TWO TLS variables: Current context, Current dispatch table, a= nd=20 they're effectively independent. Oh yes, and for the most highly optimized API functions (radeon_vtxfmt_X8= 6.S),=20 we don't need to retreive the Context value anyway -- it's hardcoded into= =20 runtime generated code. Keith |
From: F. <jrf...@tu...> - 2003-03-22 19:23:57
|
On Sat, Mar 22, 2003 at 06:55:08PM +0000, Keith Whitwell wrote: > Brian Paul wrote: > >Unfortunately, we can't change this without breaking the current libGL / > >driver ABI. I'm _really_ hesitant to go there. > > Oh wow, I missed this. (I've been sleeping really badly lately & > everything's kindof hazy) > > You really don't want to do this. The right solution is the one Gareth's > been persuing for specialized fast TLS for GL, that brings the cost of > these lookups down to almost zero. > > In any case, this solution would be slower than our current one as it > would involve constructing a new stack frame for the dispatch call, or > somehow modifying the existing one. ... Hmm... I suppose you could stick > the ctx value in a register instead of putting it on the stack. > > But the other point is -- the dispatch functions don't retrieve the > context, they retreive the active dispatch table, which is a completely > different variable, so the proposed savings don't really exist. > > There are TWO TLS variables: Current context, Current dispatch table, > and they're effectively independent. I see. > Oh yes, and for the most highly optimized API functions > (radeon_vtxfmt_X86.S), we don't need to retreive the Context value anyway > -- it's hardcoded into runtime generated code. Uuhh... neat! BTW, I suppose you meant radeon_vtxfmt_x86.c as I couldn't find radeon_vtxfmt_X86.S anywhere). Now I have to think how can I use this idea on the C++ framework... Anyway, as I said to my reply to Brian, this issue is not as urgent as the other things. Thanks for the pointer. Also, I can't help thinking that some of these tricks wouldn't be necessary if the OpenGL standard had chosen to pass opaque pointers (i.e., handles) to contexts and textures, instead of using concepts such as "current context" and "texture names", but this is OT anyway. José Fonseca |
From: Keith W. <ke...@tu...> - 2003-03-22 19:33:02
|
Jos=E9 Fonseca wrote: > On Sat, Mar 22, 2003 at 06:55:08PM +0000, Keith Whitwell wrote: >=20 >>Brian Paul wrote: >> >>>Unfortunately, we can't change this without breaking the current libGL= /=20 >>>driver ABI. I'm _really_ hesitant to go there. >> >>Oh wow, I missed this. (I've been sleeping really badly lately &=20 >>everything's kindof hazy) >> >>You really don't want to do this. The right solution is the one Gareth= 's=20 >>been persuing for specialized fast TLS for GL, that brings the cost of=20 >>these lookups down to almost zero. >> >>In any case, this solution would be slower than our current one as it=20 >>would involve constructing a new stack frame for the dispatch call, or=20 >>somehow modifying the existing one. ... Hmm... I suppose you could stic= k=20 >>the ctx value in a register instead of putting it on the stack. >> >>But the other point is -- the dispatch functions don't retrieve the=20 >>context, they retreive the active dispatch table, which is a completely= =20 >>different variable, so the proposed savings don't really exist. >> >>There are TWO TLS variables: Current context, Current dispatch table, = =20 >>and they're effectively independent. >=20 >=20 > I see. >=20 >=20 >>Oh yes, and for the most highly optimized API functions=20 >>(radeon_vtxfmt_X86.S), we don't need to retreive the Context value anyw= ay=20 >>-- it's hardcoded into runtime generated code. >=20 >=20 > Uuhh... neat! BTW, I suppose you meant radeon_vtxfmt_x86.c as I couldn'= t > find radeon_vtxfmt_X86.S anywhere). Now I have to think how can I use > this idea on the C++ framework... Anyway, as I said to my reply to > Brian, this issue is not as urgent as the other things. Thanks for the > pointer. radeon_vtxtmp_x86.S holds the templates, radeon_vtxfmt_x86.c insantiates = them.=20 It's a bit messy but does the trick. > Also, I can't help thinking that some of these tricks wouldn't be > necessary if the OpenGL standard had chosen to pass opaque pointers > (i.e., handles) to contexts and textures, instead of using concepts suc= h > as "current context" and "texture names", but this is OT anyway. Yes. Someone's pointed out that X has too many context variables whereas= GL=20 has too few. The right number would be one, and we could abandon a lot o= f=20 these coding tricks. Of course, having none makes for a nice clean external interface thats pr= oven=20 popular with coders. Keith |
From: Allen A. <ak...@po...> - 2003-03-25 00:28:17
|
On Sat, Mar 22, 2003 at 07:24:15PM +0000, Jos=E9 Fonseca wrote: | Also, I can't help thinking that some of these tricks wouldn't be | necessary if the OpenGL standard had chosen to pass opaque pointers | (i.e., handles) to contexts and textures, instead of using concepts suc= h | as "current context" and "texture names", but this is OT anyway. The history behind the design goes something like this. 3D drawing operations require a lot of state information. (Much more than is typical for OS I/O services or 2D graphics.) In the Olden Days fast memory was hideously expensive, so there wasn't much hardware support for multiple sets of state. It made sense to expose the state to the application, which could then help minimize the number of unnecessary state changes. It also made sense to design the API so that it was hard for app developers to accidentally invoke expensive state updates or update optimizations. If the API had been designed to pass a "current context" handle as an argument to each OpenGL command, the OpenGL library would have to detect when a new context had been used, then "diff" the current and new contexts to generate an efficient set of state updates. Just checking a cache for the context used on the last command involves a fetch from thread-local storage, and state-diffing is a pretty slow process. A better approach seemed to be to fetch the current context from thread-local storage in the first place, and isolate state-diffing to a relatively heavyweight "context change" operation that would have to be requested explicitly. The current-context approach and the separate dispatch table were both influenced by experience with X11, which itself was influenced by experience with early versions of Windows. (And other systems that I don't recall at the moment.) In retrospect, it might have been nice to expose the dispatch table to the application (perhaps like COM interfaces). That could eliminate one level of indirection and it might handle extensions more cleanly. But it introduces new problems, and I'm not sure about the tradeoffs. Allen |
From: Keith W. <ke...@tu...> - 2003-03-25 08:25:55
|
Allen Akin wrote: > On Sat, Mar 22, 2003 at 07:24:15PM +0000, Jos=E9 Fonseca wrote: > | Also, I can't help thinking that some of these tricks wouldn't be > | necessary if the OpenGL standard had chosen to pass opaque pointers > | (i.e., handles) to contexts and textures, instead of using concepts s= uch > | as "current context" and "texture names", but this is OT anyway. >=20 > The history behind the design goes something like this. >=20 > 3D drawing operations require a lot of state information. (Much more > than is typical for OS I/O services or 2D graphics.) In the Olden Days > fast memory was hideously expensive, so there wasn't much hardware > support for multiple sets of state. It made sense to expose the state > to the application, which could then help minimize the number of > unnecessary state changes. >=20 > It also made sense to design the API so that it was hard for app > developers to accidentally invoke expensive state updates or update > optimizations. If the API had been designed to pass a "current context= " > handle as an argument to each OpenGL command, the OpenGL library would > have to detect when a new context had been used, then "diff" the curren= t > and new contexts to generate an efficient set of state updates. Just > checking a cache for the context used on the last command involves a > fetch from thread-local storage, and state-diffing is a pretty slow > process. A better approach seemed to be to fetch the current context > from thread-local storage in the first place, and isolate state-diffing > to a relatively heavyweight "context change" operation that would have > to be requested explicitly. Ah yes, I hadn't thought about that aspect of it. That's pretty compelli= ng. Keith |
From: F. <jrf...@tu...> - 2003-03-22 19:14:55
|
On Sat, Mar 22, 2003 at 10:38:12AM -0700, Brian Paul wrote: > > OK, I'm getting caught up on email and have read through this thread. > Comments follow, and in subsequent messages... > > José Fonseca wrote: > ... > > I'm in favor of this. A while back I introduced code to do this with > GLcontext, GLframebuffer, and GLvisual. The OSMesa driver uses > containment to "derive" struct osmesa_context from GLcontext. Hmm... hence the existence _mesa_init_{context,framebuffer,visual}. That's what I use now in the C++ wrappers too. > Extending this to texture objects and texture images would be a good > follow-on. > > In design pattern terms, the drivers will have to provide "factories" > which generate texture object and image instances. The factory functions > will have to be registered with core Mesa since core Mesa often has to > take the initiative to allocate new objects. Exactly. One of such factories (for textures) will be ctx->driver.CreateTexture, which isn't used now. > I may start working in this direction soon. Great. > > ... > > As Keith has said, this is the direction he started going back with Mesa > 3.5. It kind of turns things inside-out conceptually, and people won't > "get it" right away. > > The idea is that the hardware driver runs the whole show; the driver > treats core Mesa as a collection of subsystems (state tracking, s/w > rasterization, s/w TCL, etc) which provide services to the driver. > > Going with this approach, it appears that the notion of the driver > registering callback functions with Mesa (as seen in dd.h) is kind of > backward. > > Unfortunately, we've currently got a bit of a mix of these different > styles in Mesa right now. We also have a system of dirty bits which > track state changes and indicate when derived state must be recomputed or > set. One could consider taking that to the extreme and elimining most > driver callbacks altogether. That's what I'm considering, but there will always have to be a few callbacks: - the factories you mentioned above - a few hardware abstractions for software TCL/rasterization (most noticeably, triangle primitives and framebuffer access) > [The reality is this stuff is complicated and the perfect solution has > never been obvious. We just have to evolve things as best we can as we > go along.] I know, but the mere fact that we all appear to be in sync makes me more confident that we must be on the rigth track. > > ... > > >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. > > Unfortunately, we can't change this without breaking the current libGL / > driver ABI. I'm _really_ hesitant to go there. I understand. This isn't very important (the points above were ordered by decreasing importance, and simultaneously in the order I plan to tackle them) and it isn't still very clear if it would yield any significant advantages for the C++ framework. I would like to avoid having a redirection call, but it seems almost impossible (except perhaps with some voodoo assembly and some luck with the C++ ABI). Anyway, an extra redirection call is nothing compared with a well structured C++ driver framework, so I'll leave this concern to a later time. > You're welcome to create a new branch in the Mesa CVS tree to do your > experiments. Thanks. > Just clear it with me before you merge anything into the > trunk! :-) Of course! ;-) José Fonseca |