Name
Parameters — determining framebuffer capabilities
Synopsis
#include <cyg/io/framebuf.h> typedef struct cyg_fb { cyg_ucount16 fb_depth; cyg_ucount16 fb_format; cyg_ucount16 fb_width; cyg_ucount16 fb_height; #ifdef CYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT cyg_ucount16 fb_viewport_width; cyg_ucount16 fb_viewport_height; #endif void* fb_base; cyg_ucount16 fb_stride; cyg_uint32 fb_flags0; … } cyg_fb;
cyg_fb* CYG_FB_STRUCT(
FRAMEBUF
)
;
cyg_ucount16 CYG_FB_DEPTH(
FRAMEBUF
)
;
cyg_ucount16 CYG_FB_FORMAT(
FRAMEBUF
)
;
cyg_ucount16 CYG_FB_WIDTH(
FRAMEBUF
)
;
cyg_ucount16 CYG_FB_HEIGHT(
FRAMEBUF
)
;
cyg_ucount16 CYG_FB_VIEWPORT_WIDTH(
FRAMEBUF
)
;
cyg_ucount16 CYG_FB_VIEWPORT_HEIGHT(
FRAMEBUF
)
;
void* CYG_FB_BASE(
FRAMEBUF
)
;
cyg_ucount16 CYG_FB_STRIDE(
FRAMEBUF
)
;
cyg_uint32 CYG_FB_FLAGS0(
FRAMEBUF
)
;
Description
When developing an application for a specific platform the various framebuffer parameters such as width and height are known, and the code can be written accordingly. However when writing code that should work on many platforms with different framebuffer devices, for example a graphics library, the code must be able to get these parameters and adapt.
Code using the function API can extract the parameters from the cyg_fb structures at run-time. The macro API provides dedicated macros for each parameter. These do not follow the usual eCos convention where the result is provided via an extra argument. Instead the result is returned as normal, and is guaranteed to be a compile-time constant. This allows code like the following:
#if CYG_FB_DEPTH(FRAMEBUF) < 8 … #else … #endif
or alternatively:
if (CYG_FB_DEPTH(FRAMEBUF) < 8) { … } else { … }
or:
switch (CYG_FB_DEPTH(FRAMEBUF)) { case 1 : … break; case 2 : … break; case 4 : … break; case 8 : … break; case 16 : … break; case 32 : … break; }
In terms of the code actually generated by the compiler these approaches have much the same effect. The macros expand to a compile-time constant so unnecessary code can be easily eliminated.
The available parameters are as follows:
- depth
- The number of bits per pixel or bpp. The common depths are 1, 2, 4, 8, 16 and 32.
- format
- How the pixel values are mapped on to visible colours, for example true colour or paletted or greyscale.
- width, height
- The number of framebuffer pixels horizontally and vertically.
- viewport width, viewport height
With some devices the framebuffer height and/or width are greater than what the display can actually show. The display is said to offer a viewport into the larger framebuffer. The number of visible pixels is determined from the viewport width and height. The position of the viewport is controlled via an
ioctl
. Within a cyg_fb structure these fields are only present ifCYGHWR_IO_FRAMEBUF_FUNCTIONALITY_VIEWPORT
is defined, to avoid wasting data space on fields that are unnecessary for the current platform. For the macro API the viewport macros should only be used ifCYG_FB_FLAGS0_VIEWPORT
is set for the framebuffer:#if (CYG_FB_FLAGS0(FRAMEBUF) & CYG_FB_FLAGS0_VIEWPORT) … #endif
- base, stride
- For linear framebuffers these parameters provide the information needed to access framebuffer memory. The stride is in bytes.
- flags0
This gives further information about the hardware capabilities. Some of this overlaps with other parameters, especially when it comes to colour, because it is often easier to test for a single flag than for a range of colour modes. The current flags are:
-
CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER
- Framebuffer memory is organized in a conventional fashion and can be accessed directly by higher-level code using the base and stride parameters.
-
CYG_FB_FLAGS0_LE
- This flag is only relevant for 1bpp, 2bpp and 4bpp devices and controls how the pixels are organized within each byte. If the flag is set then the layout is little-endian: for a 1bpp device pixel (0,0) occupies bit 0 of the first byte of framebuffer memory. The more common layout is big-endian where pixel (0,0) occupies bit 7 of the first byte.
-
CYG_FB_FLAGS0_TRUE_COLOUR
- The framebuffer uses a true colour format where the value of each pixel directly encodes the red, green and blue intensities. This is common for 16bpp and 32bpp devices, and is occasionally used for 8bpp devices.
-
CYG_FB_FLAGS0_PALETTE
- The framebuffer uses a palette. A pixel value does not directly encode the colours, but instead acts as an index into a separate table of colour values. That table may be read-only or read-write. Paletted displays are common for 8bpp and some 4bpp displays.
-
CYG_FB_FLAGS0_WRITEABLE_PALETTE
- The palette is read-write.
-
CYG_FB_FLAGS0_DELAYED_PALETTE_UPDATE
-
Palette updates can be synchronized to a vertical blank, in other
words a brief time period when the display is not being updated,
by using
CYG_FB_UPDATE_VERTICAL_RETRACE
as the last argument tocyg_fb_write_palette
orCYG_FB_WRITE_PALETTE
. With some hardware updating the palette in the middle of a screen update may result in visual noise. -
CYG_FB_FLAGS0_VIEWPORT
-
The framebuffer contains more pixels than can be shown on the display.
Instead the display provides a viewport into the framebuffer. An
ioctl
can be used to move the viewport. -
CYG_FB_FLAGS0_DOUBLE_BUFFER
- The display does not show the current contents of the framebuffer, so the results of drawing into the framebuffer are not immediately visible. Instead higher-level code needs to perform an explicit synch operation to update the display.
-
CYG_FB_FLAGS0_PAGE_FLIPPING
-
The hardware supports two or more pages, each of width*height pixels,
only one of which is visible on the display. This allows higher-level
code to update one page without disturbing what is currently visible.
An
ioctl
is used to switch the visible page. -
CYG_FB_FLAGS0_BLANK
- The display can be blanked without affecting the framebuffer contents or settings.
-
CYG_FB_FLAGS0_BACKLIGHT
- There is a backlight which can be switched on or off. Some hardware provides finer-grained control over the backlight intensity.
-
CYG_FB_FLAGS0_MUST_BE_ON
-
Often it is desirable to perform some initialization such as clearing
the screen or setting the palette before the display is switched on, to avoid visual
noise. However not all hardware allows this. If this flag is set then
it is possible to access framebuffer memory and the palette before the
cyg_fb_on
orCYG_FB_ON
operation. It may also be possible to perform some other operations such as activating the backlight, but that is implementation-defined.
-
To allow for future expansion there are also flags1, flags2, and
flags3 fields. These may get used for encoding additional
ioctl
functionality, support for hardware
acceleration, and similar features.
Linear Framebuffers
There are drawing primitives for writing and reading individual pixels. However these involve a certain amount of arithmetic each time to get from a position to an address within the frame buffer, plus function call overhead if the function API is used, and this will slow down graphics operations.
When the framebuffer device is known at compile-time and the macro API is used then there are additional macros specifically for iterating over parts of the frame buffer. These should prove very efficient for many graphics operations. However if the device is selected at run-time then the macros are not appropriate and code may want to manipulate framebuffer memory directly. This is possible if two conditions are satisfied:
-
The
CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER
flag must be set. Otherwise framebuffer memory is either not directly accessible or has a non-linear layout. -
The
CYG_FB_FLAGS0_DOUBLE_BUFFER
flag must be clear. An efficient double buffer synch operation requires knowing what part of the framebuffer have been updated, and the various drawing primitives will keep track of this. If higher-level code then starts manipulating the framebuffer directly the synch operation may perform only a partial update.
The base, stride, depth, width and height parameters, plus the
CYG_FB_FLAGS0_LE
flag for 1bpp, 2bpp and 4bpp
devices, provide all the information needed to access framebuffer
memory. A linear framebuffer has pixel (0,0) at the base address.
Incrementing y means adding stride bytes to the pointer.
The base and stride parameters may be set even if
CYG_FB_FLAGS0_LINEAR_FRAMEBUFFER
is clear. This can
be useful if for example the display is rotated in software from
landscape to portrait mode. However the meaning of these parameters
for non-linear framebuffers is implementation-defined.
2024-03-18 | Open Publication License |