On Tue, 27 Feb 2001, Brian S. Julin wrote:

> 
> On Tue, 27 Feb 2001, Christoph Egger wrote:

> > > Right, and the order that the resources appear in the list is the
> > > order of importance, so suppose you wanted to say this:
> > > 
> > > "I want to use 640x480 at the highest bit depth I can get, but I 
> > > definitely need a sprite even if it means using a lower bit depth.
> > > And an off-screen scratch area would be nice, but is not necessary."
> > > 
> > > You would have a linked list in this order:
> > > 
> > > (Resource with type RT_SPRITE) -->
> > > (Resource with type RT_FRAME with the ggi_mode set to 640x480/GT_AUTO) -->
> > > (Resource with type RT_SWATCH) --> 
> > > NULL
> > > 
> > > The function that does the work might look ahead in the list for
> > > example to choose a better VRAM layout, but it would always satisfy
> > > the requirements of the entries at the top of the list first.  You
> > > can also put more than one RT_FRAME resource in -- this:
> > > 
> > > (Resource with type RT_SPRITE) -->
> > > (Resource with type RT_FRAME with the ggi_mode set to 640x480/GT_8BIT) -->
> > > (Resource with type RT_SWATCH) --> 
> > > (Resource with type RT_FRAME with the ggi_mode set to GGI_AUTO/GT_AUTO) -->
> > > NULL
> > > 
> > > Means:
> > > 
> > > "I absolutely need a sprite, and I need at least 640x480x8, and I want
> > > a swatch.  Better than 8bit colors and more resolution would be nice, 
> > > but I prefer to have the swatch even if it means I only get 640x480x8."
> > 
> > I know, what you want. I have tried to thought this deeply out.
> > 
> > As a result I can say, you can NOT do this WITHOUT having at least
> > one thread in each (non-)extension like libovl, libblit, libxmi,
> > libbse, etc. And this would eat everything up, what GGI gains out of
> > the hardware, except you have a SMP-machine with 4 CPU's or more...
> 
> Hmm... I think we're reading different editions of the same book...  

Maybe.

> I don't see any need for any threads.

Well, you are thinking about an "advanced" user, who uses the
low-level-API. See below.

> But to clarify my last few emails, most of my suggestions are for
> long term expansion of GAlloc.  For the immediate short term, we
> would only need to implement the on-the-spot functionality, where
> a single feature is requested at a time with the video mode
> already having been set with ggiSetMode, it is allocated, and the
> necessary information for the higher level libraries is provided,
> and the higher level libraries use this information to build one
> of their objects.  All with a single higher level library
> function call.  This is all you need to worry about right now to
> get the structure up.  Since this will likely be ALPHA software
> for a while, adding the stuff to the GAResource_t later won't
> disrupt things too much.
> 
> But to look ahead, what we would do in the libs like libOVL is
> have two functions, one on-the-spot function, and another that
> simply adds a resource to the "extended mode request".  So the
> advanced programmers could do something like this *instead of*
> calling the regular ggiCheckMode/ggiSetMode:

Right. As you said in a former mail: libGalloc has something like a
supercharged ggi(S|G)etMode-functions.

> ggiGAInit(vis);
> ggiOVLInit(vis);
> ggiMISCInit(vis);
> 
> ggi_GAResource_t mymode;
> /* Put 640x480x8 first in the requested feature list */
> mymode = ggiGASimpleGraphModeAddRequest(640, 480, GT_8BIT);
> /* The accesses to ->next could actually be dome with
>    convenience functions, I left them this way for clarity. */
> /* Put the ability to wait for vertical retrace in the feature list. */
> mymode->next = ggiMISCAddRequest(GAT_WAITRETRACE);
> /* Put a request for a hardware pointer (of any size) in the feature list. */
> mymode->next->next = 
>       ggiOVLOverlayAddRequest(GAT_SPRITE_POINTER, GGI_AUTO, GGI_AUTO);
> if (GGIGACheck(vis, mymode)) {
>       ggiGADeallocRequests(mymode->next->next);
>       mymode->next->next = NULL
>       if (GGIGACheck(vis, mymode)) {
>               fprintf(stderr, "Need 640x480x8 and waitretrace\n");
>               fprintf(stderr, "...and you don't have it, sorry.\n");
>               GGIExit();
>       }
>       fprintf(stderr, "No mouse pointer available.  Will have to emulate.");
>       emulate_pointer = 1;
> }
> /* This does the setmode, as GAlloc implements it's own setmode, which
>    is why we need both set/check. */
> if (ggiGASet(vis, mymode)) {
>       fprintf(stderr, "FIXME: Something unexpected happened\n");
> }
> /* Deallocs/clears whole list of requests. */
> ggiGADeallocRequests(mymode);
> /* Gets the current set of allocated resources, which if there were 
>    any GGI_AUTOs or other "don't care's" in the request, this will contain 
>    the values we actually ended up getting for these fields, which is 
>    why we need the "get" function. */
> ggiGAGet(vis, &mymode);
> /* Actually this whole while loop would be more like this:
>    mypointer = ggiOVLTieItem(mymode, 0); Gets first sprite in list,
>                                          ignores stuff for other extensions 
>    ggiMISCTieItems(mymode);  Initialize any features LibGGIMISC handles
>                              which appear in the response list.
> */
> while(mymode) {
>       switch (mymode->res_type) {
>       case GAT_SPRITE_POINTER:
>         /* Grabs the info like the hardware address of the sprite/etc,
>              and asks the target to do any pre-use initialization. */
>         mypointer = ggiOVLTieItem(mymode);
>           break;
>         case GAT_MISC_VERTRETRACE;
>           ggiMISCTieItem(mymode);
>           break;
>       }
>       /* Note -- "Resource", not "Resources" -- returns rest of list. */
>       mymode = ggiGAFreeResource(mymode);
> }
>
> Note that the functions other than ggiGACheck above do not have a vis
> argument, because all they do is allocate and construct the request object.
> No target specific functions get called until ggiGACheck.
> 

