Chapter 6. Resources

Earlier it was said that LibGAlloc's was more a "protocol" than anything else. If that is the case, then the resource, LibGAlloc's fundamental unit, is the "packet header". All of LibGAlloc's internal operations use linked lists of resources which are handled with the opaque types ggiGA_resource_list and ggiGA_resource_handle. The types are opaque because inside is linked list control structure, and some other LibGAlloc accounting information. Since it is opaque, access to the values inside is forbidden, except for the items for which API functions are provided to access, which mainly alter the type and the state of the resource. Values that may be assigned to the type and the state parameters are defined in ggi/ga_types.h.

LibGAlloc's API is designed such that many extensions will not need to manipulate resources directly. Instead a lot of resources will be manipulated solely with the "properties" structure described elsewhere. However, some features will exceed the properties structure, and in addition to, or instead of, the properties structure, a resource can have a private data structure which can be loaded with the ggiGASetPriv, ggiGAGetPriv functions. Those are functions only to be used by extension authors, however, because using a private structure implies that you will be placing special support in a LibGAlloc helper library or target that will handle the data on the other side of LibGAlloc's information flow. LibGAlloc will faithfully copy and free the contents of the private data, but it does not understand them. An important consequence of this fact is that no nested data structures are allowed in a private data area.

Types of Resources

The res_type member indicates to LibGAlloc the general type of feature that the resource represents. It is used by LibGAlloc targets to route the feature to callback code in the target or in a helper library that is designed specifically to handle resources of that type. There are families of types and, subordinate to those, individual subtypes. The family can be extracted by using the macro ggiGA_TYPE to mask out subtype and other bits. The subtype can be determined by masking with the macro ggiGA_SUBTYPE. The macro ggiGA_FULLTYPE gives both the type and the subtype together, a commonly needed value.

Framebuffer Resources

Resources of type GA_RT_TYPE_FRAME are special, in that they represent a main video mode. LibGAlloc has its own operations for setting and getting the video mode, which treat the video mode as just one other type of feature. Although LibGAlloc's API has been designed to allow easy addition of LibGAlloc using extensions to existing code by doing its best to accomodate when the regular ggiSetMode operation has been used on the visual, it is recommended that calls to ggiGetMode and ggiSetMode and its variants be reworked to use the LibGAlloc method for setting modes. More on that later.

The function ggiGAAddMode can be used to add a framebuffer resource to the request list. You can use ggiGAGetGGIMode and ggiGAGetGGIDB to get a pointer to the ggi_mode and ggi_directbuffer structures in the framebuffer resources, just remember if the resource is destroyed that this pointer becomes invalid. Also, resource structures are treated differently when they are of this type, as explained in the next section.

Anciliary Buffer Resources

Resources of type GA_RT_TYPE_BUFFER represent companion buffers to other features. There are many kinds. A buffer is usually attached to another resource with the GA_STATE_SEEABOVE state flag described later in this chapter. That is because anciliary buffers usually define extra data for each pixel in a resource that contains pixel data, and would be meaningless without a resource to be associated with.

Resource of sub-type GA_RT_BUFFER_ZBUFFER represent a 3D Z-buffer. These are used to apply to each point on the screen a depth into or out of the screen. This data should be stored onboard the card because it is a critical element in the mathematics that some graphics card accelerators use when drawing 3D objects, however it is also possible to emulate a Z buffer in normal RAM in some cases.

Resources of sub-type GA_RT_BUFFER_ABUFFER represent an Alpha buffer. Alpha values tell the graphics processor whether the pixel is transparent, translucent, or opaque. Usually Alpha values are stored interleaved with the rest of the color data for a pixel, but this sub-type exists to support implementations where the Alpha buffer is separate.

Resources of sub-type GA_RT_BUFFER_SBUFFER are Stencil, or Span, buffers. These are a popular software rendering technique that may some day find itself with hardware assistance.

