Index: [thread] [date] [subject] [author]
  From: Brian Julin <bri@forcade.calyx.net>
  To  : ggi-develop@eskimo.com
  Date: Wed, 17 Mar 1999 01:31:47 -0500 (EST)

Some more "texturetalk"

OK, after a ni^Hap or two I think I've found a satisfactory solution
to the sprite/texture problem that doesn't involve altering the 
visual structure.  It is implemented as both a target and an
extension, and is a good compromise between the two positions
expressed ("just draw in the off-screen virtual area", and "shrink the 
visual structure so all sprites can have their own visual but
not use huge chunks of memory.")

I guess unless anyone else likes this proposal enough to take 
it on I'll just peck away at it in my spare time, but I'm
pretty convinced now that this is the right way to do it.

Here's how it works.  You attach the libGGIAuxBuf extension,
either before (preferably) or after setting a mode on the 
normal visual.  This gives you a new operation ggiAuxBufAlloc
on the visual which you can use to define an off-virtual-screen 
buffer (Z,Sprite,Texture, what have you.)  This takes away the
poor practice of forcing the virtx, virty to do double duty 
as an auxiliary buffer allocation -- so don't ask for virtual
screen resolution unless you really want just that.  It also 
loads the "auxbufserver" renderer on top of the existing one 
(or if that's not possible, the auxbufserver renderer must be 
preloaded by a nested construct like display-tile does), or if 
none is chosen yet, it will do so during the setmode call.

For the sake of brevity of this description I'll just refer to the 
auxilary buffers as sprites for the rest of this even though
they could be anything.

If you have not set a mode, any call to ggiAuxBufAlloc merely 
prepares the visual's informational structures to anticipate 
needing these sprites.  You can then use advanced set/checkmode 
functions provided in the extension to ask the target to allocate 
these sprite areas when it sets the mode.  It will allocate the 
sprites in the order they were requested, and continue after 
failure to try to fit as many into video memory as it can.  The 
rest are shunted to main memory buffers.  There will be functions 
to check whether a particular buffer is in video memory or main 
memory, or force moves to/from video memory, or to lock a buffer
into main/video memory so it never gets bumped out.  If the mode 
was already set using the standard ggiSetMode function, the 
allocation happens in realtime and you can check the results
of each one as you do it, but this may result in fewer buffers being 
available since the setmode didn't know what you were going to want.

Now for the trick.  The extension can mutiplex renderers based on
the _coordinates_ given to the drawing operation.  That is, if you try to 
draw anything off the normal virtual rectangle, the extension looks
to see if it has placed a sprite "there".  "There" is in quotes because
the coordinates at which the application thinks the sprite is located
in video memory may not be the same as where it actually is.  Thus all
of the following LibGGI functions are available to the sprites and
will go through the sprites' custom renderers simply because the 
auxbufserver knows that's what is "there":

ggiSetOrigin, ggiGetOrigin, ggiDrawPixel, ggiPutPixel, ggiGetPixel,
ggiDrawLine, ggiDrawHLine, ggiPutHLine, ggiGetHline, ggiDrawVline,
ggiPutVline, ggiGetVLine, ggiDrawBox, ggiPutBox, ggiGetBox, ggiCopyBox,
ggiCrossBlit, ggiPutc, ggiGetc.

All the other LibGGI functions that make sense for a sprite must go
through renamed extension functions that tack on x, y coordinates,
for example, ggiFillScreen would be implemented as ggiFillAuxBuf(vis,x,y)
and x,y would be used to figure out what sprite to fill.  Stuff that
would require extra local data for a sprite, like ggiSetGCForeground,
would not be implemented by default in the base AuxBuf extension and
would be common to all sprites using that parent visual (see problem
#3 below.)

So in the minimal case for each buffer, the data stored by the extension
is the x,y fake position, the size, the memory position of the real 
buffer data, some flags as to whether it's in video or main memory, 
or locked in either, and a pointer to the parent visual containing it's 
custom renderer.  

This should be under 35 bytes per sprite.  Arrangements could be made 
to share this array with the application so it doesn't have to 
duplicate it, with the condition that allocing more buffers 
would require refreshing the pointer to the array since it may 
have to grow/shrink forcing a alloc/copy/free action inside 
the extension.

There are a few of problems with this implementation but they 
have work-arounds:

Problem 1 -- Clipping.  Drawing with off-virtual coordinates and expecting 
a clipped operation on the main visual could result in accidentally drawing
into a sprite.  So an optional field in ggiAuxBufAlloc will allow you
to specify how much "pad" you have around the actual image if you intend
to clip this way.  You will be able to call ggiAuxBufAlloc to request padding
for the main visual as a special case.

Problem 2 -- Speed.  Waiting for a bounds check on the coordinates, 
and a lookup in the mapping of fake coordinates to memory locations,
especially for the main visual, will slow down performance a tad.  So
a function newvis = ggiAuxBufSpawn(vis,x,y) will allow you to create a 
full-weight visual with coordinate origins starting at 0,0 for a 
particular sprite, or if called with x,y inside the virtual rectangle, 
will recover the original visual from before the extension was loaded.  
These visual pointers are only valid until the parent is closed, of course.  
This recovers full GGI speed on those buffers that are performance 
critical.

Problem 3 -- Flexibility.  There's the likelihood people will want 
either each individual sprite, or a certain subclass of sprites, 
to have extra private data, like say in the case of actual sprites,
priority and on-screen position.  However this can be addressed
fairly easily by providing API functions to create new arrays
or clone the parent visual of a certain class of sprite and assign 
it to selected sprites.

Anyway, it was getting quiet on the list so I decided to write myself
to sleep.  Hopefully the dirth of posts is a good sign and it means 
evryone's busy coding stuff :)

--
Brian

--
P.C.M.C.I.A. stands for "Plastic Connectors May Crack If Adjusted"
                                                             -- me
--
Brian S. Julin

Index: [thread] [date] [subject] [author]