LibGGI types and structures =========================== LibGGI mode description ~~~~~~~~~~~~~~~~~~~~~~~ .. manpage:: 3 ggi_mode ggi_coord ggi_graphtype Synopsis -------- :: #include <ggi/ggi.h> typedef struct { int16_t x, y; } ggi_coord; typedef uint32_t ggi_graphtype; typedef struct { int32_t frames; ggi_coord visible; ggi_coord virt; ggi_coord size; ggi_graphtype graphtype; ggi_coord dpp; } ggi_mode; Description ----------- The mode structure describes a visual configuration given by its size and other graphic properties. Structure Members ----------------- `frames` The number of frames. Some displays have multi-buffer capabilities (double-buffering, triple-buffering,...). See libggi frame-related functions (ggi{s,g}et{Read,Write,Display}Frame) for information on working with multiple frames. `visible` The size of the visible area in pixels. This is what the user will see. `virt` The virtual size of the visual in pixels. It can be larger (but not smaller) than the visible area, in which case only a part of it is displayed. It is useful for scrolling or backing up portions of screen efficiently. See `ggi[Set|Get]Origin` functions for more. `size` The size of the visible area in mm. `graphtype` It holds information on the type of display. libggi defines macros to construct graphtypes values or access individual field. `depth` ( access via `GT_DEPTH(gt)`, `GT_SETDEPTH(gt,x)` ) The number of significant bits holding color information. `size` ( access via `GT_SIZE(gt)`, `GT_SETSIZE(gt,x)` ) The actual size (in bits) of a pixel. For instance, on a 32 bits X server the pixel size is 32 but the depth is only 24 (8bits RGB channels, 8 unused). `scheme` ( access via `GT_SCHEME(gt)`, `GT_SETSCHEME(gt,x)` ) The following schemes are available : - `GT_TEXT` : text mode only - `GT_TRUECOLOR` : true color mode - `GT_GREYSCALE` : pixels represent level of gray - `GT_PALETTE` : pixels are entries in a CLUT (Color Look-Up Table) - `GT_STATIC_PALETTE` - `GT_SUBSAMPLE_YUV` - `GT_SUBSAMPLE_U_YCRBR` - `GT_SUBSAMPLE_S_YCRBR` - `GT_NIL` `subscheme` ( access via `GT_SUBSCHEME(gt)`, `GT_SETSUBSCHEME(gt,x)` ) One of: - `GT_SUB_REVERSE_ENDIAN` - `GT_SUB_HIGHBIT_RIGHT` - `GT_SUB_PACKED_GETPUT` Graphtypes can be constructed directly or via the `GT_CONSTRUCT(depth,scheme,size)` macro. The following common graphtypes are defined : - `GT_TEXT16` - `GT_TEXT32` - `GT_1BIT` - `GT_2BIT` - `GT_4BIT` - `GT_8BIT` - `GT_15BIT` - `GT_16BIT` - `GT_24BIT` - `GT_32BIT` - `GT_AUTO` - `GT_INVALID` `dpp` It stands for dot-per-pixel. When filling a mode structure for setting a visual, any field can be assigned `GGI_AUTO` (`GT_AUTO` for graphtype) if a specific value isn't required. See Also -------- :man:`ggiCheckMode(3)`, :man:`ggiSetMode(3)` LibGGI color description ~~~~~~~~~~~~~~~~~~~~~~~~ .. manpage:: 3 ggi_color ggi_pixel Synopsis -------- :: #include <ggi/ggi.h> typedef struct { uint16_t r,g,b,a; } ggi_color; typedef uint32_t ggi_pixel; Description ----------- Colors in ggi are described generically through the display-independent `ggi_color` structure. 16 bit channels are used to ensure sufficient precision on most displays. `ggi_pixel`\ s are display-dependent pixel values. They are used by all GGI drawing primitives for efficiency. Use :man:`ggiMapColor(3)` to convert ggi_colors to ggi_pixels. Structure members ----------------- `r`, `g` and `b` correspond to the red, green and blue channels. Since libggi does not deal with alpha compositing, the `a` (alpha) field is mainly there for padding and it is not used by libggi. Setting this value has no effect in libggi itself, and it will most probably not be unmapped correctly from `ggi_pixel`\ s. However, some extensions might make use of it, in which case you should refer to their documentation. `ggi_pixel`\ s format depends on the actual display and mode. For those who want to operate directly on pixel values, this format is described in the `ggi_pixelformat` structure. Pixel Arrays ------------ Although individual pixels are kept into 32 bits `ggi_pixel`, arrays of pixels, as used in `ggi[Get|Put]*` functions, `ggiPackColors` and `ggiUnpackPixels`, are stored in the display specific format, thus packed according to the actual pixel size. This size is given by the `GT_SIZE` macro for `graphtype` or the `size` field of the `ggi_pixelformat` structure. The buffers provided to these functions must be big enough to store or read enough pixels. Although it is safe to use 32 bits per pixel, the optimum size (in bits) can be calculated by multiplying the number of pixel by their size. Don't forget to round up to a multiple of 8 to get the number of bytes. If you want to access such buffers directly, do *not* use pointer arithmetics with `ggi_pixel`\ s. See Also -------- :man:`ggiMapColor(3)`, :man:`ggi_mode(3)`, :man:`ggi_pixelformat(3)` LibGGI pixel format description ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. manpage:: 3 ggi_pixelformat Synopsis -------- :: #include <ggi/ggi.h> typedef struct { int depth; /* Number of significant bits */ int size; /* Physical size in bits */ /* * Simple and common things first : * * Usage of the mask/shift pairs: * If new_value is the _sizeof(ggi_pixel)*8bit_ value of the thing * you want to set, you do * * *pointer &= ~???_mask; // Mask out old bits * *pointer |= (new_value>>shift) & ???_mask; * * The reason to use 32 bit and "downshifting" is alignment * and extensibility. You can easily adjust to other datasizes * with a simple addition ... */ /* Simple colors: */ ggi_pixel red_mask; /* Bitmask of red bits */ int red_shift; /* Shift for red bits */ ggi_pixel green_mask; /* Bitmask of green bits */ int green_shift; /* Shift for green bits */ ggi_pixel blue_mask; /* Bitmask of blue bits */ int blue_shift; /* Shift for blue bits */ /* A few common attributes : */ ggi_pixel alpha_mask; /* Bitmask of alphachannel bits */ int alpha_shift; /* Shift for alpha bits */ ggi_pixel clut_mask; /* Bitmask of bits for the clut */ int clut_shift; /* Shift for bits for the clut*/ ggi_pixel fg_mask; /* Bitmask of foreground color */ int fg_shift; /* Shift for foreground color */ ggi_pixel bg_mask; /* Bitmask of background color */ int bg_shift; /* Shift for background color */ ggi_pixel texture_mask; /* Bitmask of the texture (for textmodes - the actual character) */ int texture_shift; /* Shift for texture */ /* * Now if this doesn't suffice you might want to parse the following * to find out what each bit does: */ uint32_t bitmeaning[sizeof(ggi_pixel)*8]; uint32_t flags; /* Pixelformat flags */ uint32_t stdformat; /* Standard format identifier */ /* This one has only one use for the usermode application: * To quickly check, if two buffers are identical. If both * stdformats are the same and _NOT_ 0 (which means "WEIRD"), * you may use things like memcpy between them which will have * the desired effect ... */ } 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 Description ----------- This structure describes the internal format of pixel values for a visual. See Also -------- :man:`ggiGetPixelFormat(3)` LibGGI direct buffer structure description ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. manpage:: 3 ggi_directbuffer ggi_pixellinearbuffer ggi_pixelplanarbuffer ggi_samplelinearbuffer ggi_sampleplanarbuffer Synopsis -------- :: #include <ggi/ggi.h> typedef struct { uint32_t type; int frame; ggi_resource_t resource; void *read; void *write; unsigned int page_size; uint32_t noaccess; uint32_t align; ggi_bufferlayout layout; union { ggi_pixellinearbuffer plb; ggi_pixelplanarbuffer plan; ggi_samplelinearbuffer slb; ggi_sampleplanarbuffer splan; void *extended; } buffer; } ggi_directbuffer; Description ----------- The `ggi_directbuffer` structure contains information on target-dependent buffers to allow applications to access them directly. Structure Members ----------------- :p:`type` :: /* Buffer types */ #define GGI_DB_NORMAL 0x0001 /* "frame" is valid when set */ #define GGI_DB_EXTENDED 0x0002 #define GGI_DB_MULTI_LEFT 0x0004 #define GGI_DB_MULTI_RIGHT 0x0008 /* Flags that may be or'ed with the buffer type */ #define GGI_DB_SIMPLE_PLB 0x01000000 /* GGI_DB_SIMPLE_PLB means that the buffer has the following properties: type == GGI_DB_NORMAL read == write noaccess == 0 align == 0 layout == blPixelLinearBuffer */ :p:`frame` is the frame number as used in multiple buffering. Note that each frame can export more than one DirectBuffer. :p:`resource` is a pointer to a lowlevel resource. Certain DirectBuffers need to be explicitly acquired (i.e. locked) before using them (i.e. accessing their pointers). Such a situation may arise if the underlying visual supports mixed acceleration and framebuffer access, but they cannot occur at the same time. In that case, LibGGI needs to be informed when the application is using the framebuffer. You can determine whether the DirectBuffer needs to be acquired by using `ggiResourceMustAcquire`. An acquire is done by using `ggiResourceAcquire` and it is released by calling `ggiResourceRelease`. :p:`read`, :p:`write` are the addresses where the buffer is mapped to the application. Read and write access to the buffer is done using load and store instructions of the host CPU. Read operations should be performed using the :p:`read` buffer and write operations should be performed using the :p:`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. Be aware that these fields may be changed by an acquire, and that they may be `NULL` or invalid when the DirectBuffer is not acquired. :p:`page_size` indicates a Paged buffer if not `0`. Successive access to addresses `addr0` and `addr1` 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. :p:`noaccess` is a bitfield specifying an access restriction. When bit x is set, you may not access this DirectBuffer at the width of 2^x bytes. It is usually 0, but check it. :p:`align` is a bitfield specifying another access restriction. When bit x is set, you may only access this DirectBuffer at the width of 2^x bytes, when the access is aligned to a multiple of 2^x. Note that bit 0 is a bit bogus here, but it should be always 0, as then ((noaccess|align)==0) is a quick check for "no restrictions". :p:`layout` is an enumeration specifying the buffer addressing scheme. Possible values are `blPixelLinearBuffer`, `blPixelPlanarBuffer`, `blExtended`, `blSampleLinearBuffer` and `blSamplePlanarBuffer`. See below for their definition. :p:`buffer` is a union of all buffer info. Check the `layout` member to see which member of use. Pixel Linear Buffer ------------------- :: typedef struct { int stride; /* bytes per row */ ggi_pixelformat *pixelformat; /* format of the pixels */ } ggi_pixellinearbuffer; A linear buffer is a region in the application's virtual memory address space. A pixel with the pixel coordinates (:p:`x`, :p:`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, and less than the buffer's width and height respectively. 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 of bits is stored per pixel, and this is indicated in the `ggi_pixelformat.access` field. For some visuals, the buffer might not be in host CPU native format and swapping operations need to be performed before writes or after reads. Pixel Planar Buffer ------------------- :: typedef struct { int next_line; /* bytes until next line */ int next_plane; /* bytes until next plane */ ggi_pixelformat *pixelformat; /* format of the pixels */ } ggi_pixelplanarbuffer; Sample Linear Buffer -------------------- :: typedef struct { int num_pixels; /* how many pixelformats */ int stride; /* bytes per row */ ggi_pixelformat *pixelformat[4];/* format of the pixels */ } ggi_samplelinearbuffer; Sample Planar Buffer -------------------- :: typedef struct { int next_line[3]; /* bytes until next line */ int next_plane[3]; /* bytes until next plane */ ggi_pixelformat *pixelformat[4];/* format of the pixels */ } ggi_sampleplanarbuffer; Extended Buffer --------------- TODO : write something here. See Also -------- :man:`ggi_pixelformat(3)`, :man:`ggiDBGetBuffer(3)`, :man:`ggiResourceAcquire(3)` LIBGGI colormap ~~~~~~~~~~~~~~~ .. manpage:: 3 ggi_colormap ggi_colormap_region Synopsis -------- :: #include <ggi/ggi.h> /* a color consists of red, green, blue and alpha component */ typedef struct { uint16_t r,g,b,a; } ggi_color; /* color look up table */ typedef struct { uint16_t size; ggi_color *data; } ggi_clut; enum ggi_colormap_region { GGI_COLORMAP_RW_REGION = 0, GGI_COLORMAP_RO_REGION = 1, GGI_COLORMAP_RW_RO_REGION = 2 }; typedef int (ggifunc_setPalette)(ggi_visual_t vis, size_t start, size_t size, const ggi_color *cmap); typedef struct ggi_colormap { ggi_clut clut; size_t rw_start; size_t rw_stop; size_t ro_start; size_t ro_stop; void *priv; size_t (*getPrivSize)(ggi_visual_t vis); int (*setRW)(ggi_visual_t vis, size_t start, size_t end); int (*setRO)(ggi_visual_t vis, size_t start, size_t end); int (*getRW)(ggi_visual_t vis, size_t *start, size_t *end); int (*getRO)(ggi_visual_t vis, size_t *start, size_t *end); ggifunc_setPalette* setPalette; ssize_t (*findByColor)(ggi_visual_t vis, const ggi_color *color, enum ggi_colormap_region region); ssize_t (*findByIdx)(ggi_visual_t vis, size_t idx, enum ggi_colormap_region region); int (*matchByColor)(ggi_visual_t vis, const ggi_color *color1, const ggi_color *color2, enum ggi_colormap_region region); int (*matchByIdx)(ggi_visual_t vis, size_t idx1, size_t idx2, enum ggi_colormap_region region); } ggi_colormap; /* This is a very usefull marco to directly access visual palette entry */ #define LIBGGI_PAL(vis) ((vis)->palette) Description ----------- ggi_colormap structure can be considered as an interface between target colormap and ggi internal colormap. Target specific information is stored in the priv member. The ggi colormap is represented by the clut member. It can be viewed as an abstract colormap whereas the priv member can be view as the 'real' one. These members are initialised during ggi initialisation. Colormaps (both target dependent and independent ones) are updated/initialised with the ggiSetPalette function. The target is also responsible for setting the RO/RW area indices. RW entries can be modified by any application whereas RO entries can't be modified. In a target like X (or any other windowed one) where the colormap is shared between all the applicataion, RO entries are the shared color cells. These colormap entries are shared by all applications so any changes will affect them. For example if you display a 256 colors image without taking these entries into account, the colors of the window manager and all the other windows are screwed. The RW entries are the private color cells (ie) application specific entries. The reason why the RO/RW management is not a native ggi feature is simple if we consider this almost wrong analogy. GGI can be seen as a graphical hardware and the target as its driver. The hardware only give us access to 'raw' data. The way we represent/use it is up to the target developer. Every colormap function respect the standard ggi return policy which is: - 0 on normal completion - >0 when giving additional hints or returning nonnegative integer data - <0 for errors, see :man:`ggi-error(3)` Structure Members ----------------- `clut` The ggi side colormap. `rw_start`, `rw_stop` Read/Write region boundaries. Any color in this region can be modified. `ro_start`, `ro_end` Read only region boundaries. Colors in this region can't and must not be modified. `priv` Target specific informations. This could be the target colormap structure. `getPrivSize` Return the size in bytes of the priv member. `setRW`, `setRO` Initialize the RW RO region of the colormap. These functions perform target specific operations and initialize region boundaries members of the colormap structure. `getRW`, `getRO` Get RW RO region information from target. `setPalette` One of the more important function. It initializes the colormap (both internal and target ones). `findByColor`, `findByIdx` Find the index of the color passed as argument. `matchByColor` Match the CLUT entry with the lowest index when more than one CLUT entry exists with the same color in it. `matchByIdx` Similar to matchByColor. The correct pixel value of the color in the CLUT slot N is not necessarily N. Examples -------- display/my_target/mode.c:: int GGI_my_target_setmode(ggi_visual *vis,ggi_mode *tm) { /* Target structure */ ggi_my_target_priv *priv; priv=LIBGGI_PRIVATE(vis); /* [...] */ /* Let's considerer a basic vga target with two different mode, a truecolor and a 8bpp(vga like) mode. First you'll have to initialize the ggi_colormap structure during video mode initialization. */ if(priv->mode == MY_TARGET_8BPPINDEXED) { /* Well we know that the colormap can only contain 256 colors. But that's some kind of paranoid size computation :) */ LIBGGI_PAL(vis)->clut.size = 1 << priv->bits_per_pixel; /* Let's allocate the the clut data */ LIBGGI_PAL(vis)->clut.data = _ggi_malloc(LIBGGI_PAL(vis)->clut.size * sizeof(ggi_color)); /* Set up function pointers */ LIBGGI_PAL(vis)->getPrivSize = GGI_my_target_getPrivSize; LIBGGI_PAL(vis)->setPalette = GGI_my_target_setPalette; /* If you need it initialize ggi_colormap priv member to hold target colormaps informations. my_target_palette is the colormap target structure. In this example my_target_palette contains 3 arrays of 256 bytes (b g r). */ LIBGGI_PAL(vis)->priv = _ggi_malloc(sizeof(my_target_palette)); } /* [...] */ return 0; } /* getPrivSize */ size_t GGI_my_target_getPrivSize(ggi_visual_t vis) { return sizeof(my_target_palette); } display/my_target/color.c:: #include "config.h" #include <ggi/internal/ggi-dl.h> #include <ggi/display/my_target.h> /* setPalette */ int GGI_my_target_setPalette(ggi_visual_t vis, size_t start, size_t size, const ggi_color *colormap) { ggi_fbdev_priv *priv = LIBGGI_PRIVATE(vis); my_target_palette *pal = (my_target_palette*)(LIBGGI_PAL(vis)->priv); DPRINT_COLOR("my_target setpalette.(%d,%d) %d\n", start,size,LIBGGI_PAL(vis)->clut.size); /* We will consider the target library contains a colormap initialisation function that takes a my_target_palette and two indices as arguments. First we'll update the ggi_colormap and our priv palette. */ memcpy(LIBGGI_PAL(vis)->clut.data+start, colormap, size*sizeof(ggi_color)); for(; size > 0; ++start, --size) { pal->b[start] = LIBGGI_PAL(vis)->clut.data[start].b >> 8; pal->g[start] = LIBGGI_PAL(vis)->clut.data[start].g >> 8; pal->r[start] = LIBGGI_PAL(vis)->clut.data[start].r >> 8; } /* Then we'll call the function provided by the target api that updates the colormap */ my_target_update_colormap(pal); return 0; } See Also -------- :man:`ggiSetPalette(3)`