See the introduction to LibGGI.
For a bit of background:
LibGGI was originally developed to access the graphics functionality KGI (the GGI kernel code) had provided. Support for different types of displays and hardware are provided by dynamically-loaded mini-libraries.
Nowadays LibGGI is a very generic piece of software, that will run on about every platform that has remotely heard of POSIX (ports to other systems such as Win32 are underway) and on many display subsystems.
Even if you don't want to deal with something like kernel drivers, you should consider using LibGGI, as it will give you a very broad range of supported hardware and platforms.
(Unfortunately, this can't get into some people's minds: you do not need to patch and recompile a kernel to use GGI at all!)
Yeah — sure. LibGGI won't hurt … If you can do graphics with about anything (X, SVGAlib, Glide) now, then you can with LibGGI. But your GGI applications will run on all of those without need for recompiling or anything.
Of course, to use LibGGI you need LibGGI applications. For developers, the API is stable now, so hack away and port your favorite applications to GGI :)
Yes. Why ? See above. I like it, when the same binary pops up as a window under X or fullscreen from the console (yet without the risk of console hangs or SUID binaries).
No, wrappers aren't always slow. We took great care to optimize things, and we actually do support acceleration, where available.
Or as one our developers puts it: You might want to mention squake running on svgalib-wrapper running on LibGGI running on X gives about the same framerate as squake running on SVGAlib directly on the gfxhw ;)
Because LibGGI is designed to be simple, it only provides basic drawing functions and visual management. Some applications may need more sophiscated functionality. This is provided by extensions, which are attached to LibGGI visuals (displays). Extensions have full access to the internals of LibGGI and may implement advanced features such as 3D, while using LibGGI's flexible DL system.
The configure scripts and Makefiles are automatically generated using the GNU autoconf (version >=2.13) and automake (>=1.4) tools. If you are building the CVS source, you need to have these tools installed and create these files by running the autogen.sh script included in the library directories.
The libraries in CVS already come with the required libtool (>=1.2d) macros, but if you have an existing libtool, beware that that it could cause conflicts while configuring. Please try moving your existing libtool installation first if you encounter such problems.
For a complete rebuild, you can run the buildall script in degas/lib/, which will automatically rebuild and reinstall LibGII, LibGGI, and the other libs that are considered stable.
Alternatively, use our daily snapshots, which will have the scripts automatically created for you.
Either you do not have a Linux 2.2.x kernel sources/headers installed or /usr/include/linux points to the headers for an older kernel.
If the newer kernel headers are available, you can use the --with-extra-includes=include_path option to LibGGI configure, or you can disable compiling the fbdev target (thus avoiding the errors) by using --disable-fbdev.
3.1. How to handle key repeat in games?
… ship turns as desired. However, we want constant rotation when the key is held down, and so we tried the emKeyRepeat event. This even works as desired, until the key is released, and the result is that the ship keeps spinning because there are so many emKeyRepeat events in the event queue.
What we need is the ship to stop moving as soon as the key is released...we'd like to be able to simply listen for the emKeyRelease event and, when it is encountered, flush the queue of all queued emKeyRepeat elements. However, I didn't see any documentation for manipulation of the event queue and so I'm at odds with what to do.
There is a better way:
When you get an evKeyPress event (e.g. for turn left), set a variable that says "make the ship turn left" and then handle that variable in your main loop, e.g. "if (turnleft) TurnShipLeft()". When you get an evKeyRelease event for that key, then clear that variable.
Not all targets have repeating keys, and on the ones that do, you can't rely on either the repeat speed (which could be really slow) or the delay before repeating. So using evKeyRepeat the way you described is not a good method for games.
3.2. How to copy indexed images to the screen?
Hi, I've written a simple PCX image loader with a "indexed image to ggiPixel-image converter" looking something like the following:
/*************************************************/ ggi_color tempc; ggi_pixel image[image_size]; for(i=0; i<256; i++) { tempc.r = RGBpalette[i].r<<8; <-- RGBpalette: RGB-triplets from PCX-file tempc.g = RGBpalette[i].g<<8; tempc.b = RGBpalette[i].b<<8; tempc.a = 0; image[i] = ggiMapColor(vis, &tempc); } /*************************************************/This works fine under X in Hi-Color modes (?x?x16Bpp), but it seems to slow down to "annoyingly slow" speed when using GT_8BIT modes with GGI_DISPLAY=palemu or when running X in 8bpp and "GGI_AUTO mode settings". Am I doing something wrong or is this a "feature" ??????
The above snippet is just a RGB-image-to-ggiPixel-image converter :) I assume you actually have an array of indices into the RGBpalette?
Note that doing the above in GT_8BIT modes is very slow because ggiMapColor() has to look up your RGB color in the visual's (default?) palette every time.
The obvious way to speed it up is to set the palettized visual's palette to be the same as the one in your indexed image:
ggi_visual vis; ggi_mode ggimode; /* ... */ if(GT_SCHEME(ggimode.graphtype) == GT_PALETTE) { ggi_color ggipalette[256]; ggi_pixel ggiimage[imagesize]; ggi_pixelformat *fp; int i; /* Translate RGBpalette to GGI palette */ for(i = 0; i<256; i++) { p[i].r = RGBpalette[i].r << 8; p[i].g = RGBpalette[i].g << 8; p[i].b = RGBpalette[i].b << 8; p[i].a = 0; } ggiSetPalette(vis, 256, ggipalette); /* Check return code! */ /* Make ggi_pixel operations portable to all types of hardware */ fp = ggiGetPixelFormat(vis); /* Translate indexed image to indexed-ggi_pixel-image */ for(i = 0; i<imagesize; i++) { ggiimage[i] = (image[i] >> fp->clut_shift) & fp->clut_mask; } } else { /* Other cases go here */ }
The above isn't the most efficiently coded (e.g. could use incrementing pointers instead of indexing the array every time), but you get the idea.
Note that you can also avoid function call overhead by translating RGBpalette into a buffer and using ggiPackColors() to map all colors at once. The gain may be negligible, but it gives you a packed buffer which is immediately usable as ggiPutBox, ggiPutHLine, etc. arguments. (ggi_pixel array values cannot be usually/portably used this way.)
Of course you can do the packing yourself as well. LibGGI provides all the hardware-specific information you need through ggiGetPixelFormat().
sleep(2) fails because it is being interrupted by the signals caused by manual syncing. The only way I can think of to get around this is to use select(2) or giiEventSelect(), but getting interrupted 20 times per second doesn't help you much, does it? :(
If you really want to sleep, the best way is to simply turn off SYNC mode (see ggiSetFlags(3ggi)).