Memory visuals are very handy for preparing picture parts and blitting them onto the sccreen with ggiCrossBlit.
To speed this up, the memory visual must use the same pixel coding as the target. You can achieve this with the following code sequence:
ggi_mode memmode;
ggi_visual_t mainvis,memvis;
...
ggiGetMode(mainvis,&memmode);
/* now maybe change size, but leave graphtype untouched */
memvis=ggiOpen("memory",NULL);
ggiCheckMode(memvis,&memmode);
ggiSetMode(memvis,&memmode);
Which will try to open the memory visual with exactly the same mode and pixel
encoding as the main visual.
It is strongly discouraged to draw to one visual from two (or more) different processes or threads at the same time. While serious damage is unlikely, corrupted graphics output might happen and a big performance penalty is almost guaranteed.
If drawing from two threads is needed, the application is required to synchronise the threads so that not both draw simultanously.
(Side note: Some cards need some sort of paging for accessing their video ram (banked framebuffer). Two threads accessing different parts of the screen would require a page change on each process switch, which could slow them down to a crawl. State information that has to be reloaded to the accellerator engine after every switch would be another example.)
Some libGGI functions may not be thread-safe (even with multi-threading enabled, currently). Therefore, only call libGGI functions from one thread.
Some tricky spots have to be taken care of if you mix libggi calls and direct access to the frame buffer. While direct access is done immediately, execution of a libggi call might be delayed due to the accellerator architecture, so framebuffer access immediately after an accellerated libggi call could actually be executed before or while the accellerator accesses the frame buffer itself, which worst case could lock the card and give best case wrong pixels on the screen.
To make sure that all pending accellerator commands are executed, you need
to call ggiFlush(myvis); between
a (series of) libGGI call(s) and
direct frame buffer access.
(Side note: ggiFlush(myvis); does more than just waiting for
the accellerator to finish pending jobs, so there will be another call
introduced for only this purpose. Stay tuned.)
If an application loses the focus and is not physically displayed (e.g. console switching, iconifying), it may be stopped. Some targets may implement a backbuffer and allow continuing, though.
After reactivation the application receives a redraw event. It is required to be able to perform a redraw. Whether it needs to re-set it's palette is still undecided.
Example:
ggi_event ev;
/* ... wait and get the event... */
if (ev.any.type == evExpose) {
if ((ev.expose.w == 0) && (ev.expose.h == 0)) {
/* redraw whole screen... */
redraw_screen(0, 0, screen_w, screen_h);
} else {
/* redraw part of screen... */
redraw_screen(ev.expose.x, ev.expose.y,
ev.expose.w, ev.expose.h);
}
}
/* ... etc ... */
If this is set to 255 (anything > 0 currently works), debugging output is printed to stderr.
This can be used to specify the default target and resolution to use. The common usage is probably only
export GGI_DEFMODE=800x600
for this default resolution, for the complete definition see
_ggiParseMode.
This variable is used to determine the default display target. Currently allowed values include:
force usage of X target
force usage of Xlib target
force usage of aalib target
force usage of memory target
force usage of SVGAlib target
force usage of XF86 DGA target
force usage of Glide target
force usage of terminfo target (text apps only)
emulate a true colour display on a display with lower capabilities, e.g. display true color on an 8-bit X display:
export GGI_DISPLAY="display-trueemu:8:display-X"
allows multiple displays with identical properties:
export GGI_DISPLAY="display-multi:x;x;xlib"
If GGI_DISPLAY is unset but DISPLAY is set, this is used to force usage of the X target with the appropriate display.