In this example, you request a 640x480x8-resolution, a waitretrace
from libmisc and a sprite-pointer from libovl (instead of libBSE).

I was thinking about something like this:


ggiInit();

/* Initializes libOVL and LibBlit internally */
ggiBseInit();

/* Initializes libBuf internally */
ggiXmiInit();


vis = ggiOpen(NULL);

ggiCheckSimpleMode(vis, GGI_AUTO,GGI_AUTO,
                        GGI_AUTO,GGI_AUTO, GT_AUTO, &mode);
ggiSetMode(vis, &mode);


/* Request a sprite pointer with any size. */
sprite = ggiBseAllocate(vis, GA_FT_SPRITE_POINTER,
                        GGI_AUTO, GGI_AUTO);

/* Request alpha-buffer */
abuf = ggiXmiAllocate(vis, GA_FT_BUFFER | GA_FT_BUFFER_ALPHA,
                        GGI_AUTO, GGI_AUTO);

/* Request stencil-buffer */
sbuf = ggiXmiAllocate(vis, GA_FT_BUFFER | GA_FT_BUFFER_STENCIL,
                        GGI_AUTO, GGI_AUTO);


/* Do something with the sprite and the buffers */

/* release everything */
ggiXmiFree(abuf);
ggiXmiFree(sbuf);
ggiBseFree(sprite);


ggiClose(vis);

/* Exits libBuf internally */
ggiXmiExit();

/* Exists libOVL and libBLT internally */
ggiBseExit();

ggiExit();


In this scenery, the user allocates a sprite-pointer from libbse of
any size after the graphic mode is set up. libbse asks internally
libgalloc through libovl for it. If that fails to do that in
hardware, then libbse asks libgalloc through libblit to emulate it.
The sprite is then internally handled by libovl in hardware or
emulated by libblit. Only libbse knows about that. The user himself
get the sprite and uses it. Then the user asks libxmi for an alpha-
and a stencil-buffer. libxmi asks libgalloc through libbuf for them.
libbuf falls back to use system RAM buffer if not enough VRAM is
available. When exiting the program, everything will be released.

OK so far - this is the ideomatic case how an application should be
written. Now I try to explain, why threads are needed to do this:

At first libgalloc gets a request from libovl/libblit for a
sprite-pointer. Then it gets a request libbuf for an alpha-buffer and
then for a stencil-buffer.

These basically are three things libgalloc has to get out of the
target in the best way.
To make libgalloc able to handle this, it has to start a own thread
to not lock the main process until it tries to use the resources,
which are not allocated at this time. During this time libgalloc
tries to get the best combination of the three requests out of the
target. When this is done, then its thread finishes and pass the
information back to libbuf and libovl/libblit, where a waiting thread
inside of their own allocation-function initializes the resources and
passes them back to libxmi and libbse and exits. Then the
main-process will be unlocked and it continues until exiting.

I hope I am clear enough. If you are not sure you got me right, then
ask.
 
> > I think, the best way is leave the order of importance to the
> > application. It knows, what it needs and has to say, what it needs in
> > the order of importance. When it does crap, then it gets crap. :)
> > 
> > LibGalloc just checks, if the resources are available or not and
> > allocate them if possible.
> 
> Yes, but it knows how to figure out how to get the resources out of the
> target.

Yes and no. That's a bit crufty, because there are some broken
targets like the X one.

Have a look at the source, how libovl allocates the
sprite-pointer/cursor:

It does nothing but setting a flag at allocation time to indicate
itself later, that the caller want to have one. Then when the caller
set the image of the sprite it will be allocated, because the
allocation function XCreatePixmapCursor() requires an image as a
parameter.

So, libgalloc has to set the same flag as libovl does to not brake
it. I suggest to give a callback-function through ggiGAlloc(), which
will be called if not NULL. The callback-function knows the format as
it is implemented in libovl or whatever the caller is.

> > > This is a bit of a sticky situation: LibGAlloc is supposed to be a 
> > > core library,
> > 
> > So the right place for it in the CVS would be
> > libggi/extensions/libgalloc, right?
> 
> Not sure.  Personally I think that entire directory should be 
> retired and all extensions moved down to the peer level with libGGI.
> But if we are keeping that directory, then GAlloc deserves to be there
> even more than ggiMISC does.

Yep. I agree.
 

CU,

Christoph Egger
E-Mail: [EMAIL PROTECTED]

Reply via email to