#include <ggi/ggi.h> int ggiSetFlags(ggi_visual_t vis, ggi_flags flags); ggi_flags ggiGetFlags(ggi_visual_t vis); #define ggiAddFlags(vis,flags) \ ggiSetFlags((vis), ggiGetFlags((vis)) | (flags)) #define ggiRemoveFlags(vis,flags) \ ggiSetFlags((vis), ggiGetFlags((vis)) & ~(flags))
ggiGetFlags obtains the flags currently in effect.
ggiAddFlags and ggiRemoveFlags are macros that set or unset the specified flags.
Flags are used to alter a visual's underlying behavior. All flags default to an unset value. Flags which are not supported by a given visual will remain unset even when an attempt is made to raise them. Thus, it is possible to tell by reading back the flags whether or not each of the flags is supported by the given visual.
ggiGetFlags returns the current flags. This can be used by the curious to check whether a flag is being silently ignored as per above.
To make sure that all pending graphics operations are actually done and the screen is updated, you need to call ggiFlush(3). This call is not needed in synchronous mode.
However, the synchronous mode is the default, because it is what most programmers expect.
GGI guarantees that the effects of drawing operations on the final state of the buffer are consistant with the order in which they were invoked, but as to what order the operations visibly appear during a flush, that is entirely up to the target. You could draw a red square with the GPU (through the target), and then draw a green square inside it via software -- you will always end up with a red square inside a green square, but the user may see the red square appear first.
When it comes to directbuffer, though, that is the problem that the TIDYBUF flag is meant to fix. Or at least, the TIDYBUF flag fixes a problem with the way GGI fixes the serialization problem. The display is flushed entirely before the acquire completes, and then the db is flushed entirely before the db is released, so that is serialized. The TIDYBUF stuff lets you bypass this serialization for efficiency.
So the recommendation for all graphics applications is to set the asynchronous mode. It will be far more efficient on some platforms and will never be worse.
Setting up asynchronous mode:
ggiAddFlags(vis, GGIFLAG_ASYNC); /* switches to asynchronous mode */ ggiFlush(vis); /* updates the screen */ ggiRemoveFlags(vis, GGIFLAG_ASYNC); /* switches to synchronous mode */
These visuals may also perform dirty-region tracking, such that if the directbuffer is used, altered data may never reach the screen until the lock is released, because the visual does not know that a certain area of the backbuffer contains new (dirty) data. Even explicitly calling ggiFlushRegion(3) on the affected area may not cause the data to be sent to the screen.
Note that this means that, as long as the lock is held, affected regions may also have to be flushed (and thus, should be flushed) after normal drawing primitives are called.
Before releasing the lock, applications should be sure to flush all affected regions, because the visual may revert to its default dirty-region management behavior after the lock is released.
Do note, also, that in multi-frame displays ggiFlushRegion(3) affects only the current write frame, so even though it is possible to use a directbuffer to alter a different frame, you must call ggiSetWriteFrame(3) to tell the visual that you will be altering the frame.
The GGIFLAG_TIDYBUF flag is not available on all visuals, but it is safe to attempt to set it whether or not it is available. Code written for the tidy-buffering mode will display correctly on visuals which do not have a tidy-buffering mode (but not vice-versa), so it is not necessary to adapt program behavior to its non-presence.
It is recommended that, if an application must use directbuffer, the application should attempt to place the visual in tidy-buffered mode. Do note, though, that many applications that use the directbuffer do not actually need to do so and probably should not, as it reduces portability.