LibGGI: Yet Another Graphics API

The next generation fully portable graphics library
Graphics Context

Now we are set to start drawing. LibGGI uses a GC (graphics context) to represent the current state of the drawing system. We considered a state-free approach, but this would have meant:

  • Lots of parameters for some functions

  • A very awkward look for programmers used to the GC concept

  • Ignoring that actual acceleration hardware normally has a GC

We now draw a few dots in different colors by using ggiSetGCForeground and ggiDrawPixel. As an alternative, we draw the next set of pixels using ggiPutPixel. Higher-level functions are also available, but only to a limited extent. As you can see from the example program, we support various kinds of lines and boxes (and yes, these are accelerated, if the underlying target supports it), but that's about it.

Don't be disappointed here. There is a higher-level library called LibGGI2D providing more complicated functions. LibGGI has been designed to be a basic “foundation” library on top of which specialized libraries can be built for more complex requirements, such as 3-D and animation.


When we are done drawing, we use ggiEventPoll to wait for a key or mouse event. ggiEventPoll determines if an event of the given type(s) is present and will eventually block for it for a specified time or indefinitely, if the pointer to the timeval struct is NULL as in our simple case.

We then use a convenience function to get a keystroke. Note that this will block again, if polling was terminated due to mouse activity. In most cases, you will want to use LibGGI's event system to get input from any device that is attachable to a computer system. For event classification and configuration, a helper library called LibGII is available to give you a flexible and simple way of mapping device input to program actions. After ggiGetc has returned, we close down the visual using ggiClose, and then the whole LibGGI library using ggiExit. Note that you can reopen another visual before ggiExit, which can, for example, be used to transfer the program from one target to another. After ggiExit, every other call to LibGGI functions is undefined. You will need to call ggiInit again first. You have now gained a tiny glimpse at how LibGGI programs look.

Advanced LibGGI Usage

Many applications, especially those ported from DOS and other systems where a relatively direct access path to the hardware is present, will want to access graphics RAM directly. While being tied to the layout of the particular card/mode isn't a great idea for portability, it is a good way to get extra speed. LibGGI solves this dilemma by exporting a DirectBuffer structure describing all details of the currently active video buffer. The application can decide whether to use it or fall back to standard LibGGI calls.

LibGGI applications can service multiple visuals at the same time, thus allowing multihead applications like CAD or games screens split over several monitors. For convenience, we have “memory-visuals” that can be used to draw an “invisible” area first and then blit to screen (crossblitting). Simple color-space management, such as gamma setting, is available, as well as support for double/triplebuffering and waiting for vertical retrace, or even for a specific position of the CRT beam (where the hardware allows).

3-D, Movies, Fonts

LibGGI ends at about the level of a DrawBox, which is not a desirable environment for many applications, and transparent acceleration is limited. LibGGI was kept small on purpose to work well under constrained conditions such as embedded systems, and not waste space for applications which do not need advanced functionality.

We extended LibGGI so more complex APIs could be implemented “on top” of it. So far we have LibGGI2D, Mesa-GGI and a tiny windowing library, LibGWT, running. A lightweight 3-D library, font and animation support are works in progress. Such libraries are implemented as LibGGI-Extensions. Being an extension has several benefits over just “using” LibGGI; for one thing, you inherit the complete functionality regarding library loading and target support. Thus, extension libraries also bring along their set of API drivers which can be used to allow for transparent acceleration. LibGGI ensures basic services, so all extension libraries will run on all LibGGI targets, but the level of acceleration will vary depending on the availability of driver libraries for the extension.