  LibGGI
  Steve Cheng steve@ggi-project.org, Hartmut Niemann
  $Date: 1998/08/26 18:54:39 $

  This document describes LibGGI, a flexible, extensible, dynamic draw-
  ing library developed by the GGI project.
  ______________________________________________________________________

  Table of Contents

























































  1. Temporary preface

  2. Introduction

     2.1 What is known to work

  3. How To Install And Use

     3.1 Required Software

  4. LibGGI Functions

     4.1 Library control
        4.1.1 (TT
        4.1.2 (TT
        4.1.3 (TT
     4.2 Visual management
        4.2.1 (TT
        4.2.2 (TT
     4.3 Mode management
        4.3.1 The
        4.3.2 (TT
        4.3.3 (TT
        4.3.4 Mode negotiation
        4.3.5 (TT
        4.3.6 (TT
        4.3.7 (TT
        4.3.8 Convenience functions
        4.3.9 (TT
        4.3.10 (TT
        4.3.11 (TT
        4.3.12 (TT
        4.3.13 (TT
        4.3.14 (TT
        4.3.15 (TT
        4.3.16 (TT
     4.4 Frame management
        4.4.1 General
        4.4.2 (TT
        4.4.3 (TT
        4.4.4 (TT
        4.4.5 (TT
        4.4.6 (TT
        4.4.7 (TT
     4.5 Color and palette
        4.5.1 Basic Data Types
           4.5.1.1 (TT
           4.5.1.2 (TT
        4.5.2 (TT
        4.5.3 (TT
        4.5.4 (TT
        4.5.5 (TT
        4.5.6 (TT
        4.5.7 (TT
     4.6 Gamma and Gamma Maps
        4.6.1 (TT
        4.6.2 (TT
        4.6.3 (TT
        4.6.4 (TT
     4.7 Graphics context
        4.7.1 (TT
        4.7.2 (TT
        4.7.3 (TT
        4.7.4 (TT
        4.7.5 (TT
        4.7.6 (TT
     4.8 (TT
        4.8.1 (TT
     4.9 Primitives
        4.9.1 Format of Get/Put Buffers
        4.9.2 (TT
        4.9.3 (TT
        4.9.4 (TT
        4.9.5 (TT
        4.9.6 (TT
        4.9.7 (TT
        4.9.8 (TT
        4.9.9 (TT
        4.9.10 (TT
        4.9.11 (TT
        4.9.12 (TT
        4.9.13 (TT
        4.9.14 (TT
        4.9.15 (TT
     4.10 Character Output
        4.10.1 (TT
        4.10.2 (TT
        4.10.3 (TT
     4.11 Blits
        4.11.1 (TT
        4.11.2 (TT
     4.12 Origin
        4.12.1 (TT
        4.12.2 (TT
     4.13 Input and Event handling
        4.13.1 (TT
        4.13.2 (TT
        4.13.3 Events
        4.13.4 (TT
        4.13.5 (TT
        4.13.6 (TT
        4.13.7 (TT
        4.13.8 (TT
        4.13.9 (TT
     4.14 DirectBuffer
        4.14.1 Types of Buffers
           4.14.1.1 Framebuffer
           4.14.1.2 Pixel Linear Buffer
        4.14.2 Accessing the Buffer
           4.14.2.1 Swapping Requirements
           4.14.2.2 Paged Buffers
        4.14.3 API Structures
        4.14.4 API Functions
           4.14.4.1 (TT
           4.14.4.2 (TT
           4.14.4.3 Example: How To Obtain a DirectBuffer
     4.15 Miscellaneous Functions
        4.15.1 Synchronous and asynchronous drawing modes
        4.15.2 (TT
        4.15.3 (TT
        4.15.4 (TT
        4.15.5 (TT
        4.15.6 (TT
        4.15.7 (TT

  5. LibGGI usage guidelines

     5.1 Hints on memory visuals
     5.2 LibGGI and threads
     5.3 Mixing LibGGI and direct frame buffer access
     5.4 Inactivated applications, Redraw requests
     5.5 Environment variables
        5.5.1 GGI_DEBUG
        5.5.2 GGI_DEFMODE
        5.5.3 GGI_DISPLAY

  6. LibGGI initialization example

  7. API change log

     7.1 Pending changes
     7.2 Changes for 1.5
     7.3 1.3.0 to 1.4.0


  ______________________________________________________________________

  1.  Temporary preface

  As of August 24th, 1998, some changes to the libggi API are still
  being implemented and tested.  It is now nearly complete; however, if
  you encounter any difference between this documentation and the
  implementation, please mail me at niemann@cip.e-technik.uni-
  erlangen.de, or steve@ggi-project.org, or the GGI mailing list. Thank
  you. (hn)


  2.  Introduction


  LibGGI, the dynamic GGI (General Graphics Interface) library is a
  flexible drawing library.

  It provides an opaque interface to the display's acceleration
  functions. It was originally intended to allow user programs to
  interface with KGI, the GGI Kernel Graphics Interface, but other
  display types can be easily used by loading the appropriate "display
  target" (e.g. X, memory).

  LibGGI consists of a main library (libggi.so) and a multitude of
  dynamic drivers. The library then loads the necessary "drivers" for
  the requested mode, taking hints from the graphics device if
  necessary. LibGGI can also load extension libraries, e.g. to provide
  enhanced 2D and 3D functions.

  It has been designed after having a look at several existing
  libraries, and so far we have found porting to be quite simple from
  and to most of them.

  Library functions are in ggi/ggi.h.


  2.1.  What is known to work



  o  Modes:

  o  VGA 1bit, 16color, 8bit, and ModeX

  o  text-16, linear-1bit,-8bit,-15/16bit and -32bit frame buffers+ up
     to 16bit ramdacs

  o  Targets:

  o  KGI: Kernel Graphics Interface


  o  X: X Window System (X must be in the same mode as the requested
     visual)

  o  Xlib: X Window alternate method; uses X for primitives

  o  memory: off-screen memory

  o  multi: display on multiple targets at once

  o  AA: AAlib, an ASCII-Art renderer

  o  XF86DGA: XFree86 server Direct Graphics Access

  o  SVGAlib: SUID root console graphics library

  o  GLIDE: 3Dfx

  o  Terminfo: GGI textmodes on terminals

  o  Sub-target: Visual-within-a-visual

  o  Tile: display in multiple visuals each showing a component part

  o  MonoText: emulate 8-bit visual on text-only visual (like AAlib)

  o  TrueEmu: emulate true-color (24-bit) on visual of any other depth

  o  fbdev: fbcon framebuffer devices, and kgicon

  o  suidkgi: use KGI drivers in userspace, setuid root

  o  Wrappers:

  o  SVGAlib (some functions are missing, but many demos work.)

  o  A number of demos

  The code is still alpha, so things may break overnight or change
  unexpectedly, but the main targets (X, svgalib, fbdev) are quite
  stable.


  3.  How To Install And Use


  In the libggi directory, do:



       $ make config # will be done automatically on first make
       $ make
       $ su -c "make install"




  For some demos of libggi code, see the demos subdirectory which has
  several programs showing around the features of LibGGI:



       $ make demos
       $ cd demos
       $ ./demo
       ...

  The most importent of them is demo.c which we use ourselves for
  checking new features. demo.c is heavily commented to allow people to
  learn LibGGI by example. There is also speed.c which is a speed and
  consistency test application, which can be used if you changed
  something in LibGGI to see if you have broken anything.

  LibGGI will automatically default to the most suitable display target.
  However, this can be overridden using the GGI_DISPLAY environment
  variable (see section ``GGI_DISPLAY''), set to the name of the display
  target, plus any additional arguments.

  The GGI_DEBUG environment variable can be set to 0 (default) for no
  debugging information, or 255 for verbose debugging information.


  3.1.  Required Software


  To use LibGGI, you will need:


  o  Most likely GNU Make to build LibGGI.

  o  linuxthreads-0.5 or higher (or glibc-2.0.2) if compiling with
     multi-thread support

  o  ld.so 1.7.14 or higher

  o  GGI Linux kernel if using display-KGI target.

  o  X Window System if using display-X target.

  o  XFree86 if using display-DGA target.

  o  AAlib if using display-AA target.


  4.  LibGGI Functions




  4.1.  Library control

  4.1.1.  int ggiInit(void);


  Initalizes the library. This function must be called before using
  other LibGGI functions; otherwise results will be undefined.

  Return: 0 for OK, otherwise an error code.

  Example:


       ______________________________________________________________________
       if(!ggiInit())
               exit(EXIT_FAILURE);
       /* do some libggi stuff */
       ggiExit();
       ______________________________________________________________________





  4.1.2.  int ggiExit(void);


  Uninitializes the library and automatically cleanup. This should be
  called after an application is finished with the library. If any GGI
  functions are called after the use of ggiExit the results will be
  undefined.

  Return:

     0  after successfully cleaning up,

     >0 the number of 'open' ggiInit calls, if there has been more than
        one call to ggiInit. As ggiInit and ggiExit must be used in
        properly nested pairs, e.g. the first ggiExit after two ggiInits
        will return 1.

     <0 error, especially if more ggiExit calls have been done than
        ggiInit calls.

  Example:


       ______________________________________________________________________
       if (!ggiInit())
          exit(1);  /* can't start! */
       /* do some libggi stuff */
       ggiExit();
       ______________________________________________________________________





  4.1.3.  void ggiPanic(const char *format, ...);


  Graceful shutdown for fatal errors with reporting. May be used like
  printf(3). It will shut down the graphics modes active, close all
  visuals, print the error message given and then exit the application.

  ggiPanic() should only be used by usermode programs when something is
  really screwed, and they do not know what to do. The same applies for
  libraries, but might be used in rare situations such as corruption of
  critical data structures.

  Return: never returns.

  Example:


       ______________________________________________________________________
       ggiPanic("Aiee! Penguin on fire! ;-) Error code: %d", err);
       ______________________________________________________________________





  4.2.  Visual management


  A visual is simply a thing you can draw on. For example, a VT in
  fullscreen-mode, an X window, an invisible memory area, and a printer.
  It is identified by its handle of type ggi_visual_t, which is given to
  all drawing functions to indicate which visual to operate on.
  Each visual is completely independent of each other. You can use these
  visuals to display on multiple monitors and/or in multiple windows or
  to work on "virtual" graphics devices like in-memory pixmaps or even
  PPM-files on disk.

  Most LibGGI functions are passed a visual returned by ggiOpen() to
  know where they should operate on.

  ggi_visual_t is opaque to the user. Do not try to access any part of
  the structure directly. It may change without notice.


  4.2.1.  ggi_visual_t ggiOpen(const char *display, ...);


  Opens a visual. This function is given a NULL terminated list of the
  names of LibGGI dynamic drivers to load. This is usually one display
  target. Once loaded, they will all be associated with the single
  visual. Giving no arguments except the NULL instructs LibGGI to open
  the default display target (e.g. display-X, set by GGI_DISPLAY, see
  chapter ``GGI_DISPLAY'').

  Return: The opened visual, or NULL for error.

  Example:


       ______________________________________________________________________
       memory_visual = ggiOpen("display-memory", NULL);

       /* Get from GGI_DISPLAY enviroment variable */
       default_visual = ggiOpen(NULL);

       if(!memory_visual || !default_visual)
               return EXIT_FAILURE;
       ______________________________________________________________________





  4.2.2.  int ggiClose(ggi_visual_t vis);


  Releases and destroys the visual and the associated internal control
  structures. This will close X windows, return consoles to text-mode,
  etc.

  If focus is on the closed visual, focus is set to NULL.

  Return: 0 for OK, otherwise an error code.

  Example:


       ______________________________________________________________________
       memory_visual = ggiOpen("display-memory", NULL);

       /* do some drawing, save image, etc. */

       ggiClose(memory_visual);
       ______________________________________________________________________




  4.3.  Mode management

  After opening the visual, you must set a mode (e.g. the dimensions,
  how many colors, etc.) before you can do anything useful with it, such
  as drawing.


  4.3.1.  The ggi_mode  struct

  This structure defines a visual's mode.

  The definition in ggi/ggi.h is:


       ______________________________________________________________________

       typedef struct { sint16   x, y; } ggi_coord;

       typedef struct    /* requested by user and changed by driver    */
       {
               uint32          frames;         /* frames needed                        */
               ggi_coord       visible;        /* vis. pixels, may change slightly     */
               ggi_coord       virt;           /* virtual pixels, may change           */
               ggi_coord       size;           /* size of visible in mm                */
               ggi_graphtype   graphtype;      /* which mode ?                         */
               ggi_coord       dpp;            /* dots per pixel                       */
       } ggi_mode;
       ______________________________________________________________________




  You don't need to care about the definition, if you want to set a
  mode, but it is necessary if you want to find out the mode actually
  set.


  Use of multiple buffering is specified in the frames member of the
  ggi_mode struct, as the number of screen buffers needed.

  dpp specifies the number of dots per pixel.  For graphic modes, it is
  1 (x and y) by definition.  In text modes, it is the font size (each
  character in text modes is a pixel).

  Please note that the visible and virtual size are given in pixels, not
  dots. This makes a difference for text modes, because a character is
  treated as one pixel, but consists of a dpp.x*dpp.y sized matrix of
  dots.



  4.3.2.  ggi_graphtype

  LibGGI defines a number of common graphic types, organized by
  bitdepth.

  Currently defined graphtypes include:


     GT_AUTO
        is equivalent to the GGI_AUTO (see below) and means basically:
        please take your default value. Where possible this is currently
        a graphics mode, often the highest.

     GT_TEXT16

     GT_TEXT32
        text modes with word- and longword-aligned characters.


     GT_1BIT

     GT_4BIT

     GT_8BIT
        (These modes use a palette.)


     GT_15BIT

     GT_16BIT

     GT_24BIT

     GT_32BIT
        graphics modes with the respective bits per pixel.  Note that
        for 32-bit modes, only the size (bits per pixel) is 32-bits, the
        depth (significant bits) is 24-bit.


  The fuller graphtype definition consists of:


     depth
        Number of bits-per-pixel

     access size
        Number of significant bits

     scheme
        Mode "category": e.g. GT_TEXT (text modes), GT_TRUECOLOR (pixel
        is a direct RGB value), GT_GREYSCALE (grayscale :-), GT_PALETTE
        (each pixel is an index to a colormap)

     subscheme
        Miscellaneous info.  Indicates whether the pixel values are in
        reverse byte or bit order, etc.

  These are packed into ggi_graphtype.  See ggi/types.h for details.

  Supposedly, applications can request GGI_AUTO in any of these fields
  to get a 'recommended' setting, and make their own graphtypes, but
  this is probably not supported yet by the targets.

  However, applications can usually request one of the commonly used
  graphtypes above instead of making the graphtype themselves.


  4.3.3.  GGI_AUTO

  If a mode is set or checked, any size parameter may be GGI_AUTO
  (defined in ggi/types.h.  This is a placeholder.

  The behaviour is:

  o  All parameters that are specified in GGI_DEFMODE are taken from
     there.

  o  If all parameters are equal GGI_AUTO, the GGI_DEFMODE, or, if that
     is unset, the target's default mode is used.


  If some paramters are set, then the goal is to find a working mode
  that meets the given constraints.



  o  If a visible size is given but no virtual, the lowest reasonable
     (taking alignment and accelleration constraints into account)
     should be used.


  o  If either visible x or y is given, the other one should give a x/y
     ratio close to that of the screen size, so normally about 4/3.


  o  If a virtual size is given but no visible, the highest possible
     visible size is selected.


  o  If no size is given, the driver uses some builtin default.


  o  If the graphtype is unspecified, the highest possible graphtype
     that meets the geometry constraints is set/suggested.


  o  dpp.x and dpp.y will be 1 for graphics. For text modes the largest
     possible dpp.x and dpp.y (the most fine-grained font) should be
     used.


  The rules above are recommendations to the driver implementer and in
  no way guaranteed. The only guarantee is that the returned mode
  works[*]. But if they are applied in the listed order, the result
  should be pretty much what the user expects.

  [*] In the rare case that the returned mode doesn't work, an
  application can assume that any further mode setting will not work on
  the visual and can give up.

  As of March 3rd, 1998, the KGI drivers can't handle GGI_AUTO well, so
  please specify a complete default mode with GGI_DEFMODE.


  4.3.4.  Mode negotiation

  There are three types of mode calls:

  o  The ggiCheck*Mode functions test whether a given mode is acceptable
     or suggest a better one,

  o  the ggiSet*Mode functions try to set the specified mode and fail if
     that is impossible. ggiSetMode then returns a better suggestion, as
     ggiCheck*Mode do.  (Note that the suggested mode is not silently
     set.)

  o  ggiGetMode returns the mode that is currently set.

  If a mode can not be set, the struct passed is changed to the
  suggested mode as follows:


  o  Resolutions are always adjusted up. If you want the next lower,
     start out at 1,1 (or somewhere else reasonable) and jump up the
     ladder.

     Only if the maximum resolution would be exceeded, resolutions are
     adjusted down to the maximum.

     The above applies to visible and virtual size. If there is
     interference between them, the visible size is satified first if
     possible, then the virtual size.

  o  Note that the adjustment of one value do not normally affect other
     values. For example, if 320x100 (320x200) is requested, the visible
     size may be adjusted to 320x200, but virtual size will be left
     alone. Of course, if the virtual size becomes less than visible
     size, then it will be adjusted as well. A good rule of thumb is
     that anything returned by ggiCheckMode() is minimally valid.

  o  Font sizes (i.e. the size of the pixel in textmodes) are handled
     the other way round: they are adjusted down except when there is
     nothing below.

  o  Graphtype: Modes are normally card-dependant and not too dependant
     on size (except for maxsize-limits etc.)

     The basic rationale is to change graphtype only, if the card does
     not support it at all. If max-resolution is exceeded, then that is
     adjusted down and not the graphtype. This assumes, that if you
     request true-color, you really want that and not so badly the
     resolution you requested. If this is not the case, you can still
     retry with another graphtype or GT_AUTO.

     If it is necessary to change to change the type of other visuals,
     the order should be ascending (if possible), i.e.
     1->4->8->15->16->24/32 bit. So you always get a mode which can do
     more than you requested. Only when no better modes are available,
     the type is adjusted down.

  o  It is possible to pass GGI_AUTO as any of the parameters. GGI_AUTO
     is a placeholder (e.g. the program does not care about a specific
     parameter).  The display target will reset GGI_AUTO paramter to a
     default, such as its maximum/preferred/GGI_DEFMODE resolution,
     while being compatible with the other settings. Note that the
     presence of GGI_AUTO is not flagged as an error. If
     ggiSet{Graph/Text}Mode() is given GGI_AUTO as one or more of its
     arguments, it will silently set a mode.


  4.3.5.  int ggiSetMode(ggi_visual_t visual, ggi_mode *tm);


  Set any mode (text or graphics).

  Return: 0 for OK, otherwise could not set mode.

  If GGI_AUTO/GT_AUTO is specified for any of the members of *tm, these
  are filled in with the 'recommended' parameters, following the rules
  above.  If the mode cannot be set, a mode is suggested in *tm, but it
  will not be silently set.

  However, you'll probably want to use the convenience functions
  ggiSetTextMode() and ggiSetGraphMode() instead of this function.


  4.3.6.  int ggiGetMode(ggi_visual_t visual, ggi_mode *tm);


  Get the current mode. tm will be filled with the current mode on
  return.


  Return: 0 for OK, otherwise an error code.


  4.3.7.  int ggiCheckMode(ggi_visual_t visual, ggi_mode *tm);


  Check any mode (text or graphics).

  Return: A return of 0 means that a setmode call for this mode would
  succeed.  Otherwise, the mode is given cannot be set.


  4.3.8.  Convenience functions


  The ggiCheck{Text,Graph}Mode() and ggiSet{Text,Graph}Mode() functions
  simply accept mode parameters as arguments rather than having the
  application muck with the ggi_mode struct itself.  Otherwise, they are
  functionally equivalent to the "master" ggiCheckMode() and
  ggiSetMode() functions.

  However, you cannot specify multiple buffering with these functions;
  for that, fill in a ggi_mode and use ggiSetMode() above.


  4.3.9.  int ggiSetTextMode(ggi_visual_t visual, int cols, int rows,
  int vcols, int vrows, int fontx, int fonty);


  Set a textmode with given columns and rows, virtual columns and rows
  and a font of the given size.

  Return: 0 for OK, otherwise could not set mode.

  The fontsize is actually the size of the pixel (ggi_mode.dpp), in
  textmodes.


  4.3.10.  vcols, int vrows, fontx, int fonty, ggi_mode *suggested_mode,
  ...); int ggiCheckTextMode(ggi_visual_t visual, int cols, int rows,
  int


  Check a text mode, with a null-terminated list of mode features. The
  last argument must be NULL.

  Return: A return of 0 means that a setmode call for this mode would
  succeed.  Otherwise, the mode is given cannot be set. In this case, tm
  is changed to the suggested mode:

  If suggested_mode is not NULL, then it will be filled with the
  suggested mode, as documented under ggiCheckMode(). In the future,
  there may be more arguments, but currently there is nothing that may
  be put between the final NULL and suggested_mode.


  4.3.11.  int yv, ggi_graphtype type); int ggiSetGraphMode(ggi_visual_t
  visual, int x, int y, int xv,


  Set a graphics mode with a visible area of size x/y and a virtual area
  of size vx/vy (you can pan aound the virtual area using the
  ggiSetOrigin()) and the specified graphics type.

  Return: 0 for OK, otherwise could not set mode.

  4.3.12.  int yv, ggi_graphtype type, ggi_mode *suggested_mode, ...);
  int ggiCheckGraphMode(ggi_visual_t visual, int x, int y, int xv,


  Check a graphics mode, with a null-terminated list of mode features.
  The last argument must be NULL.

  Return: A return of 0 means that a setmode call for this mode would
  succeed.  Otherwise, the mode is given cannot be set. In this case, tm
  is changed to the suggested mode:

  If suggested_mode is not NULL, then it will be filled with the
  suggested mode, as documented under ggiCheckMode(). In the future,
  there may be more arguments, but currently there is nothing that may
  be put between the final NULL and suggested_mode.

  Example:


       ______________________________________________________________________
       /* Use only my mode... but you really should try to negotiate though */
       err = ggiCheckGraphMode(vis, 320, 200, 320, 200, GT_8BIT, NULL, NULL);
       if(err)
               return EXIT_FAILURE;

       /* OR use a suggested mode if our mode not available*/
       err = ggiCheckGraphMode(vis, 320, 200, 320, 200, GT_8BIT, &sug_mode, NULL);
       ggiSetMode(&sug_mode);
       ______________________________________________________________________





  4.3.13.  ggiParseMode(const char * s, ggi_mode * m)

  This function parses a string into a mode, using the following
  template:


  visible-x x visible-y # virtual-x x virtual-y D dpp-x x dpp-y F
  frames(T)[graphtype or bpp value]

  Whitspace is ignored before and after each number.

  All values can be omitted (and default to GGI_AUTO).

  Please do export a fully defined GGI_DEFMODE (e.g.
  320x200#320x200D1x1[8]) if your KGI driver does not support GGI_AUTO
  yet.

  T indicates text modes, as an alternative the graphtype can be 'T'
  also (or e.g. GT_TEXT16, of course).


  Examples include:


     640x480
        just a visible size

     640x480#640x960
        same size, but double-height virtual screen

     #1024x768
        only virtual size defined
     80x40T
        (default-bitsized) text mode with 80x40 characters

     #x100T
        text mode with 100 virtual lines

     #x100[T]
        same

     640x400[8]
        640x400 at 8 bits per pixel

     640x400[8bpp]
        640x400[8BIT]  640x400[GT_8BIT] all the same

     [T32] [32T] [GT_TEXT32] [TEXT32]
        32bit text mode


  4.3.14.  int ggiSPrintMode(char * s, ggi_mode *m);

  4.3.15.  int ggiFPrintMode(FILE * s, ggi_mode *m);

  4.3.16.  int ggiPrintMode(ggi_mode *m)


  These functions print all the members of ggi_mode in a human-readable
  form.  ggiSPrintMode() outputs to a preallocated string buffer,
  ggiFPrintMode() outputs to a stdio FILE, and ggiPrintMode() outputs to
  standard output.  These functions correspond to sprintf(), fprintf(),
  and printf() respectively.


  4.4.  Frame management


  Multiple buffering is the allocation of multiple framebuffers and
  drawing on/reading/displaying them independently.  Applications use
  double-buffering to prepare a picture offline and switching display to
  it.

  For compatibility with older applications the current ggiSet*Mode
  calls will not be changed. So this feature is currently only
  accessible through changing the mode struct and using ggiSetMode.


  4.4.1.  General

  The frames field in the ggi_mode struct indicates the number of screen
  buffers requested. It will default to 1.

  Frames will be numbered 0 ... <frameno> -1

  After mode setting frame 0 is active for reading, writing and display.

  Three additional functions are required, to switch between these
  frames for drawing, reading back (ggiGet*) and for displaying, e.g.:


  4.4.2.  int ggiSetDisplayFrame(ggi_visual_t vis, int frameno)

  This function sets the frame that gets displayed.




  4.4.3.  int ggiSetWriteFrame(ggi_visual_t vis, int frameno)

  This function sets the frame for write operations like ggiPuts,
  ggiHLine ...


  4.4.4.  int ggiSetReadFrame(ggi_visual_t vis, int frameno)

  This function sets the frame for read operations, like ggiGetPixel and
  the ggiCrossBlit source.

  All functions return 0 if they succeed, and -1 if they fail.

  All libGGI primitives will obey the current read/write frame setting.


  4.4.5.  int ggiGetDisplayFrame(ggi_visual_t vis)

  This function reports the frame currently displayed. It may not fail.


  4.4.6.  int ggiGetWriteFrame(ggi_visual_t vis)

  This function reports the frame currently written to. It may not fail.


  4.4.7.  int ggiGetReadFrame(ggi_visual_t vis)

  This function reports the frame currently read from. It may not fail.



  4.5.  Color and palette


  Visuals may have an indirect mapping off the pixel-value to a color
  via a programmable palette. This is e.g. true for the 8 bit IBM VGA
  modes. But even for "direct-mapped" modes, you will need to know which
  color maps to which pixel-value.

  Try to keep the results of palette lookups in your application for
  efficiency purposes.


  4.5.1.  Basic Data Types

  4.5.1.1.  ggi_color

  The ggi_color struct has 16 bit wide entries for red (.r), green (.g),
  and blue (.b) values.  It also has an alpha value (.a>) which is
  unused in libggi, but allow LibGGI extensions to store an alpha value
  there.  Please scale your palette values as necessary.


  4.5.1.2.  ggi_pixel

  The ggi_pixel, or the pixelvalue is a hardware-dependent
  representation of a color. It is usually calculated from a ggi_color
  by ggiMapColor or read from the visual by ggiGetPixel, and you can
  safely assume that the relationship between a ggi_color and it's
  associated ggi_pixel value does not change unless you change the
  visual or the mode the current visual is in.

  You can also do calculations with ggi_pixel values.  Their format is
  defined in the ggi_pixelformat section.

  4.5.2.  ggi_pixel ggiMapColor(ggi_visual_t vis, ggi_color * col);


  Gets the pixelvalue for the given color.

  Return: the (closest) pixel value


  4.5.3.  int ggiUnmapPixel(ggi_visual_t vis, ggi_pixel pixel, ggi_color
  *col);


  Gets the color associated with a given pixelvalue.

  Return: 0 for OK, otherwise an error code.


  4.5.4.  int len); int ggiPackColors(ggi_visual_t vis, void *buf,
  ggi_color *cols,


  Converts the colors in cols to pixelvalues in buf.

  Return: 0 for OK, otherwise an error code.

  The output of ggiPackColors is suitable for input to the
  ggiPut{HLine,VLine,Box} functions.


  4.5.5.  int len); int ggiUnpackPixels(ggi_visual_t vis, void *buf,
  ggi_color *cols,


  Converts pixelvalues in buf to individual elements of cols.

  Return: 0 for OK, otherwise an error code.

  This function maybe used to convert buffers output by the
  ggiGet{HLine,VLine,Box} functions from the pixelvalue representation
  to ggi_colors.


  4.5.6.  *cmap); int ggiSetPalette(ggi_visual_t vis, int s, int len,
  ggi_color


  Sets a range of palette values, of length len, starting at index
  number s.


  Return: The number of the first entry changed, otherwise an error
  code.

  When called with len=0 this function will not automatically succeed,
  but the return code will indicate whether there is a writable CLUT.

  The index can be -1 to indicate to indicate that the palette can be
  installed anywhere in the CLUT.  This allows optimised use in
  windowing environments (minimizes color flashing between windows) and
  should be used.


  4.5.7.  *cmap); int ggiGetPalette(ggi_visual_t vis, int s, int len,
  ggi_color


  Gets a range of palette values, of length len, starting at index
  number s.

  Return: 0 for OK, otherwise an error code.

  When called with len=0 this function will not automatically succeed,
  but the return code will indicate whether there is a readable CLUT.


  4.6.  Gamma and Gamma Maps


  Some truecolor modes on some hardware can use the DAC's palette to
  lookup the values before sending to the monitor.  Generally this is
  used for gamma correction by filling the lookup table with a curve,
  hence the name "gamma map" I suppose, but it could be used for other
  things e.g.  special effects in games.


  4.6.1.  int ggiGetGammaMap(ggi_visual_t vis,int s,int len,ggi_color
  *gammamap);

  4.6.2.  int ggiSetGammaMap(ggi_visual_t vis,int s,int len,ggi_color
  *gammamap);


  Set or get the gamma map, for len colors starting at s.

  Return: 0 for OK, otherwise an error code.


  4.6.3.  int ggiGetGamma(ggi_visual_t vis,ggi_float *r,ggi_float
  *g,ggi_float *b);

  4.6.4.  int ggiSetGamma(ggi_visual_t vis,ggi_float r,ggi_float
  g,ggi_float b);


  Set or get the gamma correction.

  Return: 0 for OK, otherwise an error code.



  4.7.  Graphics context


  LibGGI has a current context associated with each visual. This is done
  for performance reasons, as LibGGI can set up pointers to optimized
  functions when the GC changes (which can be monitored, as it may only
  be changed by the functions mentioned below).


  4.7.1.  int ggiSetGCForeground(ggi_visual_t vis, ggi_pixel color);


  Sets the current colors for the foreground, used in all normal
  graphics functions.

  Return: 0 for OK, otherwise an error code.


  4.7.2.  int ggiSetGCBackground(ggi_visual_t vis, ggi_pixel color);



  Sets the current colors for the background, used in some 2-color
  operations like drawing text.

  Return: 0 for OK, otherwise an error code.


  4.7.3.  int ggiGetGCForeground(ggi_visual_t vis, ggi_pixel * color);


  Reads the current foreground color.

  Return: 0 for OK, otherwise an error code.


  4.7.4.  int ggiGetGCBackground(ggi_visual_t vis, ggi_pixel * color);


  Reads the current background color.

  Return: 0 for OK, otherwise an error code.


  4.7.5.  right,int bottom); int ggiSetGCClipping(ggi_visual_t vis, int
  left, int top, int


  Set the current clipping rectangle to (left,top)-(right,bottom).
  (right and bottom are the bottom right corner of the rectangle + 1).

  Return: 0 for OK, otherwise an error code.

  Initially the clipping rectangle is the whole virtual screen.

  All libGGI drawing primitives obey the clipping rectangle.

  For more advanced clipping please use libggi2d.

  Return: 0 for OK, otherwise an error code.


  4.7.6.  *right, int *bottom); int ggiGetGCClipping(ggi_visual_t vis,
  int *left, int *top, int


  Get the current clipping rectangle's coordinates.

  Return: 0 for OK.



  4.8.  ggi_pixelformat


  This structure describes the format of a ggi_pixel.  An application
  would use this if it wanted to directly output ggi_pixels rather than
  calling ggiMapColor() or ggiPackColors() (to convert a ggi_color to a
  ggi_pixel value).









  ______________________________________________________________________

  /* Pixelformat for ggiGet/Put* buffers and pixellinearbuffers */
  typedef struct {
          int             depth;          /* Number of significant bits */
          int             size;           /* Physical size in bits */

          ggi_pixel       red_mask;       /* Bitmask of red bits */
          ggi_pixel       green_mask;     /* Bitmask of green bits */
          ggi_pixel       blue_mask;      /* Bitmask of blue bits */
          ggi_pixel       alpha_mask;     /* Bitmask of alphachannel bits */

          ggi_pixel       clut_mask;      /* Bitmask of bits for the clut */
          ggi_pixel       fg_mask;        /* Bitmask of foreground color */
          ggi_pixel       bg_mask;        /* Bitmask of background color */
          ggi_pixel       texture_mask;   /* Bitmask of the texture (for
                                             textmodes - the actual character) */
          uint32          flags;          /* Pixelformat flags */
  } ggi_pixelformat;

  /* Pixelformat flags */
  #define GGI_PF_REVERSE_ENDIAN   0x01
  #define GGI_PF_HIGHBIT_RIGHT    0x02
  #define GGI_PF_HAM              0x04
  #define GGI_PF_EXTENDED         0x08
  ______________________________________________________________________




  depth and size are same as the depth and access size information
  specified in the ggi_graphtype.

  clut_mask is used in GT_PALETTE modes, indicating which bits
  correspond to an index to the CLUT (color look-up table).

  fg_mask, bg_mask, and texture_mask are for text modes only.


  4.8.1.  ggi_pixelformat *ggiGetPixelFormat(ggi_visual_t vis);


  This function obtains the default pixel format for the given visual.

  Return: pointer to ggi_pixelformat structure.



  4.9.  Primitives


  LibGGI has three basic types of primitives when it comes to filling
  rectangular areas (including the degenerate cases of horizontal and
  vertical lines and single pixels).

  We have found three operations commonly performed on such areas :

  o  Draw: This means you set all contained pixels to the current
     foreground color (maybe modified by the update-operations as set in
     the current graphics context).

  o  Put: Fill the area with pixels of different value from a buffer.

  o  Get: Read pixels from the screen into such a buffer.


  4.9.1.  Format of Get/Put Buffers


  The format of the pixels in ggiGet* and ggiPut* buffers are defined by
  ggi_pixelformat (please see the ggi_pixelformat section above).

  Pixels are stored linearly, e.g. a rectangle with a width of three and
  a height of two will be stored pixel (0,0) (1,0) (2,0) (0,1) (1,1),
  (2,1) in that order.

  Both ggiGet* and ggiPut* use chunky pixels, unpacked, even if their
  representation in the framebuffer is packed (i.e. pixel size not
  multiple of 8 bits) or non-linear.  Thus the application does not need
  to know how to use planar or packed pixels for non-direct acccess.

  (You may specify use of packed buffers using the GT_SUB_PACKED_GETPUT
  ggi_graphtype flag, but as of this writing, no targets implement that
  yet.)

  The buffer passed to the ggiGet* and ggiPut* functions should be
  allocated for at least width * height *
  ((ggiGetPixelFormat()->size+7)8)/ bytes.  (That is, the pixel size is
  obtained from ggi_pixelformat->size, rounded to a multiple of 8 bits
  (one byte), multiplied by x and y.)



  4.9.2.  int ggiDrawPixel(ggi_visual_t vis, int x, int y);

  4.9.3.  int ggiPutPixel(ggi_visual_t vis, int x, int y, ggi_pixel
  col);

  4.9.4.  int ggiGetPixel(ggi_visual_t vis, int x, int y, ggi_pixel
  *col);


  Draws/Puts/Gets a single pixel at x/y.

  Return: 0 for OK, otherwise an error code.


  4.9.5.  int ggiDrawHLine(ggi_visual_t vis, int x, int y, int w);

  4.9.6.  *buf); int ggiPutHLine(ggi_visual_t vis, int x, int y, int w,
  void

  4.9.7.  *buf); int ggiGetHLine(ggi_visual_t vis, int x, int y, int w,
  void


  Draws/Puts/Gets a horizontal line from x/y, extending w pixels in the
  positive x direction (normally right).

  Return: 0 for OK, otherwise an error code.


  4.9.8.  int ggiDrawVLine(ggi_visual_t vis, int x, int y, int h);

  4.9.9.  *buf); int ggiPutVLine(ggi_visual_t vis, int x, int y, int h,
  void

  4.9.10.  *buf); int ggiGetVLine(ggi_visual_t vis, int x, int y, int h,
  void



  Draws/Puts/Gets a vertical line from x/y, extending h pixels in the
  positive y direction (normally down).

  Return: 0 for OK, otherwise an error code.


  4.9.11.  int ggiDrawBox(ggi_visual_t vis, int x, int y, int w, int h);

  4.9.12.  *buf); int ggiPutBox(ggi_visual_t vis, int x, int y, int w,
  int h, void

  4.9.13.  *buf); int ggiGetBox(ggi_visual_t vis, int x, int y, int w,
  int h, void


  Draws/Gets/Puts a filled rectangle at x/y and extending w pixels in
  the positive x direction and h in the positive y direction.

  Return: 0 for OK, otherwise an error code.




  4.9.14.  int ggiFillscreen(ggi_visual_t vis);


  Fills the entire virtual screen. May be more efficient than the
  corresponding call to ggiDrawBox().

  Return: 0 for OK, otherwise an error code.



  4.9.15.  int ggiDrawLine(ggi_visual_t vis, int x, int y, int xe, int
  ye);


  Draws any line from x/y to xe/ye. The line is exact; the pixel set is
  no more than 0.5 pixels off the place it should be.

  Return: 0 for OK, otherwise an error code.


  4.10.  Character Output


  LibGGI provides means to do basic character output. These functions
  are intended for debugging and simple GUI applications. They are
  simple on purpose, without loadable font support, without
  internationalisation support, without changeable size. All more
  complex character functions go beyond the scope of this base library.

  Only the standard ASCII charset ('\0x20' ... '\0x7f') is supported.

  In graphics modes, ggiPutc() and ggiPuts() use at least 8x8 character
  fonts.  In text mode, (by definition) the character cell is 1x1. (The
  actual font size, of which the application usually doesn't need to
  know, is specified in the dpp member of ggi_mode)


  4.10.1.  int ggiPutc(ggi_visual_t vis, int x, int y, char c);


  Puts a single character on a graphical visual. This is only a very
  simple routine using a fixed-width font.

  Return: 0 for OK, otherwise an error code.


  4.10.2.  int ggiPuts(ggi_visual_t vis, int x, int y, const char *str);


  Puts multiple characters at once. No special handling is applied to
  control characters like CR or LF. You will see the associated glyph
  being displayed, so do this yourself if you need.  ggiPuts() also does
  not wrap text at the clipping rectangle; it merely stops.

  Return: 0 for OK, otherwise an error code.

  Don't use ggiPutc() repeatedly for multiple characters, as ggiPuts()
  might be able to optimize the output of muliple chars at once.

  Example:



       ______________________________________________________________________
       ggiPuts(vis, 0, 100, "Hello World!");
       ______________________________________________________________________





  4.10.3.  int ggiGetCharSize(ggi_visual_t vis, int *width, int *height)

  This function stores the size of a ggiPutc character, measured in
  pixels, in width and height. For text mode, it will put (1,1) there by
  definition.  For graphical modes, it puts the appropriate size
  (usually 8,8).

  Return: 0 for OK, otherwise an error code.


  4.11.  Blits

  4.11.1.  nx, int ny); int ggiCopyBox(ggi_visual_t vis, int x, int y,
  int w, int h, int


  This is a area-to-area-blit, all in the same visual. Copy the box
  described by x,y,w,h to the new location nx,ny. This automatically
  takes care of overlaps and optimizes for the given target (e.g. uses
  HW-accel or intermediate buffers as appropriate).

  Return: 0 for OK, otherwise an error code.

  ggiCopyBox will transfer an area between frames when the read frame is
  not the same as the write frame.


  4.11.2.  int ggiCrossBlit(ggi_visual *src, int sx, int sy, int sw, int
  sh, ggi_visual *dst, int dx, int dy)


  Blits a rectangular memory area from one visual to another. It handles
  colorspace-conversion. (Though it can be quite expensive, so take
  care.)

  Return: 0 for OK, otherwise an error code.


  ggiCrossBlit will transfer an area from the source visual's read frame
  to the destination visual's write frame.

  This function does not perform stretching.


  4.12.  Origin

  4.12.1.  int ggiSetOrigin(ggi_visual_t vis, int x, int y);


  Set the top-left corner of the displayed area to x/y.

  Return: 0 for OK, otherwise an error code.

  When using a larger virtual area, you can pan the visible area over
  the virtual one to do scrolling. Some targets have extemely efficient
  means to do this (i.e. they do it in hardware).

  Thus this is commonly used for double-buffering by requesting a
  double- height virtual screen (i.e. virtual size is double of the
  visible size), and then drawing on the upper/lower half alternatingly
  and displaying the currently "steady" buffer (the one which is not
  drawn to) using ggiSetOrigin().  (Though there is an easier way to do
  this.)

  Example: Pan from the top to the bottom of the virtual screen


       ______________________________________________________________________
       for(i = 0; i<virt_y-visible_y; i++) {
               ggiSetOrigin(vis, 0, i);
       }
       ______________________________________________________________________




  Note that this call takes dot coordinates, not pixel coordinates as
  the drawing primitives do. This makes a difference in text mode.


  4.12.2.  int ggiGetOrigin(ggi_visual_t vis, int *x, int *y);


  Get the current top-left corner of the displayed area into x/y.

  Note that due to rounding to the hardware's capabilities, the values
  retrieved by a subsequent ggiGetOrigin() may not necessarily match
  those passed to ggiSetOrigin() previously.

  Return: 0 if OK, otherwise an error code.


  4.13.  Input and Event handling


  In addition to graphics operations, LibGGI provides several event
  handling functions, and, as a convenience, basic keyboard support.

  The keyboard functions are based on ggiEventPoll() and ggiEventRead().
  If you need more complex things, use the event interface directly.




  4.13.1.  int ggiKbhit(ggi_visual_t vis);


  Checks if a key has been hit on the keyboard. This does not consume
  the key. It is basically for easy porting of old DOS applications.

  Return: 0 if no key has been received yet, otherwise there is a key to
  be consumed.

  DO NOT poll like this: do while( ! ggiKbhit(vis) );. On a multitasking
  OS you would be wasting ressources which could be available to other
  processes.  If you want to wait for a key, use the ggiGetc() call.


  4.13.2.  int ggiGetc(ggi_visual_t vis);


  Gets a character from the keyboard. Blocks if no key is available.

  Return: a Unicode character (either UCS-2 (16-bit) or UCS-4 (32-bit))

  For a fuller definition of characters, please look at ggi/keyboard.h.
  It is based on Linux keysyms and Unicode.


  4.13.3.  Events

  Events are of type ggi_event:


       ______________________________________________________________________
       typedef union ggi_event {

               uint8           size;           /* size of this event   */

               ggi_any_event   any;            /* access COMMON_DATA   */
               ggi_cmd_event   cmd;            /* command/broadcast    */
               ggi_raw_event   raw;            /* raw data event       */
               ggi_val_event   val;            /* valuator change      */
               ggi_key_event   key;            /* key press/release    */
               ggi_pmove_event pmove;          /* pointer move         */
               ggi_pbutton_event pbutton;      /* pointer buttons      */

       } ggi_event;
       ______________________________________________________________________




  The first element, size, is the size of the given event (in bytes).
  Then the COMMON_DATA follows:



       ______________________________________________________________________
               uint8   size;           /* size of event in bytes       */
               uint8   type;           /* type of this event           */
               uint8   focus;          /* focus this is reported from  */
               uint8   device;         /* who sent this                */
               uint32  time;           /* timestamp                    */
       ______________________________________________________________________





  Type is the type of event, which may be the following:



       ______________________________________________________________________
       typedef enum ggi_event_type {

               evNothing = 0,  /* event is not valid. (must be zero)   */
               evCommand,      /* report command/do action             */
               evBroadcast,    /* notification of general interest     */
               evDeviceInfo,   /* report input device information      */

               evRawData,      /* raw data received from device        */

               evKeyPress,     /* key has been pressed                 */
               evKeyRelease,   /* key has been released                */
               evKeyRepeat,    /* automatically repeated keypress      */
               evKeyState,     /* resynchronize keys state             */

               evPtrRelative,  /* pointer movements reported relative  */
               evPtrAbsolute,  /* pointer movements reported absolute  */
               evPtrButtonPress,       /* pointer button pressed       */
               evPtrButtonRelease,     /* pointer button released      */
               evPtrState,     /* resynchronize pointer state          */

               evValRelative,  /* valuator change (reported relative)  */
               evValAbsolute,  /* valuator change (reported absolute)  */
               evValState,     /* resynchronize valuator state         */

               evLast          /* must be less than 33                 */

       }  ggi_event_type;
       ______________________________________________________________________




  Use the appropriate member from the ggi_event union to access the
  event data, depending on the given type. See ggi/event.h and
  ggi/keyboard.h for more details. For example:



       ______________________________________________________________________
               ggi_event ev;

               /* ... get the event... */

               switch(ev.any.type) {
                       case evKeyPress:
                       case evKeyRepeat:
                               printf("Received key symbol: %x\n", ev.key.sym);
                               break;
                       case evKeyRelease:
                               /* ... ignore ... */ break;
                       case evPtrRelative:
                       case evPtrAbsolute:
                               printf("Moved the mouse! x: %d, y: %d\n",
                                       ev.pmove.x, ev.pmove.y);

                       /* ... etc ... */
       ______________________________________________________________________




  There is also ggi_event_mask which may be passed to various event
  handling functions to indicate which types of events the program is
  interested in. See ggi/ggi.h for possible masks.


  4.13.4.  ggi_event_mask ggiEventPoll(ggi_visual_t vis, ggi_event_mask
  *mask, struct timeval t)


  Check if any of the events given in EvMask is available. Using the
  struct timeval *t, you can control the timeout, like select(2). Give
  NULL to wait indefinitely or a filled out struct to wait for a given
  time (which may be 0 to get non-blocking behaviour).

  Return: a mask of events which are available (within the limits set by
  the mask parameter).


  4.13.5.  mask) int ggiEventRead(ggi_visual_t vis, ggi_event *ev,
  ggi_event_mask


  Read an Event from the queue. This call blocks, if there is no such
  event present.  Any queued events not in the mask remain unaffected,
  and can be retrieved later on when needed.

  Return: the size of the event.


  4.13.6.  int ggiSetEventMask(ggi_visual_t vis, ggi_event_mask mask)


  Set the global event mask.  Only the events in this mask get queued
  for later retrieval using ggiEventRead.  Events not in this mask are
  always discarded.  Note that changing this mask causes all queued
  events not in the new mask to be flushed, which may be just what you
  want.

  Return: 0 for OK, otherwise an error code.


  4.13.7.  ggi_event_mask ggiGetEventMask(ggi_visual_t vis)


  Return: the global event mask.


  4.13.8.  int ggiAddEventMask(ggi_visual_t vis, ggi_event_mask evm)

  4.13.9.  int ggiRemoveEventMask(ggi_visual_t vis, ggi_event_mask evm)


  Macros to add or remove a specific event mask.


  4.14.  DirectBuffer


  Dependent on the visual target and runtime environment found,
  applications may be granted direct access to hardware and/or library
  internal buffers. This may significantly enhance performance for
  certain pixel oriented applications or libraries.

  The DirectBuffer is a mechanism in which a LibGGI program can use to
  determine all the characteristics of these buffers (typically the
  framebuffer), including the method of addressing, the stride,
  alignment requirements, and endianness.

  However, use not conforming to this specification will have undefined
  effects and may cause data loss or corruption, program malfunction or
  abnormal program termination. So you don't really want to do this.


  4.14.1.  Types of Buffers

  4.14.1.1.  Framebuffer



  A frame buffer may be organized as several distinct buffers.  Each
  buffer may have a different layout. This means both the addressing
  scheme to be used as well as the addressing parameters may differ from
  buffer to buffer.

  LibGGI currently has support for pixel-linear buffers, bit-planar
  buffers, and interleaved planar buffers.


  4.14.1.2.  Pixel Linear Buffer


  A linear buffer is a region in the application's virtual memory
  address space. A pixel with the pixel coordinates (<x>,<y>) is
  assigned a pixel number according to the following formula: <pixel
  number> = (<origin_y> + <y>)*<stride> + <origin_x> + <x> In any case
  both <x> and <y> must not be negative, <x> must be less than <size_x>
  and <y> must be less than <size_y>.  For top-left-origin screen
  coordinates, <stride> and <origin_y> will both be positive. For
  bottom-left-origin screen coordinates, <stride> and <origin_y> will
  both be negative.  This will result in the correct pixel number with
  the same formula in both cases. The pixel number will be used to
  address the pixel.

  A certain number <bpp> of bits is stored per pixel. Bit <n> of the
  pixel value for pixel number <i> is stored in bit number <i>*<bpp> +
  <n> of the buffer. Bit <n> of byte <i> in the buffer corresponds to
  bit <i>*8 + <n> of the buffer for host CPU native bit and byte
  ordering. For some targets, the buffer might not be in host CPU native
  format and swapping operations need to be performed before writes or
  after reads.


  4.14.2.  Accessing the Buffer


  Read and write access to the buffer is done using load and store
  instructions of the host CPU.

  The access width and alignment requirements are assumed to be the same
  as the host CPU.

  Read operations should be performed using the <read> buffer and write
  operations should be performed using the <write> buffer. These might
  be the same, but need not. If they are, read/write may be done to
  either buffer. Please note, that either read or write may be NULL.
  These are write-only or read-only buffers, which might be caused by
  hardware limitations. Such buffers are not suited to do Read-Modify-
  Write operations, so take care.




  4.14.2.1.  Swapping Requirements

  If the buffer is not stored with native bit and byte ordering,
  swapping operations have to be performed before writes and after
  reads.  For pixel-linear buffers, this is indicated in the flags
  member of ggi_pixelformat.  For example, if flags &
  GGI_PF_REVERSE_ENDIAN, then the pixel values must be byte swapped or
  reversed.



  4.14.2.2.  Paged Buffers

  Paged buffers are indicated with page_size != 0 in ggi_directbuffer.

  Successive access to addresses <addr> and <addr2> of either read or
  write buffers with <addr0>  <page_size>  !=  <addr1> / <page_size>/
  may be very expensive compared to successive accesses with <addr0>
  <page_size>  ==  <addr1> / <page_size>/.  On i386 the penalty will be
  about 1500 cycles plus 4 cycles per to be remapped. Because of this,
  block transfer operations might become very inefficient for paged
  buffers. If there are two different buffers provided for read and
  write operations, you should do successive reads from one and do
  successive writes to the other. If not, it is recommended to copy
  pagewise into a temporary buffer and then to copy this temporary
  buffer back to screen.



  4.14.3.  API Structures




































  ______________________________________________________________________

  typedef enum {
          blPixelLinearBuffer,
          blExtended,

          blLastBufferLayout
  } ggi_bufferlayout;

  typedef struct {
          int             stride;         /* bytes per row                */
          ggi_pixelformat *pixelformat;   /* format of the pixels         */
  } ggi_pixellinearbuffer;

  /* Buffer types */
  #define GGI_DB_NORMAL           0x01
  #define GGI_DB_EXTENDED         0x02
  #define GGI_DB_MULTI_LEFT       0x04
  #define GGI_DB_MULTI_RIGHT      0x08

  /* Flags that may be or'ed with the buffer type */
  #define GGI_DB_SIMPLE_PLB       0x80000000
  /* GGI_DB_SIMPLE_PLB means that the buffer has the following properties:
        type=GGI_DB_NORMAL
        read=write
        layout=blPixelLinearBuffer
  */

  typedef struct {
          int             frame;          /* framenumber */
          uint32          type;           /* buffer type */

          /*      access info     */
          void            *read;          /* buffer address for reads     */
          void            *write;         /* buffer address for writes    */
          unsigned int    page_size;      /* zero for true linear buffers */

          ggi_bufferlayout        layout;

          /* The actual buffer info. Depends on layout. */
          union {
                  ggi_pixellinearbuffer plb;
                  void *extended;
          } buffer;
  } ggi_directbuffer;
  ______________________________________________________________________





     frame
        is the frame number as used in multiple buffering.

     layout
        is an enumeration specifying whether the buffer is pixel-linear,
        planar, etc.

     buffer
        is a union of all buffer info.  Check the layout member to see
        which member of use.

  Please see the ggi_pixelformat section for information
  ggi_pixelformat, which is the format of the pixels for pixel-linear
  buffers.

  4.14.4.  API Functions

  4.14.4.1.  int ggiDBGetNumBuffers(ggi_visual_t vis);

  Return the number of DirectBuffers available to the application.


  4.14.4.2.  const ggi_directbuffer *ggiDBGetBuffer(ggi_visual_t vis,
  int bufnum);

  Return DirectBuffer with number bufnum.  The buffers at position 0 to
  ggi_mode.frames-1 represent the DirectBuffers for each frame in the
  visual, if they are available.


  Pixel-linear buffers have type==GGI_DB_SIMPLE_PLB | GGI_DB_NORMAL.
  You're on your own now.




  4.14.4.3.  Example: How To Obtain a DirectBuffer












































  ______________________________________________________________________

  ggi_visual_t    vis;
  ggi_mode        mode;
  int             i;

  /* Pointers to framebuffer */
  unsigned char *readptr[2], *writeptr[2];
  int stride[2];

  mode.frames = 2;        /* Double-buffering */
  mode.visible.x = 640;   /* Screen res */
  mode.visible.y = 480;
  mode.virt.x = GGI_AUTO; /* Any virtual resolution.  Will usually be set
  mode.virt.y = GGI_AUTO;    to be the same as visible but some targets may
                             have restrictions on virtual size. */
  mode.graphtype = GT_8BIT;               /* Depend on 8-bit palette. */
  mode.dpp.x = mode.dpp.y = GGI_AUTO;     /* Always 1x1 but we don't care. */

  if(ggiInit())
  {
          /* Failed to initialize library. Bomb out. */
  }

  vis = ggiOpen(NULL);
  if(!vis)
  {
          /* Opening default visual failed, quit. */
  }

  if(ggiSetMode(vis, &mode))
  {
          /* Set mode has failed, should check if suggested mode
             is o.k. for us, and try the call again. */
  }

  /* We got the mode we wanted.
     Now get framebuffers for frame #0 and frame #1. */

  for(i = 0; i<mode.frames; i++)
  {
          ggi_directbuffer *db;

          db = ggiDBGetBuffer(vis, i);

          if(!db)
          {
                  /* Failed to get buffer... */
                  break;
          }

          if(!(db->type & GGI_DB_SIMPLE_PLB))
          {
                  /* We don't handle anything but simple pixel-linear buffers.
                     Fall back to ggiPutBox() or something. */
                  break;
          }

          readptr[i] = db->read;
          writeptr[i] = db->write;

          /* Stride of framebuffer (in bytes). */
          stride[i] = db->buffer.plb.stride;

          /* Check pixel format, be portable.... */
  ______________________________________________________________________
  4.15.  Miscellaneous Functions



  4.15.1.  Synchronous and asynchronous drawing modes

  Some targets allow different modes with regard to when the screen is
  updated and the actual drawing takes place.

  The synchronous mode is default because it is what most programmers
  expect: When the drawing command returns, it is already or will be
  executed very shortly. So the visible effect is that everything is
  drawn immediately.  (It is not guaranteed in the strict sense that it
  is already drawn when the function call returns, but almost.)

  The asynchronous mode is (at least on the X) faster, but does not
  guarantee that the command is executed immediately. To make sure that
  all pending graphics operations are actually done and the screen is
  updated, you need to call ggiFlush(myvis);.

  (Side note: The screen refresh the X target does every 1/20 s can take
  about half the execution time of a program. So syncronous mode can
  really slow things down.)

  As it stands now, all operations are guaranteed to be performed in the
  order given in both modes.  Reordering has been discussed but is
  currently not done.

  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. (If asynchronous mode is not supported by a
  target, setting it is still allowed, but has no effect.)

  How to set up asynchronous mode?


  o  ggiAddFlags(myvis,GGIFLAG_ASYNC); switches to asynchronous mode,

  o  ggiFlush(myvis); updates the screen,

  o  ggiRemoveFlags(myvis,GGIFLAG_ASYNC); switches to synchronous mode.


  4.15.2.  int ggiFlush(ggi_visual_t visual);


  Flush all pending output.  Not needed in synchrounous mode.


  4.15.3.  int ggiSetFlags(ggi_visual_t vis, ggi_flags flags);


  Set flags on visual, e.g. asynchronous mode.


  4.15.4.  int ggiGetFlags(ggi_visual_t vis, ggi_flags flags);


  Get flags currently in effect.


  4.15.5.  int ggiAddFlags(ggi_visual_t vis, ggi_flags flags);




  4.15.6.  int ggiRemoveFlags(ggi_visual_t vis, ggi_flags flags);


  Macros to add or remove individual flags. (Currently only
  GGIFLAG_ASYNC.)


  4.15.7.  int ggiGetSelectFD(ggi_visual_t vis);


  Obtain a file descriptor for the specified visual.  This file
  descriptor then can be passed as part of a set to select(2) -- when
  there is input available, it becomes readable.  This is useful in user
  interfaces where you need to wait for multiple inputs at once.

  Return: file descriptor, or -1 if it is not available.

  Use ggiEventPoll() and ggiEventRead() once you get an event.


  5.  LibGGI usage guidelines

  5.1.  Hints on memory visuals

  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.


  5.2.  LibGGI and threads

  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.


  5.3.  Mixing LibGGI and direct frame buffer access

  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.)


  5.4.  Inactivated applications, Redraw requests

  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 ... */
       ______________________________________________________________________








  5.5.  Environment variables


  5.5.1.  GGI_DEBUG

  If this is set to 255 (anything > 0 currently works), debugging output
  is printed to stderr.

  5.5.2.  GGI_DEFMODE

  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.


  5.5.3.  GGI_DISPLAY

  This variable is used to determine the default display target.
  Currently allowed values include:


     display-x
        force usage of X target

     display-xlib
        force usage of Xlib target

     display-aa
        force usage of aalib target

     display-memory
        force usage of memory target

     display-svga
        force usage of SVGAlib target

     display-dga
        force usage of XF86 DGA target

     display-glide
        force usage of Glide target

     display-terminfo
        force usage of terminfo target (text apps only)

     display-trueemu
        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"

     display-multi
        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.





  6.  LibGGI initialization example


  A primitive tutorial on how to start using LibGGI, since many people
  seem to have trouble with this. For more practical usage, please see
  demo.c.




























































  ______________________________________________________________________
  #include <ggi/ggi.h>

  int main(void)
  {
          ggi_visual_t vis;
          ggi_mode mode;
          int err;

          /* first initialize LibGGI */
          if(ggiInit()) {
                  fprintf("Cannot init libggi.\n");
                  exit(EXIT_FAILURE);
          }

          /* Get the default visual to work on */
          vis = ggiOpen(NULL);

          /* You can also do some drawing to memory, like this:
             (don't forget the ending NULL!)

          vis = ggiOpen("display-memory", NULL);
          */

          if(vis==NULL) {
                  ggiPanic("Cannot open visual!\n");
          }

  #ifdef AUTO_SELECT_MODE
          /* This automatically selects the default mode */
          err = ggiSetGraphMode(vis,
                  GGI_AUTO, GGI_AUTO,     /* Visible resolution */
                  800, 600,               /* Virtual: perhaps you'd like a large area to scroll around in */
                  GGI_AUTO);              /* graphtype auto */

  #else
          /* OR you can select your own */

          /* Check for mode: 320x200x8 320x200.
             After this call, mode will now have our mode,
             OR the suggested mode if our mode cannot be satisfied.
          */
          ggiCheckGraphMode(vis, 320, 200, 320, 200, GT_8BIT,
                  &mode, NULL);

          /* Now set the mode */
          err = ggiSetMode(vis, &mode);
  #endif

          if(err) {
                  ggiPanic("Cannot set requested mode!\n");
          }

          /* do some stuff */

          ggiClose(vis);

          ggiExit();

          return 0;
  }
  ______________________________________________________________________




  7.  API change log

  7.1.  Pending changes


  7.2.  Changes for 1.5


  o  The key definitions have changed:

  o  K_F10 is now GGI_KEY_F10

  o  KT_SPEC is now GGI_KT_SPEC

  o  KG_SHIFT is now GGI_KM_SHIFT

  o  KTYP and KVAL are now GGI_KTYP and GGI_KVAL

  o  KT_LATIN & KT_LETTER were replaced with GGI_KT_LATIN1

  o  Syms are not Linux-kludged (xor 0xf000) anymore (was not clearly
     defined before)


  o  ggi/libggi.h has been changed to ggi/ggi.h

  o  ggiSetInfoFlags became ggiSetFlags

  o  ggiSetPaletteVec and ggiGetPaletteVec became ggiSetPalette and
     ggiGetPalette

  o  ggiDrawCircle has been moved to LibGGI2D.

  o  ggiWaitRayPos, ggiGetRayPos and ggiSetSplitline have been moved to
     libGGImisc.

  o  Changes in the definition of ggiInit() and ggiExit allow nesting
     them.

  o  ggiPuts behaviour has been defined more clearly.

  o  The stretching version of ggiCrossBlit has been moved to libggi2d
     (as ggiStretchBlit), in favour of a ggiCrossBlit which does not do
     stretching.

  o  An alpha value has been added to ggi_color (but not used by
     libggi).

  o  The graphtype GT_AUTO has been introduced.

  o  Graphtypes are defined precisely in a non-VGA-centric way.

  o  Support for multiple frames (doublebuffering) has been defined.

  o  More get/put buffer properties have been defined.

  o  The "display-" Target prefix can now be omitted.


  7.3.  1.3.0 to 1.4.0


  o  ggiMapColor takes now a pointer to a ggi_color struct as it's
     second argument instead of the struct itself.  This breaks binary
     compatibility for about every program!

  o  ggi*Sprite functions, that had never been implemented, are removed.

  o  The ggi_mode struct members virt and visible now do contain the
     number of pixels, not dots (which makes a difference for text mode.
     One character is one pixel but e.g. 9x16 dots). It is unclear what
     it had to contain before. So it might be a change, it might be a
     bugfix.

     According to Brian Julin, the semantics is:


       ______________________________________________________________________
                                       Before            After
        mode->request.visible.x       dots              pixels
        mode->request.visible.y       dots              pixels
        mode->request.virt.x          dots              pixels
        mode->request.virt.y          dots              pixels
        mode->request.text.x          dots              -- doesn't exist --
        mode->request.text.y          dots              -- doesn't exist --
        mode->request.dpp.x     -- didn't exist --      dots (==1 in graph modes)
        mode->request.dpp.y     -- didn't exist --      dots (==1 in graph modes)
       ______________________________________________________________________












































