Name
Overview — eCos Support for Framebuffer Devices
Description
        Framebuffer devices are the most common way for a computer system to
        display graphical output to users. There are immense variations in the
        implementations of such devices. CYGPKG_IO_FRAMEBUF
        provides an abstraction layer for use by application code and other
        packages. It defines an API for manipulating framebuffers, mapping
        this API on to functionality provided by the appropriate device
        driver. It also defines the interface which such device drivers should
        implement. For simple hardware it provides default implementations of
        much of this interface, greatly reducing the effort needed to write a
        device driver.
      
This package does not constitute a graphics library. It does not implement functionality like drawing text or arbitrary lines, let alone any kind of windowing system. Instead it operates at the lower level of individual pixels and blocks of pixels, in addition to control operations such as hardware initialization. Some applications may use the framebuffer API directly. Others will instead use a higher-level graphics library, and it is that library which uses the framebuffer API.
It is assumed that users are already familiar with the fundamentals of computer graphics, and no attempt is made here to explain terms like display depth, palette or pixel.
| ![[Note]](pix/note.png) | Note | 
|---|---|
| This package is work-in-progress. The support for 1bpp, 2bpp and 4bpp display depths is incomplete. For double-buffered displays the code does not yet maintain a bounding box of the updated parts of the display. The package has also been designed to allow for expansion with new functionality. | 
Configuration
        CYGPKG_IO_FRAMEBUF only contains
        hardware-independent code. It should be complemented by one or more
        framebuffer device drivers appropriate for the target platform. These
        drivers may be specific to the platform, or they may be more generic
        with platform-specific details such as the framebuffer memory base
        address provided by the platform HAL. When creating a configuration
        for a given target the device driver(s) will always be included
        automatically (assuming one has been written or ported). However by
        default this driver will be inactive and will not get built, so does
        not add any unnecessary size overhead for applications which do not
        require graphics. To activate the device driver
        CYGPKG_IO_FRAMEBUF must be added explicitly to the
        configuration, for example using
        ecosconfig add framebuf. After this the
        full framebuffer API will be available to other packages and to
        application code.
      
        This package contains very few configuration options. Instead it is
        left to device drivers or higher-level code to provide appropriate
        configurability. One option,
        CYGFUN_IO_FRAMEBUF_INSTALL_DEFAULT_PALETTE, relates
        to the initialization of paletted displays.
      
        There are a number of calculated and inferred configuration options
        and a number of interfaces. These provide information such as whether
        or not there is a backlight. The most important one is
        CYGDAT_IO_FRAMEBUF_DEVICES, which holds a list of
        framebuffer identifiers for use with the macro-based API. If there is a single
        framebuffer device driver which supports one display in either
        landscape or portrait mode, the configuration option may hold a value
        like  240x320x8 320x240x8r90.
      
Application Programmer Interfaces
Framebuffer devices require a difficult choice between flexibility and performance. On the one hand the API should be able to support multiple devices driving separate displays, or a single device operating in different modes at different times. On the other hand graphics tends to involve very large amounts of I/O: even something as simple as drawing a background image can involve setting many thousands of pixels. Efficiency requires avoiding all possible overheads including function calls. Instead the API should make extensive use of macros or inline functions. Ideally details of the framebuffer device such as the stride would be known constants at compile-time, giving the compiler as much opportunity as possible to optimize the code. Clearly this is difficult if multiple framebuffer devices are in use or if the device mode may get changed at run-time.
To meet the conflicting requirements the generic framebuffer package provides two APIs: a fast macro API which requires selecting a single framebuffer device at compile or configure time; and a slower function API without this limitation. The two are very similar, for example:
#include <cyg/io/framebuf.h>
void
clear_screen(cyg_fb* fb, cyg_fb_colour colour)
{
    cyg_fb_fill_block(fb, 0, 0,
                      fb->fb_width, fb->fb_height,
                      colour);
}or the equivalent macro version:
#include <cyg/io/framebuf.h>
#define FRAMEBUF 240x320x8
void
clear_screen(cyg_fb_colour colour)
{
    CYG_FB_FILL_BLOCK(FRAMEBUF, 0, 0,
                      CYG_FB_WIDTH(FRAMEBUF), CYG_FB_HEIGHT(FRAMEBUF),
                      colour);
}
        The function-based API works in terms of
        cyg_fb structures, containing all the
        information needed to manipulate the device. Each framebuffer device
        driver will export one or more of these structures, for example
        cyg_alaia_fb_240x320x8, and the driver
        documentation should list the variable names. The macro API works in
        terms of identifiers such as 240x320x8, and by a
        series of substitutions the main macro gets expanded to the
        appropriate device-specific code, usually inline. Again the device
        driver documentation should list the supported identifiers. In
        addition the configuration option
        CYGDAT_IO_FRAMEBUF_DEVICES will contain the full
        list. By convention the identifier will be specified by a
        #define'd symbol such as
        FRAMEBUF, or in the case of graphics libraries by a
        configuration option.
      
If a platform has multiple framebuffer devices connected to different displays then there will be separate cyg_fb structures and macro identifiers for each one. In addition some devices can operate in multiple modes. For example a PC VGA card can operate in a monochome 640x480 mode, an 8bpp 320x200 mode, and many other modes, but only one of these can be active at a time. The different modes are also represented by different cyg_fb structures and identifiers, effectively treating the modes as separate devices. It is the responsibility of higher-level code to ensure that only one mode is in use at a time.
        It is possible to use the macro API with more than one device,
        basically by compiling the code twice with different values of
        FRAMEBUF, taking appropriate care to avoid
        identifier name clashes. This gives the higher performance of the
        macros at the cost of increased code size.
      
        All of the framebuffer API, including exports of the device-specific
        cyg_fb structures, is available through a
        single header file <cyg/io/framebuf.h>. The
        API follows a number of conventions. Coordinates (0,0) correspond to
        the top-left corner of the display. All functions and macros which
        take a pair of coordinates have x first, y second. For block
        operations these coordinates are followed by width, then height.
        Coordinates and dimensions use cyg_ucount16 variables,
        which for any processor should be the most efficient unsigned data
        type with at least 16 bits - usually plain unsigned integers. Colours
        are identified by cyg_fb_colour variables, again usually
        unsigned integers.
      
        To allow for the different variants of the English language, the API
        allows for a number of alternate spellings. Colour and color can be
        used interchangeably, so there are data types
        cyg_fb_colour and cyg_fb_color, and
        functions cyg_fb_make_colour and
        cyg_fb_make_color. Similarly gray is accepted as
        a variant of grey so the predefined colours
        CYG_FB_DEFAULT_PALETTE_LIGHTGREY and
        CYG_FB_DEFAULT_PALETTE_LIGHTGRAY are equivalent.
      
The API is split into the following categories:
- parameters
- getting information about a given framebuffer device such as width, height and depth. Colours management is complicated so has its own category.
- control
- operations such as switching the display on and off, and more device-specific ones such as manipulating the backlight.
- colours
- determining the colour format (monochrome, paletted, …), manipulating the palette, or constructing true colours.
- drawing
- primitives for manipulating pixels and blocks of pixels.
- iteration
- efficiently iterating over blocks of pixels.
Thread Safety
The framebuffer API never performs any locking so is not thread-safe. Instead it assumes that higher-level code such as a graphics library performs any locking that may be needed. Adding a mutex lock and unlock around every drawing primitive, including pixel writes, would be prohibitively expensive.
It is also assumed that the framebuffer will only be updated from thread context. With most hardware it will also be possible to access a framebuffer from DSR or ISR context, but this should be avoided in portable code.
| 2025-10-02 | Open Publication License | 



