GGI : Yet-Another Graphic Interface? Not quite

by Brian S. Julin

Genesis

If you've ever coded for a graphics program like a game or demo, or written a toolkit for GUI based applications, you've probably noticed how very suboptimal the state of graphics libraries and display APIs is today. Odds are, when you began, you spent a good deal of time trying to choose between systems like Xlib, DGA, DirectX/DirectDraw, SVGALIB, various OS framebuffer devices, SDL, and DirectFB. You made some compromises and did some workarounds to get your code running, and then sometime later when the whole thing worked, you realized a lot of people wanted to run your console application in X windows, or visa versa, or that performance wasn't as good as you had hoped, or that it only worked on certain hardware. In order to expand the user base, you may even have ported it to additional graphics back-end systems -- and in the process found that you had to rework your code not only to accomodate for the shortcomings of the new graphics systems and quirks resulting from the shortcomings of the original graphics system, but also switch to a completely different input device system, since most back-ends seem to be hopelessly entangled with a particular input API.

Why do we put ourselves through this mess? Why does every graphics-using project have a huge stash of source code containing re-implementations and re-inventions of a general graphics interface -- re-implementations which seem to unfortunately always be too tailored to the individual application to be re-used by others? That's exactly what the founders of the GGI project were asking themselves when they began to pour molten metal in their hidden caves and beat it into the shape of things to come. With the exception perhaps of SDL, which has managed to claw its way to some popularity by having a fair number of implemented back-ends and an interface which is usable by a good portion of programs, noone had put serious effort into pooling this solution set into a truly re-usable codebase for graphics applications. GGI aims to do just that -- and to create a new framework where higher level functionality can also begin to collect into a common codebase.

Design and achievements

The GGI Project was founded on a few principals which are admittedly rather obvious... but the unique thing about GGI is it stuck to them with a fervor, and the result has been some very beautiful code indeed.

One of the principals is that an API should come without strings attached, and so should a library's runtime requirements. For example, if a programmer does not want to use the GGI Project's input system (LibGII), it can be disabled, leaving input handles and devices free to be driven by something else. Furthermore, the entire project is modular, abstracting graphics back-ends to the point where the computer running a binary does not need to have every back-end installed in order to use LibGGI -- in fact, the same binary can be run on one machine, say a machine where there is no xlib installed, and then be copied to another machine and run inside an X window, without recompiling it from source. The GGI Project even went so far as to divide APIs into levels such that if you do not need e.g. fast 2D blended triangle operations, you don't need to install the module that provides that functionality -- and consequently you do not need to implement 2d blended triangles for new/private/esoteric graphics back-ends if all you want to do is access a framebuffer. This is important because it allows the application programmer to make informed decisions balancing portability (some systems will never be able to do fast 2d blended triangles) against functionality -- code for the minimal API subset that provides what you need, and the result will be that your application runs on the maximum number of platforms and graphics back-ends capable of supporting it. This level of granularity will make GGI Project libraries equally as well suited for large complex workstation applications (even full desktop environment servers such as Berlin) as they are for slimmed-down embedded appliances.

Another principal GGI strove for was to please 99% of the people 99% of the time. Special attention was payed to ensuring that GGI could tweak every common aspect of a graphics back-end (and there is a method that allows external user configuration to tweak back-end-specific aspects), but also to avoid requiring simple applications to pass large numbers of parameters to a very complicated API function with a 20KB manpage. Consider the difference between LibGGI's ggiCheck* family of functions and the functions used by many other graphics libraries. LibGGI's ggiCheckMode function allows the user to specify many aspects of the desired video mode -- visible and virtual size, graphics scheme and bitdepth, number of frames (double-buffer, triple-buffer, etc.) to name a few, and simultaneously allows other aspects to be auto-optimized. Many other APIs provide a list of supported modes, which must be be checked one-by-one until a satisfactory mode is found. However, LibGGI also provides a ggiSetSimpleMode, which does what most applications want -- gets the "best" mode available. Most GGI Project APIs are designed like this, with powerful do-all functions which are there to cover the bases when the easy-to-use convenience functions aren't smart enough.