Resources of type GA_RT_BUFFER_SWATCH will result in the allocation of onboard or offboard areas where you can draw in the same pixel format as the main framebuffer. The swatch is different than simply allocating off-screen area by adjusting virtual resolution, because on double and triple buffered displays (where the ggi_mode's "frame" element is > 1), the virtual area exists once for each frame. On-board swatch resources are kept only one per visual, and so they are more efficient. (And, unlike virtual area, they can also be requested as off-board buffers.)

Resources of sub-types GA_RT_BUFFER_LSTEREO and GA_RT_BUFFER_RSTEREO represent data meant to be used to modify the display data for the user's left and right eyes when using 3D viewing devices. (We put them in for Steffen, author of KGI, he knows more.)

Sprite Resources

Sprites are small, and sometimes not so small, images that float on top of the screen and can be moved around on the screen just by changing a few hardware registers which define their screen position. The contents of the image are contained either in registers or in the video RAM. The big advantage to sprites is that they remove the need to worry about whether the image of the sprite will interfere with other drawing operations being performed on the framebuffer. All sprite like objects have a type of GA_RT_SPRITE.

Resources of sub-type GA_RT_SPRITE_POINTER are sprites that are specifically designed to make happen the little arrow that you move around with your mouse. They sometimes have features that other types of sprites implemented on a card may not (like color transforms with the image in back of it), and often lack features that generic sprites have (like hardware collision detection).

Resources of sub-type GA_RT_SPRITE_CURSOR usually refer to the blinking hardware cursor in VGA text mode, but there are also targets that implement these for graphics modes as well, in which case they are very similar to, if not the same as, the pointer sprites described above.

Resources of sub-type GA_RT_SPRITE_SPRITE are all-purpose sprites. They often come in sets in which certain sprites will appear to be over or under other sprites when they overlap, and the sets sometimes have hardware registers that keep track if any of the opaque pixels in one sprite are occupying the same location as an opaque pixel in another sprite. Some graphics targets can have sprites up to the full size of the screen.

Video related resources

Resources of type GA_RT_VIDEO represent areas of the screen which may be fed data from a TV tuner or hardware DVD/MPEG1/H.32x source.

Window Resources

Resources of type GA_RT_WINDOW represent features that are meant to aid or accelerate windowing systems.

Resources of sub-type GA_RT_WINDOW_YUV are YUV viewports, which cause the pixel data in a certain region of the screen to be interperated as YUV colorspace instead of RGB colorspace. They are useful for image processing programs like the GIMP.

Resources of sub-type GA_RT_WINDOW_MM are hardware address translation windows which cause some of the IO space of the target to refer to the contents of a region of the screen with the origin and stride of the data being that of the window. If you understand modern CPUs, this can be thought of as an MMU for rectangles in graphics memory. If you've ever used the display-sub LibGGI target, then this would be a hardware accelerated display-sub with directbuffer.

Miscellaneous Resources

The type GA_RT_MISC is a catagory to file features that do not belong to any family of features big enough to merit its own type. Hence, the name. :)

Resources of sub-type GA_RT_MISC_RAYPOS allow the querying and lazy-polling of the raster position on displays that use cathode ray tubes, or internally are structure similar to CRT displays. See LibGGIMisc's *RayPos functions.

Resources of sub-type GA_RT_MISC_RAYTRIG_SET and GA_RT_MISC_RAYTRIG_PAL allow a way to tell the hardware to automatically set a display attribute (like the frame displayed when double-buffering, or the color pallete values) when the raster reaches the end of the screen and begins the vertical retrace cycle.

Resources of sub-type GA_RT_MISC_SPLITLINE allow the screen data to be wrapped into a cylinder which can be scrolled. See the LibGGIMisc SetSplitline() function documentation for more information.

Resources of sub-type GA_RT_MISC_FONTCELL represent the data used to display characters in a hardware text mode. In these modes, the frame contains one or two bytes per character, which are used as indexes into a table of tiny graphics images of all the letters of the alphabet and other characters elsewhere in the video RAM, or in a ROM. These features allow you to read or modify the images of the characters.

Variants: Motors, Tanks, and Carbs

The flag GA_RT_MOTOR, if set, indicates that the resource is a "motor" resource; The flag GA_RT_CARB, if set, indicates that the resource is a "carb" resource; if neither flag is set, the resource is a "tank" resource.

Motor resources represent the capabilities of the target to perform the operations required to implement a feature, and usually occupy little or no memory space. For example, (GA_RT_MOTOR & GA_RT_SPRITE_SPRITE) would refer to the circuitry that places sprites on the screen, moves them around, and performs prioritization and collision detection.

