Most LibGalloc resources will contain a structure called the properties, which is set when the resource is added to a list with ggiGAAdd, and a pointer to which can be retrieved with ggiGAGetProperties.
The properties structure contains commonly used parameters for the negotiation of a resource. This chapter describes the meaning of the members of this structure.
If a resource has a props structure, then it will probably use some of the following members. An additional union member, sub, contains members specific to the three resource variants: "tank", "motor", and "carb" resources, and is described in the next three sections.
The qty member is a generic field for storing an integer attribute. For example, a GA_RT_SPRITE_SPRITE motor resource would use this field in negotiation of how many sprites it can display on the screen simultaneuously.
The flags field is a generic variable for holding flags. For example, most motor resources will use the the two flags GA_PIXEL_MODE or GA_DOT_MODE to define what units the snap grid parameters are in (see below).
The size member is used to define the size of the negotiated resource, if it has one. GGI_AUTO (0) is considered to mean automatically find the maximum size possible for this resource. The size member can be accessed as size.x,size.y for two dimensional objects, or size.linear for linear allocations.
The two members storage_ok and storage_need check the capability to use certain types of data storage for the resource. The meaning of storage_ok and storage_need are described below; Let us look at the values these feilds may contain. First, the special value GA_STORAGE_DONTCARE (which equals zero) means any type of storage is acceptable.
The flag values GA_STORAGE_READ and GA_STORAGE_WRITE designate that the storage is readable/writeable. For convenience, the value GA_STORAGE_RW (equal to GA_STORAGE_READ | GA_STORAGE_WRITE) is also defined. The flag value GA_STORAGE_DIRECT indicates that the storage may be accessed as per normal system memory (even if it is not.) Unless it is set, special methods are needed to access the storage. The value GA_STORAGE_NORMAL (equal to GA_STORAGE_RW | GA_STORAGE_DIRECT) is provided for convenience as well.
The flag value GA_STORAGE_ONBOARD indicates that storage is located on-board the graphics device, and does not need to be transferred across the system bus in order to be used in a graphics operation (however, on the down side, this means that actually loading content into the storage from regular system memory will require the data to be passed across the system bus.) The value GA_STORAGE_VRAM (equal to GA_STORAGE_NORMAL | GA_STORAGE_ONBOARD) is more convenient to use.
The flag value GA_STORAGE_RAM indicates that the storage is normal system memory which is stored permanently in RAM, that is, it will not be swapped out to secondary storage. The value GA_STORAGE_REALRAM (equal to GA_STORAGE_NORMAL | GA_STORAGE_RAM) is more convenient to use.
The flag value GA_STORAGE_SECONDARY indicates that the storage is located on a physical medium which is slower than system RAM, usually a disk drive. Likewise, the flag value GA_STORAGE_TERTIARY indicates the storage is located on a medium which may have large latency or very slow speed -- this usually indicates the storage is on a network server which lacks service guarantees.
The flag value GA_STORAGE_TRANSFER indicates that the graphics system is capable of using the storage without CPU assistance. For example, user-space DMA-capable buffers can be gotten using the convenient value GA_STORAGE_DMA, which is equal to GA_STORAGE_REALRAM | GA_STORAGE_TRANSFER.
The flag value GA_STORAGE_VIRT indicates that an automatic caching system (transparent to the user) is in effect which makes slower storage appear to be interchangable with faster storage. For example, the convenient value GA_STORAGE_SWAP represents virtual RAM which may be stored in either real ram, or in "virtual memory" on a hard drive. Accordingly, GA_STORAGE_SWAP is equal to GA_STORAGE_REALRAM | GA_STORAGE_SECONDARY | GA_STORAGE_VIRT. Another convenience value GA_STORAGE_GART is provided and equals GA_STORAGE_REALRAM | GA_STORAGE_ONBOARD | GA_STORAGE_VIRT.
The flag value GA_STORAGE_HOTPIPE indicates that read and write operations to the storage do more than alter the contents of the storage, and may in fact trigger graphics operations.
The storage_need and storage_ok members work together to provide a flexible negotiation system. When a request is submitted to LibGAlloc via ggiGASet, each bit flag position is checked in both positions, and the following meanings apply depending on the values found:
This type of storage is not acceptable. The resource will fail if it is only available with this type of storage.
This type of storage is desirable, but is not entirely necessary. If this type of storage is not available, the resource will still succeed, but if it is available, LibGAlloc will try to allocate it before any other type of storage.
This type of storage is undesirable, but is acceptable. If this type of storage is the only kind available, the resource will still succeed, but if other storage is available, LibGAlloc will try to allocate it first.
This type of storage is necessary. The resource will fail unless it is available.
LibGAlloc also returns values in these fields. The values in these feilds will be always be altered by ggiGASet. When ggiGACheck is called the values will not be altered if the resource is flagged with GA_STATE_NOCHANGE (see the section on resource state). The meanings of the returned flags are as follows when a call to ggiGACheck or ggiGASet fails:
Any requests for this resource that have this bit set will fail. This type of storage is not compatible with this resource.
Requests for this resource will be more likely to succeed if this bit is set to 1.
Requests for this resource will be more likely to succeed if this bit is set to 0.
Any requests for this resource will fail unless this bit is set. Storage of this type is the only kind compatible with this resource.
Note that downsizing the resource may help in the second and third situation above depending on the available amounts of different types of storage. In this case, suggested sizes are supplied in the returned resource. In the first and fourth situations, altering characteristics of the resource may change the values returned entirely, by changing the types of storage that the resource is compatible with. Clues as to minimal alterations needed to make the resource work with the originally requested storage type may have been placed by LibGAlloc in various members of the returned resource.
When ggiGASet (or ggiGACheck) is successful, both members will contain the same value, which will have bit flags set accordingly to represent the type of storage which has actually been (or would be) obtained and allocated for use by this resource.
A motor resource is a chipset feature that moves data (hence the name). As such, the properties used by motor resources all involve limits and attributes concerning what capabilities the motor has to move/position the data. Motor properties area accessible through the union member sub.motor in the resource properties structure. The common properties member qty will usually refer to the number of simultaneous objects that can be positioned/moved by the motor. The common properties members storage_ok and storage_need are reserved for future use.
Most motor resources allow you to position something on the screen, but many have limitations about where on the screen you are able to position that something. The snap grid defines the rules for positioning with a motor resource. The grid_start and grid_size members offer x,y coordinates within which the motor can position things.
In addition, some motors can only place things on a grid (for example, it might place things at 0,0 or 10,0 or 0,10 or 10,10 or 0,20 but not at 3,5 or any other location whose coordinates are not divisible by 10.) This is a lot like the "snap-to-grid" feature in many common desktop publishing programs.
The pos_snap member defines x and y snap intervals, and if they are set to values other than 1, attempting to position the resource at coordinates off the snap grid will result in your coordinates being rounded to the nearest grid snap point. Likewise, there is a size_snap member which tells you if the motor has similar restrictions when it is resizing something.
Many motor resources have a different resolution than the main framebuffer, or the capability to scale things. In some cases, the motor is immune to the main framebuffer's double-scan and pixel-doubling settings, and is able to position and size with sub-pixel accuracy. Even further, some motors use an entirely different pixel clock which is gated into the CRTC when the raster beam is traversing the object defined by the motor resource, so sub dot accuracy is possible. In addition, many resources support their own pixel doubling or double-scan, allowing the motor to scale the object.
The scaling factors possible are defined by four vectors contained in the mul_min, mul_max, div_min, and div_max members. The base units that these members operate on are either known implicitly, or are determined by flags. The flag values GA_PIXEL_MODE and GA_DOT_MODE are provided for this purpose, and specify that the scaling factors apply to pixels or dots, respectively. It is important to note that the snap grid described in the last section uses units of 1/div_max pixels or dots, as indicated by the presence of these flag values. Users will generally be sheilded from this fact by an API using integer pixel coordinates or fixed-point sub-pixel coordinates, but extension authors are advised to check their units after negotiating a motor.
A tank resource represents data to be moved by a motor. The tank properties describe the layout this data is stored with. They are accessible under the union member sub.tank. The common properties member size refers to the size of the data stored in the tank; the units are usually pixels, but it depends on the type of the resource. The qty feild requests several of the same sized objects, or, if set to GGI_AUTO (zero), will grab as many of the resources as will fit.
A standard ggi_graphtype for the tank data is provided for in the gt member. Also, a pointer to a standard ggi_directbuffer structure is provided for in the db member (this db structure is often shared between many resources, and so should not be freed.) Separate pointers to access the data in the tank for read and write access are provided. These are to be used instead of the read and write pointers in the directbuffer structure.
Within the buffer space allocated for a tank, there may be a snap grid (as described above for motors) or linear alignment restriction on operations performed on the data, such that those operations can only address data starting at certain locations in the buffer. The buf_snap member provides an embelishment of the db member's alignment restrictions, and may be addressed as a vector (sub.tank.buf_snap.area.x, sub.tank.buf_snap.area.y), or as a linear quantity (sub.tank.buf_snap.linear).
A carb resource represents a translation, alteration, or mixing of data from tank(s) before a motor positions the data. This kind of resource is used to represent "raster operations", special feature-specific pallette entries or look-up tables, and data format (endian, depth) translations. The carb-specific resource properties are accessible under the union member sub.carb. For carb resources, the common properties members qty, size, and flags have meanings that vary based on the type of the carb. The carb is used most commonly in LibBlt, so refer to that library's documentation for a description of how GA_RT_BOB carbs use these fields.
A 32-bit set of flags and bitmasks is defined in the enumerated type ggi_ll_rop. These represent the types of operations that can be performed by a "ROP". For our purposes a ROP is an operation that takes two tanks as "operands", which are compared either bit-by-bit or pixel-by-pixel, and some sort of result is produced by taking each pair of bits (or pixels) as arguments to a function which produces one bit (or pixel) of the result. Since some hardware uses "unary" (or "non-associative") operators, there are cases where a certain ROP is represented by two bits, one for each operand.
A note on notation: earlier hardware implementations of ROPs assume that the two tanks of data being operated on were a "source" tank, and the data which was to be replaced by the result of the operation. Later implementations allow operations between two tanks to be performed without the data to be replaced by the result being one of them. As such, many of the symbols in the ggi_ll_rop type have two names; the former being a *_SOURCE and *_DEST pair and the latter being an *_OPERAND1, *_OPERAND2 pair. These symbols are equivalent and are merely to allow code clarity in either context. When we refer to a symbol in the below descriptions, we will omit the suffixes and may be refer to a pair of bits by their common root e.g. LL_ROP_KEYVAL refers to the two bits LL_ROP_KEYVAL_SOURCE (a.k.a. LL_ROP_KEYVAL_OPERAND1) and LL_ROP_KEYVAL_DEST (a.k.a. LL_ROP_KEYVAL_OPERAND2).
The least signifigant 16 bits of the ggi_ll_rop type are used to supply one bit for each of the "boolean" ROPs. These rops compare the two operands bit-by-bit and the resulting value is a logical operation between the two bit values. There are 16 "truth tables" possible, some of which have, in addition to a name like LL_ROP_TRUTHTABLE_0001, a commonly used name like LL_ROP_NOR.
The LL_ROP_KEVAL bits represent the ability to perform "keying", which is sometimes imprecisely referred to "comparing". To key is to apply the ROP only when the data in one or the other operand matches, or does not match, a specific value. Further, the LL_ROP_KEYMASK bits designate the ability to exempt certain bits from the key comparison, such that these bits are "don't care" bits.
The LL_ROP_COEFF bits represent the ability to scale the value of each pixel by a constant coeeficient. This is not multiplication unless the tank is grayscale -- each of the color channels is separately scaled, and may be adapted for gamma correction. Further, when the tank contains an Alpha channel, the coeeficient used is not a constant, but rather the contents of the alpha channel in that pixel. When used in this manner, the alternative LL_ROP_ALPHA symbol is clearer to say.
The LL_ROP_THRESH bits represent the ability of the ROP to only be performed when the pixel data is above (or below) a certain threshold value. This value represents the pixel's intensity as calculated by weighting the values in each channel, not a simple integer value derived from the whole pixel. Further, when the tank contains a Z channel, the comparison is assumed to be between Z values, rather than by intensity. When used in this manner, the alternative LL_ROP_DEPTH symbol is clearer to say.
The LL_ROP_ADD bit represents the ability to "add" the two pixels together. This is not always plain addition of the pixel's bit values, it is addition of colors and uses a formula appropriate to the tanks' color spaces. Further the LL_ROP_KEY_CMP bit designates the ability to "key" on the result of this "addition".
The LL_ROP_TESSLATE, LL_ROP_XWRAP, and LL_ROP_YWRAP values are used for "pattern fills". They apply only to the source, or operand1. LL_ROP_TESSLATE indicates that the ROP can take a pattern inside a tank and repeat it many times to fill a larger region with that pattern. The others indicate that the pattern can be "pinned", such that the resulting fill begins at some offset inside the pattern, rather than at the pattern's top left corner.
The LL_ROP_AUX bits indicate that this ROP feeds into another ROP before being passed into the motor. If LL_ROP_OPERAND1_AUX is set, then the result from this rop becomes the first operand of another ROP. If LL_ROP_OPERAND2_AUX is set, then the result from this rop becomes the second operand of another ROP. IF both are set (LL_ROP_AUX) this is a special case indicating a "side-by-side" rop, which is most often used such that two tanks can be compared for keying purposes, deciding whether or not to perform a different ROP on a corresponding pixel in two other tanks.
As mentioned above, Z and Alpha operations are implicit when certain ROP flags are set and the set of tanks being processed contain Z or Alpha values. There are two common ways in which Z and ALPHA operations are performed. In one mode, most common for Alpha and rare for Z, the Z or Alpha data is contained in a channel alongside the data for each color channel in the pixel itself. In another mode, most common for Z and rare for Alpha, the Z or Alpha data is kept in a separate tank of the same geometry as the tank containing the color data. In the latter case LL_ROP_AUX bits are both set as described in the last paragraph.
The LL_ROP_ALT bit is there to deal with unforseen or quirky ROPs that may need to be added to this API at a later date. If it is set, assume you know nothing about the meaning of the ggi_ll_rop value in question. A ggi_ll_rop item with a value of LL_ROP_NOP does absolutely nothing.
Adjusters represent the ability of a carb to adjust data between various pixel formats.
The LL_ADJ_ENDIAN* bit flags represent the ability of the hardware to compensate for differences between the endiannes (in 4, 8, 16, or 32 bit endian slices) of tanks. The LL_ADJ_BACKASS_WORDS bit represents the ability to reassemble the pixel with the bits in reverse order, as a format that carries the bits backwards was unfortunately popularized by an certain notorious operating system whose name should not be spoken.
The LL_ADJ_UPSIZE and LL_ADJ_DOWNSIZE indicate an ability to translate pixels between different bit-depths.
The LL_ADJ_USE_OWN_CLUT flag indicates that an internal CLUT separate from CLUTs of the involved tanks is available for use. The LL_ADJ_COLORSPACE flag indicates the ability to gamma correct or adjust between colorspaces (YUV/RGB/CMYK).
The carb properties members named "must" and "can" contain each a ggi_ll_rop named rop, a ggi_ll_adjuster named adj, and a ggiGA_storage_type named tostorage. The former are described above; the latter refer to the type of storage of the destination resource, which the carb and the motor that owns it has been created to send the data to. This does *not* mean that normal storage_need and storage_ok properties members in the carb resource refer to the storage type of the source data (the source data is a tank resource and has it's own storage_ok, storage_need members). Naturally, the values in the structure named must are required for the request to succeed, and the ones in the structure named can are just wishlist requests. If the carb resource is not flagged GA_STATE_NOCHANGE, or is being returned by ggiGASet, then the values returned in the structure named must are always active, and cannot be disabled, while the ones returned in the structure named can may be turned on or off through some mechanism provided by a higher level extension target.
The totype carb properties member designates what types of resources are valid candidates to receive the data from this carb (via its motor). This can be a specific type/subtype, or can be a whole resource type family by using one of the GA_RT_*_DONTCARE values. Usually, this value is a tank. The togt carb properties member is similar, it defines the valid graphics scheme/depth which are eligible to receive data from this carb (via its motor), and can contain the various auto/dontcare values accepted by ggiSetMode.
Several pointers (block1, block2, block3) are available and are used to offer hints which allow extension targets to find resources which are used to control the carb. For GA_RT_BOB resources, these are used to hand back addresses of "batchop blocks". Another possible use is as a handoff for the addresses of internal CLUT/ILUT/TLUT tables stored in VRAM.