Another goal of course was speed. The GGI Project's highly modular architecture could have been layered into some sort of complex, gratuitously object oriented paradigm, but instead stuck with simple C and spartan faux-OO techniques. In most cases, the modularity costs only one extra level of indirection/calling overhead, which on most systems is virtually unnoticable. The overloadable system developed by the GGI Project allows layout/pixelformat/hardware optimizations to be dynamically loaded at various levels without additional overhead. (In this last aspect we must admit we are still short of our goal, because there remains work to be done in actually building a larger portfolio of dynamically loadable accelerations and extending accelerations to higher level GGI Project APIs.)

GGI overview

A few side-benefits emerged from the LibGGI architecture. First, LibGGI is easily integratable into other programming languages (C is, after all, the common denominator of 99% of computing languages). Wrappers for both python and PERL have been produced for the base LibGGI library. Second, the overall axiom of the project ("Do The Right Thing") may have caused GGI Project participants to spend a good deal of time and effort covering corner cases and implementing facets which may rarely be used, but in doing so LibGGI has become sort of a reference book which gives a good read of the state of the art of basic graphics subsystems. If you want to assess the shortcomings or benefits of a graphics system, read the "display target" code of some GGI Project libraries for that system. Ugly code tends to accumulate around the places where a back-end falls short. I would say that this is the reason why our sister KGI Project emerged and began trying to develop the perfect graphics back-end, but I suspect the founders of the KGI Project had that in mind long before LibGGI was released to the public.

Finally, the GGI Project applied the same principals in creating LibGII, which provides a portable event interface covering a large variety of input devices and libraries across many platforms and OSes, and a modular filter system that allows some pretty neat tricks, to boot.

Where are we going now?

So what is up with GGI these days? Well, we have admittedly been stuck on a log in that LibGGI and LibGGIMISC, our production quality graphics libraries which are available today in many OS distributions (Debian, Mandrake, Gentoo, Net/Free/OpenBSD ports), do not fulfill the expectations of a large number of application developers. However, we are determined to take the GGI Project to the next level by providing extensions that cover the needs of modern applications -- APIs for fast blending, blitting, and overlays have been drawn up and prototype implementations are being completed. This phase will allow LibGGI to compete in the area of heavily menu-driven applications and applications providing motion video. From there, depending on how OpenGL2 fares, we will decide how to proceed with GGI's 3D implementation.

Currently we are wrestling with the issue of marrying the basic object paradigm, which can entail storage, efficiency, and transfer overheads, with the display-list/vector-list/programmable-pipeline paradigm, where data is arranged in back-end-specific manners for fast transfer to accelerated graphics engines -- it has been a challenging and educational discussion so far and though we feel we are near closure, folks are welcome to drop by and throw a monkey wrench or two into the plan -- what doesn't kill it will make it stronger.

Conclusion

In closing I would like to appeal to the reader to really think about the benefits that a mutual graphics codebase, fully opensource and fully under opensource community control, provides. Often our greatest obstacle is that application developers do not realize that with some extra effort, a good portion of their applications could become generic library code which would be reusable -- and enhancable -- by a large number of people. Don't underestimate the utility of that 3/3/2-to-5/6/5-RGB-anti-aliased-triangle-copy routine you have lurking on your hard disk. Categorizing, abstracting, and modularizing basic algorithms into a coherent set of APIs seems like a lot of work when you are doing it, but it saves everybody a lot more work in the long run. Interested developers can hook up with us on our mailing list or IRC channels.

Brian S. Julin Brian S. Julin is a graduate and employee of the University of Massachusetts, with a Bachelors of Science degree in Computer Systems Engineering. He works as a network engineer, supporting and expanding the UMASS state-wide network, which acts as the ISP for most public Higher Education schools in the State. He specializes in interactive two-way videoconferencing, Asyncronous Transfer Mode, and IP QoS.