Tank resources represent the actual data manipulated by a motor resource. It is possible to associate multiple tanks with a motor, and multiple motors with a tank. Think of the tank as ammunition, and the motor as a gun: as long as the bullets are the right type, they can be used in any gun.

Carb resources are halfway between motors and tanks, both in meaning and in fact. A carb resource defines a mixing, blending, or other operation which is performed on data from one or more tank resources while it is on its way to the motor for positioning. This can be a software or hardware operation. In order to attach a tank to a motor, a carb resource is needed.

Motor, tank, and carb resources all use the resource properties structure differently, and are called "resource variants". For more detailed information, see the section on resource properties.

The Request List

Before we go on to describe the resource state, time should be taken to understand how a linked list of resources, which we refer to as the "request list", is used to allocate feature resources. In the below discussion we should think of LibGAlloc as a foreign tourist on an international airplane flight, who is trying to buy as many cigarettes as he can from some of the other passengers, but has to pay in the currency accepted in their country. Not every resource uses just "bytes of video RAM"; They all have their own form of currency. For the purpose of this discussion though, we will ignore what kind of currency is being used, and instead we will talk about a resource just using an amount of "space", and having "sizes" that say how much "space" the resource uses.

When a request list is processed, the list is taken in order, and space for each resource is budgeted until one of the resources does not fit. If a resource does not fit, the list is discarded immediately and an error is returned to the user with a flag set in the offending resource. The application may then try to modify the list and check again if it will fit, for as many times as it takes to get every item on the list approved by LibGAlloc.

If a resource is submitted on the list that has a size set to GGI_AUTO, then that resource will be made as large as possible, and may consume all the available space, so that any more resources that need space will be failed. This would make it very tedious to get a feature to be an optimal size because the application would have to submit the request with GGI_AUTO, find out what size the resource was budgeted at, and then reduce the size until everything fit. This would result in the application needing to do a lot of the work LibGAlloc is supposed to take off of our hands, so we have built in a way to get around this problem.

First, there is a way which you can put a resource into the list multiple times with different values. This allows you to put a request for, say a 640x480x8 video mode at the top of the list, and then request all of your features, and the put a request for GGI_AUTOxGGI_AUTOxGT_AUTO at the end of the list. That would guarantee you to get 640x480x8 at least, and then if there was space left over after the features had been allocated, the video mode would be upsized. The section on "tag groups" describes this process in more detail.

Second, a resource can be flagged such that it is a "resource cap". A "resource cap" immediately follows a resource of the same type, and any size in the cap resource must be set higher than the same value in the resource before it, or to GGI_AUTO. It is known that these two resources refer to the same instance of a feature, and so the amount of space allocated for it will be at least the amount of space requested by the first resource, but at most the amount requested by the "resource cap".

Finally, there are some resources that have meaning only when associated with another resource. Resources can be either be a regular resource or a resource which refers to a regular resource. All resources that refer to a regular resource must immediately follow the regular resource (or its cap if it has one) in the list. Each group of resource, resource cap and referring resources and their caps can be called a "compound resource". These are described in more detail later.

The Resource State

The resource state is a variable that contains bitwise flags that represent the status of a resource during negotiation. Some of these flags are meant to be set only by the user, some of them are meant to be set only by LibGAlloc, and some of them are bi-directional. You can find out which is which by masking with the values GA_STATE_REQUEST_MASK and GA_STATE_RESPONSE_MASK.

The "failure" flag means the resource used too much space

The RS_STATE_FAILED flag is set by LibGAlloc; it will also be cleared by LibGAlloc, so there is no need to worry what state it is in when you send a resource to LibGAlloc. This flag indicates that this resource is the point in the list where LibGAlloc decided that the feature list did not fit.

LibGAlloc sets the "modified" flag if it makes a suggestion

The RS_STATE_MODIFIED flag is only set by LibGAlloc. When it has been set it means LibGAlloc has altered the valus of the sizes of the resource. This can be one of two cases -- if the resource contained GGI_AUTO sizes, then the GGI_AUTOs have been replaced by the largest sizes that would fit. The other case, which you can tell by the RS_STATE_FAILED flag returned by LibGAlloc, is that the resource failed. In this case, the sizes have been replaced with the largest sizes that would suceed, whether or not they contained GGI_AUTO.

The "nochange" flag tells LibGAlloc not to make suggestions

The RS_STATE_NOCHANGE flag is only set by the creator of a resource. (In rare cases, this can be LibGAlloc.) It is not altered after the resource is created. This flag tells Galloc not to suggest values for the sizes of this resource if it fails during a ggiGACheck. Normally, if a resource fails, LibGAlloc will set RS_STATE_MODIFIED flag, and replace the sizes in the object with smaller sizes that would succeed. This is like the optional suggestion parameter passed back by ggiCheckmode. Note that if the resource list passes check, this flag is ignored by ggiGASet, and the values in the returned reslist may have been altered nonetheless.

The "see above" flags designates a referring resource

The RS_STATE_SEEABOVE flag is only set by the creator of a resource. (In rare cases, this can be LibGAlloc.) It is not altered after the resource is created. This flag designates the resource to be a "referer resource" as described above. Many of the properties fields in this resource might be ignored in favor of the values in the first resource in the current compound resource, (exactly which values are overridden depends on the types of both resources.)

The "cap" flags designates a resource cap

The RS_STATE_CAP flag is only set by the creator of a resource. (In rare cases, this can be LibGAlloc.) It is not altered after the resource is created. This flag designates the resource to be a "resource cap" as described above. The sizes in this resource must be greater than the values in the resource before it in the list, (GGI_AUTO should be considered infinity for this purpose.) When budgeting space, LibGAlloc will make the resource use at least as much space as the resource before it, but no more than asked for by this resource.

The "noreset" flags designates an in-service feature

The RS_STATE_NORESET flag is only set by the creator of a resource. (In rare cases, this can be LibGAlloc.) It is not altered after the resource is created. This flag designates the resource to represent a feature that is currently being used, and cannot be reallocated. Any feature anywhere in the request list which would force this resource to be reallocated or use of it to be interrupted in any way will fail.

The "shared" flag designates a sharable resource

The RS_STATE_SHARED flag is only set by LibGAlloc. When it has been set it means the resource properties structure can be/is shared. Certain types of negotiations require a resource to appear multiple times in the request list; sharing the properties structure is done in these cases for efficiency and simplicity of internal code.

The "tag" feild defines advanced list structure.

Resources are considered to be in a "tag" group if the bits masked by GA_STATE_TAG_MASK are non-zero. There are two types of tag groups, one which has tanks in it, the other which has motors and carbs; and they work a bit differently.

Tag groups containing tanks are processed as follows: each time a tank resource of that tag group is encountered, it, and the resources attached to it, are negotiated as they normally would be, but it is assumed that they will be reusing the same storage areas that previous resources in the tag group used (if more space is needed for this resource than for any of the previous resources inthe tag group, a larger area is requested). The user is responsible at this point for not trying to use the resources simultaneously, and for initializing the storage areas after another resource has been using them. Note that GA_RT_FRAME resources are implicitly in a tag group with any other GA_RT_FRAME resources. Now, it is easy to see that the process of "upsizing" a resource which was described earlier is nothing more than requesting a second, bigger resource that shares the same storage area, and simply not using the smaller resource.

In a tank tag group, compound resources interact with the tag group as follows: any resources marked "seeabove" and in the same compound must exist simultaneously with each other and so they do not share storage area with each other even though they share the same tag; they only share storage with resources in other compound resources. Any resources in the compound which are not marked as part of the tag group cause allocation of new storage areas, even if they exist in previous compounds in that tag group... so be sure to join your seeaboves into the tag group, as well.

Note also that if you wish to upsize a resource and it's attached seeaboves, e.g. Z-Buffers, they must appear in both the original compound resource, and in the second "upsize" resource -- do not assume that because you have requested a Z-buffer above in the list that it is implicitly requested for other resources in the same tag group; it is not.

Now, for tag groups containing motors and carbs, the handling is slightly different. Generally these consist of one or more motors and a lot of carbs. The carbs are attached to tank compound resources seeabove, and this is how the tank-carb-motor pipleine is glued together. If negotiation of a carb succeeds, it means that the tank it is attached to has a valid path (the carb) through which its data can be sent to any of the motors which are in the same tag group as the carb.